@thoughtspot/visual-embed-sdk 1.28.3 → 1.28.5-alpha-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/cjs/package.json +2 -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 +1 -1
- package/cjs/src/authToken.d.ts.map +1 -1
- package/cjs/src/authToken.js +9 -2
- package/cjs/src/authToken.js.map +1 -1
- package/cjs/src/embed/app.d.ts +50 -6
- package/cjs/src/embed/app.d.ts.map +1 -1
- package/cjs/src/embed/app.js +9 -3
- package/cjs/src/embed/app.js.map +1 -1
- package/cjs/src/embed/app.spec.js +10 -0
- package/cjs/src/embed/app.spec.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 +24 -2
- package/cjs/src/embed/liveboard.d.ts.map +1 -1
- package/cjs/src/embed/liveboard.js +8 -3
- package/cjs/src/embed/liveboard.js.map +1 -1
- package/cjs/src/embed/liveboard.spec.js +61 -4
- package/cjs/src/embed/liveboard.spec.js.map +1 -1
- package/cjs/src/embed/sage.d.ts +4 -4
- package/cjs/src/embed/sage.d.ts.map +1 -1
- package/cjs/src/embed/sage.js +2 -18
- package/cjs/src/embed/sage.js.map +1 -1
- package/cjs/src/embed/sage.spec.js +20 -31
- package/cjs/src/embed/sage.spec.js.map +1 -1
- package/cjs/src/embed/search.d.ts +33 -5
- package/cjs/src/embed/search.d.ts.map +1 -1
- package/cjs/src/embed/search.js +6 -4
- package/cjs/src/embed/search.js.map +1 -1
- package/cjs/src/embed/search.spec.js +2 -1
- package/cjs/src/embed/search.spec.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 +15 -6
- package/cjs/src/embed/ts-embed.js.map +1 -1
- package/cjs/src/embed/ts-embed.spec.js +27 -18
- package/cjs/src/embed/ts-embed.spec.js.map +1 -1
- package/cjs/src/errors.js +1 -1
- package/cjs/src/errors.js.map +1 -1
- package/cjs/src/react/index.spec.js +1 -13
- package/cjs/src/react/index.spec.js.map +1 -1
- package/cjs/src/types.d.ts +114 -15
- package/cjs/src/types.d.ts.map +1 -1
- package/cjs/src/types.js +68 -7
- package/cjs/src/types.js.map +1 -1
- package/cjs/src/utils/authService/tokenizedAuthService.spec.d.ts +2 -0
- package/cjs/src/utils/authService/tokenizedAuthService.spec.d.ts.map +1 -0
- package/cjs/src/utils/authService/tokenizedAuthService.spec.js +32 -0
- package/cjs/src/utils/authService/tokenizedAuthService.spec.js.map +1 -0
- package/cjs/src/utils/sessionInfoService.d.ts +66 -0
- package/cjs/src/utils/sessionInfoService.d.ts.map +1 -0
- package/cjs/src/utils/sessionInfoService.js +92 -0
- package/cjs/src/utils/sessionInfoService.js.map +1 -0
- package/dist/src/auth.d.ts.map +1 -1
- package/dist/src/authToken.d.ts +1 -1
- package/dist/src/authToken.d.ts.map +1 -1
- package/dist/src/embed/app.d.ts +50 -6
- 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 +24 -2
- package/dist/src/embed/liveboard.d.ts.map +1 -1
- package/dist/src/embed/sage.d.ts +4 -4
- package/dist/src/embed/sage.d.ts.map +1 -1
- package/dist/src/embed/search.d.ts +33 -5
- 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/types.d.ts +114 -15
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/authService/tokenizedAuthService.spec.d.ts +2 -0
- package/dist/src/utils/authService/tokenizedAuthService.spec.d.ts.map +1 -0
- package/dist/src/utils/sessionInfoService.d.ts +66 -0
- package/dist/src/utils/sessionInfoService.d.ts.map +1 -0
- package/dist/tsembed-react.es.js +1764 -1691
- package/dist/tsembed-react.js +7024 -6951
- package/dist/tsembed.es.js +7275 -7202
- package/dist/tsembed.js +15449 -15376
- package/dist/visual-embed-sdk-react-full.d.ts +223 -30
- package/dist/visual-embed-sdk-react.d.ts +223 -30
- package/dist/visual-embed-sdk.d.ts +223 -30
- package/lib/package.json +2 -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 +1 -1
- package/lib/src/authToken.d.ts.map +1 -1
- package/lib/src/authToken.js +9 -2
- package/lib/src/authToken.js.map +1 -1
- package/lib/src/embed/app.d.ts +50 -6
- package/lib/src/embed/app.d.ts.map +1 -1
- package/lib/src/embed/app.js +9 -3
- package/lib/src/embed/app.js.map +1 -1
- package/lib/src/embed/app.spec.js +10 -0
- package/lib/src/embed/app.spec.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 +24 -2
- package/lib/src/embed/liveboard.d.ts.map +1 -1
- package/lib/src/embed/liveboard.js +9 -4
- package/lib/src/embed/liveboard.js.map +1 -1
- package/lib/src/embed/liveboard.spec.js +61 -4
- package/lib/src/embed/liveboard.spec.js.map +1 -1
- package/lib/src/embed/sage.d.ts +4 -4
- package/lib/src/embed/sage.d.ts.map +1 -1
- package/lib/src/embed/sage.js +2 -18
- package/lib/src/embed/sage.js.map +1 -1
- package/lib/src/embed/sage.spec.js +20 -31
- package/lib/src/embed/sage.spec.js.map +1 -1
- package/lib/src/embed/search.d.ts +33 -5
- package/lib/src/embed/search.d.ts.map +1 -1
- package/lib/src/embed/search.js +7 -5
- package/lib/src/embed/search.js.map +1 -1
- package/lib/src/embed/search.spec.js +2 -1
- package/lib/src/embed/search.spec.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 +18 -9
- package/lib/src/embed/ts-embed.js.map +1 -1
- package/lib/src/embed/ts-embed.spec.js +27 -18
- package/lib/src/embed/ts-embed.spec.js.map +1 -1
- package/lib/src/errors.js +1 -1
- package/lib/src/errors.js.map +1 -1
- package/lib/src/react/index.spec.js +1 -13
- package/lib/src/react/index.spec.js.map +1 -1
- package/lib/src/types.d.ts +114 -15
- package/lib/src/types.d.ts.map +1 -1
- package/lib/src/types.js +68 -7
- 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/utils/authService/tokenizedAuthService.spec.d.ts +2 -0
- package/lib/src/utils/authService/tokenizedAuthService.spec.d.ts.map +1 -0
- package/lib/src/utils/authService/tokenizedAuthService.spec.js +29 -0
- package/lib/src/utils/authService/tokenizedAuthService.spec.js.map +1 -0
- package/lib/src/utils/sessionInfoService.d.ts +66 -0
- package/lib/src/utils/sessionInfoService.d.ts.map +1 -0
- package/lib/src/utils/sessionInfoService.js +85 -0
- package/lib/src/utils/sessionInfoService.js.map +1 -0
- package/lib/src/visual-embed-sdk.d.ts +228 -35
- package/package.json +2 -1
- package/src/auth.ts +6 -6
- package/src/authToken.ts +9 -2
- package/src/embed/app.spec.ts +15 -0
- package/src/embed/app.ts +67 -8
- package/src/embed/base.spec.ts +3 -3
- package/src/embed/base.ts +14 -14
- package/src/embed/liveboard.spec.ts +82 -9
- package/src/embed/liveboard.ts +42 -5
- package/src/embed/sage.spec.ts +20 -35
- package/src/embed/sage.ts +4 -21
- package/src/embed/search.spec.ts +2 -1
- package/src/embed/search.ts +45 -10
- package/src/embed/ts-embed.spec.ts +48 -34
- package/src/embed/ts-embed.ts +52 -39
- package/src/errors.ts +1 -1
- package/src/react/index.spec.tsx +1 -30
- package/src/types.ts +114 -15
- package/src/utils/authService/authService.spec.ts +4 -4
package/dist/tsembed-react.es.js
CHANGED
|
@@ -564,7 +564,6 @@ var AuthType;
|
|
|
564
564
|
* .then((data) => data.token);
|
|
565
565
|
* }
|
|
566
566
|
* });
|
|
567
|
-
* });
|
|
568
567
|
* ```
|
|
569
568
|
*/
|
|
570
569
|
AuthType["TrustedAuthToken"] = "AuthServer";
|
|
@@ -939,8 +938,7 @@ var EmbedEvent;
|
|
|
939
938
|
*
|
|
940
939
|
* API - API call failure error.
|
|
941
940
|
*
|
|
942
|
-
* FULLSCREEN - Error when presenting a Liveboard or visualization in full screen
|
|
943
|
-
* mode.
|
|
941
|
+
* FULLSCREEN - Error when presenting a Liveboard or visualization in full screen mode.
|
|
944
942
|
*
|
|
945
943
|
* SINGLE_VALUE_FILTER - Error due to multiple values in the single value filter.
|
|
946
944
|
*
|
|
@@ -2589,6 +2587,13 @@ var Param;
|
|
|
2589
2587
|
Param["ClientLogLevel"] = "clientLogLevel";
|
|
2590
2588
|
Param["OverrideNativeConsole"] = "overrideConsoleLogs";
|
|
2591
2589
|
Param["enableAskSage"] = "enableAskSage";
|
|
2590
|
+
Param["CollapseSearchBarInitially"] = "collapseSearchBarInitially";
|
|
2591
|
+
Param["EnableCustomColumnGroups"] = "enableCustomColumnGroups";
|
|
2592
|
+
Param["DateFormatLocale"] = "dateFormatLocale";
|
|
2593
|
+
Param["NumberFormatLocale"] = "numberFormatLocale";
|
|
2594
|
+
Param["CurrencyFormat"] = "currencyFormat";
|
|
2595
|
+
Param["Enable2ColumnLayout"] = "enable2ColumnLayout";
|
|
2596
|
+
Param["IsFullAppEmbed"] = "isFullAppEmbed";
|
|
2592
2597
|
})(Param || (Param = {}));
|
|
2593
2598
|
/**
|
|
2594
2599
|
* ThoughtSpot application pages include actions and menu commands
|
|
@@ -2726,6 +2731,18 @@ var Action;
|
|
|
2726
2731
|
* ```
|
|
2727
2732
|
*/
|
|
2728
2733
|
Action["AddFilter"] = "addFilter";
|
|
2734
|
+
/**
|
|
2735
|
+
* The **Add Data Panel Objects** action on the data panel v2.
|
|
2736
|
+
* Allows to show action menu to add different objects (like
|
|
2737
|
+
* formulas, parameters) in data panel v2.
|
|
2738
|
+
*
|
|
2739
|
+
* @example
|
|
2740
|
+
* ```js
|
|
2741
|
+
* disabledActions: [Action.AddDataPanelObjects]
|
|
2742
|
+
* ```
|
|
2743
|
+
* @version SDK: 1.32.0 | Thoughtspot: 10.0.0.cl
|
|
2744
|
+
*/
|
|
2745
|
+
Action["AddDataPanelObjects"] = "addDataPanelObjects";
|
|
2729
2746
|
/**
|
|
2730
2747
|
* Filter configuration options on a Liveboard and Search page.
|
|
2731
2748
|
* Allows configuring filter options when adding filters to a
|
|
@@ -2768,6 +2785,28 @@ var Action;
|
|
|
2768
2785
|
* ```
|
|
2769
2786
|
*/
|
|
2770
2787
|
Action["AddParameter"] = "addParameter";
|
|
2788
|
+
/**
|
|
2789
|
+
* The **Add Column Set** action on a Answer.
|
|
2790
|
+
* Allows adding column sets to a Answer.
|
|
2791
|
+
*
|
|
2792
|
+
* @example
|
|
2793
|
+
* ```js
|
|
2794
|
+
* disabledActions: [Action.AddColumnSet]
|
|
2795
|
+
* ```
|
|
2796
|
+
* @version SDK: 1.32.0 | Thoughtspot: 10.0.0.cl
|
|
2797
|
+
*/
|
|
2798
|
+
Action["AddColumnSet"] = "addSimpleCohort";
|
|
2799
|
+
/**
|
|
2800
|
+
* The **Add Query Set** action on a Answer.
|
|
2801
|
+
* Allows adding query sets to a Answer.
|
|
2802
|
+
*
|
|
2803
|
+
* @example
|
|
2804
|
+
* ```js
|
|
2805
|
+
* disabledActions: [Action.AddQuerySet]
|
|
2806
|
+
* ```
|
|
2807
|
+
* @version SDK: 1.32.0 | Thoughtspot: 10.0.0.cl
|
|
2808
|
+
*/
|
|
2809
|
+
Action["AddQuerySet"] = "addAdvancedCohort";
|
|
2771
2810
|
/**
|
|
2772
2811
|
* @hidden
|
|
2773
2812
|
*/
|
|
@@ -3199,6 +3238,28 @@ var Action;
|
|
|
3199
3238
|
* @version SDK: 1.21.0 | ThoughtSpot: 9.2.0.cl
|
|
3200
3239
|
*/
|
|
3201
3240
|
Action["CrossFilter"] = "context-menu-item-cross-filter";
|
|
3241
|
+
/**
|
|
3242
|
+
* The **Sync to Slack** action on Liveboard visualizations.
|
|
3243
|
+
* Allows sending data to third-party apps Slack
|
|
3244
|
+
*
|
|
3245
|
+
* @example
|
|
3246
|
+
* ```js
|
|
3247
|
+
* disabledActions: [Action.SyncToSlack]
|
|
3248
|
+
* ```
|
|
3249
|
+
* @version @version SDK : 1.32.0 | Thoughtspot: 10.1.0.cl
|
|
3250
|
+
*/
|
|
3251
|
+
Action["SyncToSlack"] = "syncToSlack";
|
|
3252
|
+
/**
|
|
3253
|
+
* The **Sync to Teams** action on Liveboard visualizations.
|
|
3254
|
+
* Allows sending data to third-party apps Team
|
|
3255
|
+
*
|
|
3256
|
+
* @example
|
|
3257
|
+
* ```js
|
|
3258
|
+
* disabledActions: [Action.SyncToTeams]
|
|
3259
|
+
* ```
|
|
3260
|
+
* @version @version SDK : 1.32.0 | Thoughtspot: 10.1.0.cl
|
|
3261
|
+
*/
|
|
3262
|
+
Action["SyncToTeams"] = "syncToTeams";
|
|
3202
3263
|
/**
|
|
3203
3264
|
* The **Remove** action that appears when cross filters are applied
|
|
3204
3265
|
* on a Liveboard.
|
|
@@ -3501,15 +3562,15 @@ var Action;
|
|
|
3501
3562
|
*/
|
|
3502
3563
|
Action["RemoveFromWatchlist"] = "removeFromWatchlist";
|
|
3503
3564
|
/**
|
|
3504
|
-
* The **
|
|
3565
|
+
* The **Organise Favourites** action on Homepage Favourite Module.
|
|
3505
3566
|
*
|
|
3506
3567
|
* @example
|
|
3507
3568
|
* ```js
|
|
3508
|
-
* disabledActions: [Action.
|
|
3569
|
+
* disabledActions: [Action.OrganiseFavourites]
|
|
3509
3570
|
* ```
|
|
3510
|
-
* @version SDK : 1.
|
|
3571
|
+
* @version SDK : 1.32.0 | Thoughtspot: 10.0.0.cl
|
|
3511
3572
|
*/
|
|
3512
|
-
Action["
|
|
3573
|
+
Action["OrganiseFavourites"] = "organiseFavourites";
|
|
3513
3574
|
/**
|
|
3514
3575
|
* Action ID for AI Highlights button
|
|
3515
3576
|
*
|
|
@@ -5823,8 +5884,6 @@ function isEqual(value, other) {
|
|
|
5823
5884
|
|
|
5824
5885
|
var isEqual_1 = isEqual;
|
|
5825
5886
|
|
|
5826
|
-
var name="@thoughtspot/visual-embed-sdk";var version="1.28.3";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={".":{"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,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};
|
|
5827
|
-
|
|
5828
5887
|
/**
|
|
5829
5888
|
* Checks if `value` is `undefined`.
|
|
5830
5889
|
*
|
|
@@ -6052,7 +6111,9 @@ const INVALID_TOKEN_ERR = 'Invalid token received form token callback or authTok
|
|
|
6052
6111
|
let cachedAuthToken = null;
|
|
6053
6112
|
// This method can be used to get the authToken using the embedConfig
|
|
6054
6113
|
const getAuthenticationToken = async (embedConfig) => {
|
|
6055
|
-
if
|
|
6114
|
+
// Since we don't have token validation enabled , we cannot tell if the
|
|
6115
|
+
// cached token is valid or not. So we will always fetch a new token.
|
|
6116
|
+
if (cachedAuthToken && !embedConfig.disableTokenVerification) {
|
|
6056
6117
|
let isCachedTokenStillValid;
|
|
6057
6118
|
try {
|
|
6058
6119
|
isCachedTokenStillValid = await validateAuthToken(embedConfig, cachedAuthToken, true);
|
|
@@ -6078,6 +6139,10 @@ const getAuthenticationToken = async (embedConfig) => {
|
|
|
6078
6139
|
return authToken;
|
|
6079
6140
|
};
|
|
6080
6141
|
const validateAuthToken = async (embedConfig, authToken, suppressAlert) => {
|
|
6142
|
+
if (embedConfig.disableTokenVerification) {
|
|
6143
|
+
logger.info('Token verification is disabled. Assuming token is valid.');
|
|
6144
|
+
return true;
|
|
6145
|
+
}
|
|
6081
6146
|
try {
|
|
6082
6147
|
const isTokenValid = await verifyTokenService(embedConfig.thoughtSpotHost, authToken);
|
|
6083
6148
|
if (isTokenValid)
|
|
@@ -6104,383 +6169,924 @@ const validateAuthToken = async (embedConfig, authToken, suppressAlert) => {
|
|
|
6104
6169
|
* ```js
|
|
6105
6170
|
* resetCachedAuthToken();
|
|
6106
6171
|
* ```
|
|
6107
|
-
* @version SDK: 1.28.
|
|
6172
|
+
* @version SDK: 1.28.0 | ThoughtSpot: *
|
|
6108
6173
|
* @group Authentication / Init
|
|
6109
6174
|
*/
|
|
6110
6175
|
const resetCachedAuthToken = () => {
|
|
6111
6176
|
cachedAuthToken = null;
|
|
6112
6177
|
};
|
|
6113
6178
|
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6179
|
+
let config = {};
|
|
6180
|
+
/**
|
|
6181
|
+
* Gets the configuration embed was initialized with.
|
|
6182
|
+
*
|
|
6183
|
+
* @returns {@link EmbedConfig} The configuration embed was initialized with.
|
|
6184
|
+
* @version SDK: 1.19.0 | ThoughtSpot: *
|
|
6185
|
+
* @group Global methods
|
|
6186
|
+
*/
|
|
6187
|
+
const getEmbedConfig = () => config;
|
|
6188
|
+
|
|
6189
|
+
/**
|
|
6190
|
+
* Fetch wrapper that adds the authentication token to the request.
|
|
6191
|
+
* Use this to call the ThoughtSpot APIs when using the visual embed sdk.
|
|
6192
|
+
*
|
|
6193
|
+
* @param input
|
|
6194
|
+
* @param init
|
|
6195
|
+
* @version SDK: 1.28.0
|
|
6196
|
+
* @group Global methods
|
|
6197
|
+
*/
|
|
6198
|
+
const tokenizedFetch = async (input, init) => {
|
|
6199
|
+
const embedConfig = getEmbedConfig();
|
|
6200
|
+
if (embedConfig.authType !== AuthType.TrustedAuthTokenCookieless) {
|
|
6201
|
+
return fetch(input, init);
|
|
6202
|
+
}
|
|
6203
|
+
const req = new Request(input, init);
|
|
6204
|
+
const authToken = await getAuthenticationToken(embedConfig);
|
|
6205
|
+
if (authToken) {
|
|
6206
|
+
req.headers.append('Authorization', `Bearer ${authToken}`);
|
|
6207
|
+
}
|
|
6208
|
+
return fetch(req);
|
|
6117
6209
|
};
|
|
6118
6210
|
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
}
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6211
|
+
/**
|
|
6212
|
+
*
|
|
6213
|
+
* @param root0
|
|
6214
|
+
* @param root0.query
|
|
6215
|
+
* @param root0.variables
|
|
6216
|
+
* @param root0.thoughtSpotHost
|
|
6217
|
+
* @param root0.isCompositeQuery
|
|
6218
|
+
*/
|
|
6219
|
+
async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
|
|
6220
|
+
const operationName = getOperationNameFromQuery(query);
|
|
6221
|
+
try {
|
|
6222
|
+
const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
|
|
6223
|
+
method: 'POST',
|
|
6224
|
+
headers: {
|
|
6225
|
+
'content-type': 'application/json;charset=UTF-8',
|
|
6226
|
+
'x-requested-by': 'ThoughtSpot',
|
|
6227
|
+
accept: '*/*',
|
|
6228
|
+
'accept-language': 'en-us',
|
|
6229
|
+
},
|
|
6230
|
+
body: JSON.stringify({
|
|
6231
|
+
operationName,
|
|
6232
|
+
query,
|
|
6233
|
+
variables,
|
|
6234
|
+
}),
|
|
6235
|
+
credentials: 'include',
|
|
6236
|
+
});
|
|
6237
|
+
const result = await response.json();
|
|
6238
|
+
const dataValues = Object.values(result.data);
|
|
6239
|
+
return (isCompositeQuery) ? result.data : dataValues[0];
|
|
6240
|
+
}
|
|
6241
|
+
catch (error) {
|
|
6242
|
+
return error;
|
|
6243
|
+
}
|
|
6136
6244
|
}
|
|
6137
6245
|
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6246
|
+
const getSourceDetailQuery = `
|
|
6247
|
+
query GetSourceDetail($ids: [GUID!]!) {
|
|
6248
|
+
getSourceDetailById(ids: $ids, type: LOGICAL_TABLE) {
|
|
6249
|
+
id
|
|
6250
|
+
name
|
|
6251
|
+
description
|
|
6252
|
+
authorName
|
|
6253
|
+
authorDisplayName
|
|
6254
|
+
isExternal
|
|
6255
|
+
type
|
|
6256
|
+
created
|
|
6257
|
+
modified
|
|
6258
|
+
columns {
|
|
6259
|
+
id
|
|
6260
|
+
name
|
|
6261
|
+
author
|
|
6262
|
+
authorDisplayName
|
|
6263
|
+
description
|
|
6264
|
+
dataType
|
|
6265
|
+
type
|
|
6266
|
+
modified
|
|
6267
|
+
ownerName
|
|
6268
|
+
owner
|
|
6269
|
+
dataRecency
|
|
6270
|
+
sources {
|
|
6271
|
+
tableId
|
|
6272
|
+
tableName
|
|
6273
|
+
columnId
|
|
6274
|
+
columnName
|
|
6275
|
+
__typename
|
|
6276
|
+
}
|
|
6277
|
+
synonyms
|
|
6278
|
+
cohortAnswerId
|
|
6279
|
+
__typename
|
|
6280
|
+
}
|
|
6281
|
+
relationships
|
|
6282
|
+
destinationRelationships
|
|
6283
|
+
dataSourceId
|
|
6284
|
+
__typename
|
|
6285
|
+
}
|
|
6286
|
+
}
|
|
6287
|
+
`;
|
|
6288
|
+
const sourceDetailCache = new Map();
|
|
6289
|
+
/**
|
|
6290
|
+
*
|
|
6291
|
+
* @param thoughtSpotHost
|
|
6292
|
+
* @param sourceId
|
|
6293
|
+
*/
|
|
6294
|
+
async function getSourceDetail(thoughtSpotHost, sourceId) {
|
|
6295
|
+
if (sourceDetailCache.get(sourceId)) {
|
|
6296
|
+
return sourceDetailCache.get(sourceId);
|
|
6297
|
+
}
|
|
6298
|
+
const details = await graphqlQuery({
|
|
6299
|
+
query: getSourceDetailQuery,
|
|
6300
|
+
variables: {
|
|
6301
|
+
ids: [sourceId],
|
|
6302
|
+
},
|
|
6303
|
+
thoughtSpotHost,
|
|
6304
|
+
});
|
|
6305
|
+
const souceDetails = details[0];
|
|
6306
|
+
if (souceDetails) {
|
|
6307
|
+
sourceDetailCache.set(sourceId, souceDetails);
|
|
6308
|
+
}
|
|
6309
|
+
return souceDetails;
|
|
6310
|
+
}
|
|
6142
6311
|
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
var navigator = window$1.navigator;
|
|
6151
|
-
var document$1 = window$1.document;
|
|
6152
|
-
var windowOpera = window$1.opera;
|
|
6153
|
-
var screen = window$1.screen;
|
|
6154
|
-
var userAgent = navigator.userAgent;
|
|
6155
|
-
var nativeBind = FuncProto.bind;
|
|
6156
|
-
var nativeForEach = ArrayProto.forEach;
|
|
6157
|
-
var nativeIndexOf = ArrayProto.indexOf;
|
|
6158
|
-
var nativeMap = ArrayProto.map;
|
|
6159
|
-
var nativeIsArray = Array.isArray;
|
|
6160
|
-
var breaker = {};
|
|
6161
|
-
var _ = {
|
|
6162
|
-
trim: function(str) {
|
|
6163
|
-
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
|
|
6164
|
-
return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
|
|
6312
|
+
const bachSessionId = `
|
|
6313
|
+
id {
|
|
6314
|
+
sessionId
|
|
6315
|
+
genNo
|
|
6316
|
+
acSession {
|
|
6317
|
+
sessionId
|
|
6318
|
+
genNo
|
|
6165
6319
|
}
|
|
6166
|
-
}
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6320
|
+
}
|
|
6321
|
+
`;
|
|
6322
|
+
const getUnaggregatedAnswerSession = `
|
|
6323
|
+
mutation GetUnAggregatedAnswerSession($session: BachSessionIdInput!, $columns: [UserPointSelectionInput!]!) {
|
|
6324
|
+
Answer__getUnaggregatedAnswer(session: $session, columns: $columns) {
|
|
6325
|
+
${bachSessionId}
|
|
6326
|
+
answer {
|
|
6327
|
+
visualizations {
|
|
6328
|
+
... on TableViz {
|
|
6329
|
+
columns {
|
|
6330
|
+
column {
|
|
6331
|
+
id
|
|
6332
|
+
name
|
|
6333
|
+
referencedColumns {
|
|
6334
|
+
guid
|
|
6335
|
+
displayName
|
|
6336
|
+
}
|
|
6337
|
+
}
|
|
6338
|
+
}
|
|
6339
|
+
}
|
|
6179
6340
|
}
|
|
6180
6341
|
}
|
|
6181
|
-
},
|
|
6182
|
-
/** @type {function(...*)} */
|
|
6183
|
-
warn: function() {
|
|
6184
|
-
if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
|
|
6185
|
-
var args = ['Mixpanel warning:'].concat(_.toArray(arguments));
|
|
6186
|
-
try {
|
|
6187
|
-
windowConsole.warn.apply(windowConsole, args);
|
|
6188
|
-
} catch (err) {
|
|
6189
|
-
_.each(args, function(arg) {
|
|
6190
|
-
windowConsole.warn(arg);
|
|
6191
|
-
});
|
|
6192
|
-
}
|
|
6193
|
-
}
|
|
6194
|
-
},
|
|
6195
|
-
/** @type {function(...*)} */
|
|
6196
|
-
error: function() {
|
|
6197
|
-
if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
|
|
6198
|
-
var args = ['Mixpanel error:'].concat(_.toArray(arguments));
|
|
6199
|
-
try {
|
|
6200
|
-
windowConsole.error.apply(windowConsole, args);
|
|
6201
|
-
} catch (err) {
|
|
6202
|
-
_.each(args, function(arg) {
|
|
6203
|
-
windowConsole.error(arg);
|
|
6204
|
-
});
|
|
6205
|
-
}
|
|
6206
|
-
}
|
|
6207
|
-
},
|
|
6208
|
-
/** @type {function(...*)} */
|
|
6209
|
-
critical: function() {
|
|
6210
|
-
if (!_.isUndefined(windowConsole) && windowConsole) {
|
|
6211
|
-
var args = ['Mixpanel error:'].concat(_.toArray(arguments));
|
|
6212
|
-
try {
|
|
6213
|
-
windowConsole.error.apply(windowConsole, args);
|
|
6214
|
-
} catch (err) {
|
|
6215
|
-
_.each(args, function(arg) {
|
|
6216
|
-
windowConsole.error(arg);
|
|
6217
|
-
});
|
|
6218
|
-
}
|
|
6219
|
-
}
|
|
6220
|
-
}
|
|
6221
|
-
};
|
|
6222
|
-
|
|
6223
|
-
var log_func_with_prefix = function(func, prefix) {
|
|
6224
|
-
return function() {
|
|
6225
|
-
arguments[0] = '[' + prefix + '] ' + arguments[0];
|
|
6226
|
-
return func.apply(console$1, arguments);
|
|
6227
|
-
};
|
|
6228
|
-
};
|
|
6229
|
-
var console_with_prefix = function(prefix) {
|
|
6230
|
-
return {
|
|
6231
|
-
log: log_func_with_prefix(console$1.log, prefix),
|
|
6232
|
-
error: log_func_with_prefix(console$1.error, prefix),
|
|
6233
|
-
critical: log_func_with_prefix(console$1.critical, prefix)
|
|
6234
|
-
};
|
|
6235
|
-
};
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
// UNDERSCORE
|
|
6239
|
-
// Embed part of the Underscore Library
|
|
6240
|
-
_.bind = function(func, context) {
|
|
6241
|
-
var args, bound;
|
|
6242
|
-
if (nativeBind && func.bind === nativeBind) {
|
|
6243
|
-
return nativeBind.apply(func, slice.call(arguments, 1));
|
|
6244
6342
|
}
|
|
6245
|
-
|
|
6246
|
-
|
|
6343
|
+
}
|
|
6344
|
+
`;
|
|
6345
|
+
const removeColumns = `
|
|
6346
|
+
mutation RemoveColumns($session: BachSessionIdInput!, $logicalColumnIds: [GUID!], $columnIds: [GUID!]) {
|
|
6347
|
+
Answer__removeColumns(
|
|
6348
|
+
session: $session
|
|
6349
|
+
logicalColumnIds: $logicalColumnIds
|
|
6350
|
+
columnIds: $columnIds
|
|
6351
|
+
) {
|
|
6352
|
+
${bachSessionId}
|
|
6247
6353
|
}
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
ctor.prototype = func.prototype;
|
|
6255
|
-
var self = new ctor();
|
|
6256
|
-
ctor.prototype = null;
|
|
6257
|
-
var result = func.apply(self, args.concat(slice.call(arguments)));
|
|
6258
|
-
if (Object(result) === result) {
|
|
6259
|
-
return result;
|
|
6354
|
+
}
|
|
6355
|
+
`;
|
|
6356
|
+
const addColumns = `
|
|
6357
|
+
mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
|
|
6358
|
+
Answer__addColumn(session: $session, columns: $columns) {
|
|
6359
|
+
${bachSessionId}
|
|
6260
6360
|
}
|
|
6261
|
-
return self;
|
|
6262
|
-
};
|
|
6263
|
-
return bound;
|
|
6264
|
-
};
|
|
6265
|
-
|
|
6266
|
-
/**
|
|
6267
|
-
* @param {*=} obj
|
|
6268
|
-
* @param {function(...*)=} iterator
|
|
6269
|
-
* @param {Object=} context
|
|
6270
|
-
*/
|
|
6271
|
-
_.each = function(obj, iterator, context) {
|
|
6272
|
-
if (obj === null || obj === undefined) {
|
|
6273
|
-
return;
|
|
6274
6361
|
}
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6280
|
-
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6362
|
+
`;
|
|
6363
|
+
const getAnswerData = `
|
|
6364
|
+
query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
|
|
6365
|
+
getAnswer(session: $session) {
|
|
6366
|
+
${bachSessionId}
|
|
6367
|
+
answer {
|
|
6368
|
+
id
|
|
6369
|
+
visualizations {
|
|
6370
|
+
id
|
|
6371
|
+
... on TableViz {
|
|
6372
|
+
columns {
|
|
6373
|
+
column {
|
|
6374
|
+
id
|
|
6375
|
+
name
|
|
6376
|
+
type
|
|
6377
|
+
aggregationType
|
|
6378
|
+
dataType
|
|
6379
|
+
}
|
|
6380
|
+
}
|
|
6381
|
+
data(deadline: $deadline, pagination: $dataPaginationParams)
|
|
6382
|
+
}
|
|
6288
6383
|
}
|
|
6289
6384
|
}
|
|
6290
6385
|
}
|
|
6291
6386
|
}
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
_.extend = function(obj) {
|
|
6295
|
-
_.each(slice.call(arguments, 1), function(source) {
|
|
6296
|
-
for (var prop in source) {
|
|
6297
|
-
if (source[prop] !== void 0) {
|
|
6298
|
-
obj[prop] = source[prop];
|
|
6299
|
-
}
|
|
6300
|
-
}
|
|
6301
|
-
});
|
|
6302
|
-
return obj;
|
|
6303
|
-
};
|
|
6304
|
-
|
|
6305
|
-
_.isArray = nativeIsArray || function(obj) {
|
|
6306
|
-
return toString.call(obj) === '[object Array]';
|
|
6307
|
-
};
|
|
6308
|
-
|
|
6309
|
-
// from a comment on http://dbj.org/dbj/?p=286
|
|
6310
|
-
// fails on only one very rare and deliberate custom object:
|
|
6311
|
-
// var bomb = { toString : undefined, valueOf: function(o) { return "function BOMBA!"; }};
|
|
6312
|
-
_.isFunction = function(f) {
|
|
6313
|
-
try {
|
|
6314
|
-
return /^\s*\bfunction\b/.test(f);
|
|
6315
|
-
} catch (x) {
|
|
6316
|
-
return false;
|
|
6317
|
-
}
|
|
6318
|
-
};
|
|
6319
|
-
|
|
6320
|
-
_.isArguments = function(obj) {
|
|
6321
|
-
return !!(obj && hasOwnProperty$9.call(obj, 'callee'));
|
|
6322
|
-
};
|
|
6323
|
-
|
|
6324
|
-
_.toArray = function(iterable) {
|
|
6325
|
-
if (!iterable) {
|
|
6326
|
-
return [];
|
|
6327
|
-
}
|
|
6328
|
-
if (iterable.toArray) {
|
|
6329
|
-
return iterable.toArray();
|
|
6330
|
-
}
|
|
6331
|
-
if (_.isArray(iterable)) {
|
|
6332
|
-
return slice.call(iterable);
|
|
6333
|
-
}
|
|
6334
|
-
if (_.isArguments(iterable)) {
|
|
6335
|
-
return slice.call(iterable);
|
|
6336
|
-
}
|
|
6337
|
-
return _.values(iterable);
|
|
6338
|
-
};
|
|
6339
|
-
|
|
6340
|
-
_.map = function(arr, callback, context) {
|
|
6341
|
-
if (nativeMap && arr.map === nativeMap) {
|
|
6342
|
-
return arr.map(callback, context);
|
|
6343
|
-
} else {
|
|
6344
|
-
var results = [];
|
|
6345
|
-
_.each(arr, function(item) {
|
|
6346
|
-
results.push(callback.call(context, item));
|
|
6347
|
-
});
|
|
6348
|
-
return results;
|
|
6349
|
-
}
|
|
6350
|
-
};
|
|
6351
|
-
|
|
6352
|
-
_.keys = function(obj) {
|
|
6353
|
-
var results = [];
|
|
6354
|
-
if (obj === null) {
|
|
6355
|
-
return results;
|
|
6356
|
-
}
|
|
6357
|
-
_.each(obj, function(value, key) {
|
|
6358
|
-
results[results.length] = key;
|
|
6359
|
-
});
|
|
6360
|
-
return results;
|
|
6361
|
-
};
|
|
6362
|
-
|
|
6363
|
-
_.values = function(obj) {
|
|
6364
|
-
var results = [];
|
|
6365
|
-
if (obj === null) {
|
|
6366
|
-
return results;
|
|
6367
|
-
}
|
|
6368
|
-
_.each(obj, function(value) {
|
|
6369
|
-
results[results.length] = value;
|
|
6370
|
-
});
|
|
6371
|
-
return results;
|
|
6372
|
-
};
|
|
6373
|
-
|
|
6374
|
-
_.include = function(obj, target) {
|
|
6375
|
-
var found = false;
|
|
6376
|
-
if (obj === null) {
|
|
6377
|
-
return found;
|
|
6378
|
-
}
|
|
6379
|
-
if (nativeIndexOf && obj.indexOf === nativeIndexOf) {
|
|
6380
|
-
return obj.indexOf(target) != -1;
|
|
6381
|
-
}
|
|
6382
|
-
_.each(obj, function(value) {
|
|
6383
|
-
if (found || (found = (value === target))) {
|
|
6384
|
-
return breaker;
|
|
6385
|
-
}
|
|
6386
|
-
});
|
|
6387
|
-
return found;
|
|
6388
|
-
};
|
|
6389
|
-
|
|
6390
|
-
_.includes = function(str, needle) {
|
|
6391
|
-
return str.indexOf(needle) !== -1;
|
|
6392
|
-
};
|
|
6393
|
-
|
|
6394
|
-
// Underscore Addons
|
|
6395
|
-
_.inherit = function(subclass, superclass) {
|
|
6396
|
-
subclass.prototype = new superclass();
|
|
6397
|
-
subclass.prototype.constructor = subclass;
|
|
6398
|
-
subclass.superclass = superclass.prototype;
|
|
6399
|
-
return subclass;
|
|
6400
|
-
};
|
|
6401
|
-
|
|
6402
|
-
_.isObject = function(obj) {
|
|
6403
|
-
return (obj === Object(obj) && !_.isArray(obj));
|
|
6404
|
-
};
|
|
6387
|
+
`;
|
|
6405
6388
|
|
|
6406
|
-
|
|
6407
|
-
|
|
6408
|
-
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6389
|
+
// eslint-disable-next-line no-shadow
|
|
6390
|
+
var OperationType;
|
|
6391
|
+
(function (OperationType) {
|
|
6392
|
+
OperationType["GetChartWithData"] = "GetChartWithData";
|
|
6393
|
+
OperationType["GetTableWithHeadlineData"] = "GetTableWithHeadlineData";
|
|
6394
|
+
})(OperationType || (OperationType = {}));
|
|
6395
|
+
/**
|
|
6396
|
+
* Class representing the answer service provided with the
|
|
6397
|
+
* custom action payload. This service could be used to run
|
|
6398
|
+
* graphql queries in the context of the answer on which the
|
|
6399
|
+
* custom action was triggered.
|
|
6400
|
+
*
|
|
6401
|
+
* @example
|
|
6402
|
+
* ```js
|
|
6403
|
+
* embed.on(EmbedEvent.CustomAction, e => {
|
|
6404
|
+
* const underlying = await e.answerService.getUnderlyingDataForPoint([
|
|
6405
|
+
* 'col name 1'
|
|
6406
|
+
* ]);
|
|
6407
|
+
* const data = await underlying.fetchData(0, 100);
|
|
6408
|
+
* })
|
|
6409
|
+
* ```
|
|
6410
|
+
* @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
|
|
6411
|
+
* @group Events
|
|
6412
|
+
*/
|
|
6413
|
+
class AnswerService {
|
|
6414
|
+
/**
|
|
6415
|
+
* Should not need to be called directly.
|
|
6416
|
+
*
|
|
6417
|
+
* @param session
|
|
6418
|
+
* @param answer
|
|
6419
|
+
* @param thoughtSpotHost
|
|
6420
|
+
* @param selectedPoints
|
|
6421
|
+
*/
|
|
6422
|
+
constructor(session, answer, thoughtSpotHost, selectedPoints) {
|
|
6423
|
+
this.session = session;
|
|
6424
|
+
this.answer = answer;
|
|
6425
|
+
this.thoughtSpotHost = thoughtSpotHost;
|
|
6426
|
+
this.selectedPoints = selectedPoints;
|
|
6427
|
+
this.session = removeTypename(session);
|
|
6428
|
+
}
|
|
6429
|
+
/**
|
|
6430
|
+
* Get the details about the source used in the answer.
|
|
6431
|
+
* This can be used to get the list of all columns in the data source for example.
|
|
6432
|
+
*/
|
|
6433
|
+
async getSourceDetail() {
|
|
6434
|
+
const sourceId = this.answer.sources[0].header.guid;
|
|
6435
|
+
return getSourceDetail(this.thoughtSpotHost, sourceId);
|
|
6436
|
+
}
|
|
6437
|
+
/**
|
|
6438
|
+
* Remove columnIds and return updated answer session.
|
|
6439
|
+
*
|
|
6440
|
+
* @param columnIds
|
|
6441
|
+
* @returns
|
|
6442
|
+
*/
|
|
6443
|
+
async removeColumns(columnIds) {
|
|
6444
|
+
return this.executeQuery(removeColumns, {
|
|
6445
|
+
logicalColumnIds: columnIds,
|
|
6446
|
+
});
|
|
6447
|
+
}
|
|
6448
|
+
/**
|
|
6449
|
+
* Add columnIds and return updated answer session.
|
|
6450
|
+
*
|
|
6451
|
+
* @param columnIds
|
|
6452
|
+
* @returns
|
|
6453
|
+
*/
|
|
6454
|
+
async addColumns(columnIds) {
|
|
6455
|
+
return this.executeQuery(addColumns, {
|
|
6456
|
+
columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
|
|
6457
|
+
});
|
|
6458
|
+
}
|
|
6459
|
+
/**
|
|
6460
|
+
* Fetch data from the answer.
|
|
6461
|
+
*
|
|
6462
|
+
* @param offset
|
|
6463
|
+
* @param size
|
|
6464
|
+
* @returns
|
|
6465
|
+
*/
|
|
6466
|
+
async fetchData(offset = 0, size = 1000) {
|
|
6467
|
+
const { answer } = await this.executeQuery(getAnswerData, {
|
|
6468
|
+
deadline: 0,
|
|
6469
|
+
dataPaginationParams: {
|
|
6470
|
+
isClientPaginated: true,
|
|
6471
|
+
offset,
|
|
6472
|
+
size,
|
|
6473
|
+
},
|
|
6474
|
+
});
|
|
6475
|
+
const { columns, data } = answer.visualizations.find((viz) => !!viz.data) || {};
|
|
6476
|
+
return {
|
|
6477
|
+
columns,
|
|
6478
|
+
data,
|
|
6479
|
+
};
|
|
6480
|
+
}
|
|
6481
|
+
/**
|
|
6482
|
+
* Fetch the data for the answer as a CSV blob. This might be
|
|
6483
|
+
* quicker for larger data.
|
|
6484
|
+
*
|
|
6485
|
+
* @param userLocale
|
|
6486
|
+
* @param includeInfo Include the CSV header in the output
|
|
6487
|
+
* @returns Response
|
|
6488
|
+
*/
|
|
6489
|
+
async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
|
|
6490
|
+
const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
|
|
6491
|
+
return tokenizedFetch(fetchUrl, {
|
|
6492
|
+
credentials: 'include',
|
|
6493
|
+
});
|
|
6494
|
+
}
|
|
6495
|
+
/**
|
|
6496
|
+
* Just get the internal URL for this answer's data
|
|
6497
|
+
* as a CSV blob.
|
|
6498
|
+
*
|
|
6499
|
+
* @param userLocale
|
|
6500
|
+
* @param includeInfo
|
|
6501
|
+
* @returns
|
|
6502
|
+
*/
|
|
6503
|
+
getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
|
|
6504
|
+
return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
|
|
6505
|
+
}
|
|
6506
|
+
/**
|
|
6507
|
+
* Get underlying data given a point and the output column names.
|
|
6508
|
+
* In case of a context menu action, the selectedPoints are
|
|
6509
|
+
* automatically passed.
|
|
6510
|
+
*
|
|
6511
|
+
* @param outputColumnNames
|
|
6512
|
+
* @param selectedPoints
|
|
6513
|
+
* @example
|
|
6514
|
+
* ```js
|
|
6515
|
+
* embed.on(EmbedEvent.CustomAction, e => {
|
|
6516
|
+
* const underlying = await e.answerService.getUnderlyingDataForPoint([
|
|
6517
|
+
* 'col name 1' // The column should exist in the data source.
|
|
6518
|
+
* ]);
|
|
6519
|
+
* const data = await underlying.fetchData(0, 100);
|
|
6520
|
+
* })
|
|
6521
|
+
* ```
|
|
6522
|
+
* @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
|
|
6523
|
+
*/
|
|
6524
|
+
async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
|
|
6525
|
+
if (!selectedPoints && !this.selectedPoints) {
|
|
6526
|
+
throw new Error('Needs to be triggered in context of a point');
|
|
6527
|
+
}
|
|
6528
|
+
if (!selectedPoints) {
|
|
6529
|
+
selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
|
|
6530
|
+
}
|
|
6531
|
+
const sourceDetail = await this.getSourceDetail();
|
|
6532
|
+
const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
|
|
6533
|
+
const unAggAnswer = await graphqlQuery({
|
|
6534
|
+
query: getUnaggregatedAnswerSession,
|
|
6535
|
+
variables: {
|
|
6536
|
+
session: this.session,
|
|
6537
|
+
columns: selectedPoints,
|
|
6538
|
+
},
|
|
6539
|
+
thoughtSpotHost: this.thoughtSpotHost,
|
|
6540
|
+
});
|
|
6541
|
+
const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
|
|
6542
|
+
const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
|
|
6543
|
+
.map((c) => c.column.referencedColumns[0].guid));
|
|
6544
|
+
const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
|
|
6545
|
+
if (columnsToAdd.length) {
|
|
6546
|
+
await unaggAnswerSession.addColumns(columnsToAdd);
|
|
6547
|
+
}
|
|
6548
|
+
const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
|
|
6549
|
+
if (columnsToRemove.length) {
|
|
6550
|
+
await unaggAnswerSession.removeColumns(columnsToRemove);
|
|
6551
|
+
}
|
|
6552
|
+
return unaggAnswerSession;
|
|
6553
|
+
}
|
|
6554
|
+
/**
|
|
6555
|
+
* Execute a custom graphql query in the context of the answer.
|
|
6556
|
+
*
|
|
6557
|
+
* @param query graphql query
|
|
6558
|
+
* @param variables graphql variables
|
|
6559
|
+
* @returns
|
|
6560
|
+
*/
|
|
6561
|
+
async executeQuery(query, variables) {
|
|
6562
|
+
const data = await graphqlQuery({
|
|
6563
|
+
query,
|
|
6564
|
+
variables: {
|
|
6565
|
+
session: this.session,
|
|
6566
|
+
...variables,
|
|
6567
|
+
},
|
|
6568
|
+
thoughtSpotHost: this.thoughtSpotHost,
|
|
6569
|
+
isCompositeQuery: false,
|
|
6570
|
+
});
|
|
6571
|
+
this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
|
|
6572
|
+
return data;
|
|
6573
|
+
}
|
|
6574
|
+
/**
|
|
6575
|
+
* Get the internal session details for the answer.
|
|
6576
|
+
*
|
|
6577
|
+
* @returns
|
|
6578
|
+
*/
|
|
6579
|
+
getSession() {
|
|
6580
|
+
return this.session;
|
|
6581
|
+
}
|
|
6582
|
+
}
|
|
6583
|
+
/**
|
|
6584
|
+
*
|
|
6585
|
+
* @param sourceDetail
|
|
6586
|
+
* @param colNames
|
|
6587
|
+
*/
|
|
6588
|
+
function getGuidsFromColumnNames(sourceDetail, colNames) {
|
|
6589
|
+
const cols = sourceDetail.columns.reduce((colSet, col) => {
|
|
6590
|
+
colSet[col.name] = col;
|
|
6591
|
+
return colSet;
|
|
6592
|
+
}, {});
|
|
6593
|
+
return new Set(colNames.map((colName) => {
|
|
6594
|
+
const col = cols[colName];
|
|
6595
|
+
return col.id;
|
|
6596
|
+
}));
|
|
6597
|
+
}
|
|
6598
|
+
/**
|
|
6599
|
+
*
|
|
6600
|
+
* @param selectedPoints
|
|
6601
|
+
*/
|
|
6602
|
+
function getSelectedPointsForUnderlyingDataQuery(selectedPoints) {
|
|
6603
|
+
const underlyingDataPoint = [];
|
|
6604
|
+
/**
|
|
6605
|
+
*
|
|
6606
|
+
* @param colVal
|
|
6607
|
+
*/
|
|
6608
|
+
function addPointFromColVal(colVal) {
|
|
6609
|
+
var _a;
|
|
6610
|
+
const dataType = colVal.column.dataType;
|
|
6611
|
+
const id = colVal.column.id;
|
|
6612
|
+
let dataValue;
|
|
6613
|
+
if (dataType === 'DATE') {
|
|
6614
|
+
if (Number.isFinite(colVal.value)) {
|
|
6615
|
+
dataValue = [{
|
|
6616
|
+
epochRange: {
|
|
6617
|
+
startEpoch: colVal.value,
|
|
6618
|
+
},
|
|
6619
|
+
}];
|
|
6620
|
+
// Case for custom calendar.
|
|
6621
|
+
}
|
|
6622
|
+
else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
|
|
6623
|
+
dataValue = [{
|
|
6624
|
+
epochRange: {
|
|
6625
|
+
startEpoch: colVal.value.v.s,
|
|
6626
|
+
endEpoch: colVal.value.v.e,
|
|
6627
|
+
},
|
|
6628
|
+
}];
|
|
6629
|
+
}
|
|
6630
|
+
}
|
|
6631
|
+
else {
|
|
6632
|
+
dataValue = [{ value: colVal.value }];
|
|
6633
|
+
}
|
|
6634
|
+
underlyingDataPoint.push({
|
|
6635
|
+
columnId: colVal.column.id,
|
|
6636
|
+
dataValue,
|
|
6637
|
+
});
|
|
6638
|
+
}
|
|
6639
|
+
selectedPoints.forEach((p) => {
|
|
6640
|
+
p.selectedAttributes.forEach(addPointFromColVal);
|
|
6641
|
+
});
|
|
6642
|
+
return underlyingDataPoint;
|
|
6643
|
+
}
|
|
6417
6644
|
|
|
6418
|
-
|
|
6419
|
-
|
|
6645
|
+
const ERROR_MESSAGE = {
|
|
6646
|
+
INVALID_THOUGHTSPOT_HOST: 'Error parsing ThoughtSpot host. Please provide a valid URL.',
|
|
6647
|
+
LIVEBOARD_VIZ_ID_VALIDATION: 'Please select a liveboard to embed.',
|
|
6648
|
+
TRIGGER_TIMED_OUT: 'Trigger timedout in getting response',
|
|
6649
|
+
SEARCHEMBED_BETA_WRANING_MESSAGE: 'Search Embed is in Beta in this release.',
|
|
6650
|
+
SAGE_EMBED_BETA_WARNING_MESSAGE: 'Sage Embed is in Beta in this release.',
|
|
6420
6651
|
};
|
|
6421
6652
|
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6653
|
+
/**
|
|
6654
|
+
* Copyright (c) 2023
|
|
6655
|
+
*
|
|
6656
|
+
* Utilities related to reading configuration objects
|
|
6657
|
+
*
|
|
6658
|
+
* @summary Config-related utils
|
|
6659
|
+
* @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
|
|
6660
|
+
*/
|
|
6661
|
+
const urlRegex = new RegExp([
|
|
6662
|
+
'(^(https?:)//)?',
|
|
6663
|
+
'(([^:/?#]*)(?::([0-9]+))?)',
|
|
6664
|
+
'(/{0,1}[^?#]*)',
|
|
6665
|
+
'(\\?[^#]*|)',
|
|
6666
|
+
'(#.*|)$', // hash
|
|
6667
|
+
].join(''));
|
|
6668
|
+
/**
|
|
6669
|
+
* Parse and construct the ThoughtSpot hostname or IP address
|
|
6670
|
+
* from the embed configuration object.
|
|
6671
|
+
*
|
|
6672
|
+
* @param config
|
|
6673
|
+
*/
|
|
6674
|
+
const getThoughtSpotHost = (config) => {
|
|
6675
|
+
if (!config.thoughtSpotHost) {
|
|
6676
|
+
throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
|
|
6677
|
+
}
|
|
6678
|
+
const urlParts = config.thoughtSpotHost.match(urlRegex);
|
|
6679
|
+
if (!urlParts) {
|
|
6680
|
+
throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
|
|
6681
|
+
}
|
|
6682
|
+
const protocol = urlParts[2] || window.location.protocol;
|
|
6683
|
+
const host = urlParts[3];
|
|
6684
|
+
let path = urlParts[6];
|
|
6685
|
+
// Lose the trailing / if any
|
|
6686
|
+
if (path.charAt(path.length - 1) === '/') {
|
|
6687
|
+
path = path.substring(0, path.length - 1);
|
|
6688
|
+
}
|
|
6689
|
+
// const urlParams = urlParts[7];
|
|
6690
|
+
// const hash = urlParts[8];
|
|
6691
|
+
return `${protocol}//${host}${path}`;
|
|
6692
|
+
};
|
|
6693
|
+
const getV2BasePath = (config) => {
|
|
6694
|
+
if (config.basepath) {
|
|
6695
|
+
return config.basepath;
|
|
6696
|
+
}
|
|
6697
|
+
const tsHost = getThoughtSpotHost(config);
|
|
6698
|
+
// This is to handle when e2e's. Search is run on pods for
|
|
6699
|
+
// comp-blink-test-pipeline with baseUrl=https://localhost:8443.
|
|
6700
|
+
// This is to handle when the developer is developing in their local
|
|
6701
|
+
// environment.
|
|
6702
|
+
if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
|
|
6703
|
+
return '';
|
|
6704
|
+
}
|
|
6705
|
+
return 'v2';
|
|
6706
|
+
};
|
|
6707
|
+
/**
|
|
6708
|
+
* It is a good idea to keep URLs under 2000 chars.
|
|
6709
|
+
* If this is ever breached, since we pass view configuration through
|
|
6710
|
+
* URL params, we would like to log a warning.
|
|
6711
|
+
* Reference: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
|
|
6712
|
+
*/
|
|
6713
|
+
const URL_MAX_LENGTH = 2000;
|
|
6714
|
+
/**
|
|
6715
|
+
* The default CSS dimensions of the embedded app
|
|
6716
|
+
*/
|
|
6717
|
+
const DEFAULT_EMBED_WIDTH = '100%';
|
|
6718
|
+
const DEFAULT_EMBED_HEIGHT = '100%';
|
|
6425
6719
|
|
|
6426
|
-
|
|
6427
|
-
|
|
6720
|
+
var Config = {
|
|
6721
|
+
DEBUG: false,
|
|
6722
|
+
LIB_VERSION: '2.45.0'
|
|
6428
6723
|
};
|
|
6429
6724
|
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6725
|
+
// since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
|
|
6726
|
+
var window$1;
|
|
6727
|
+
if (typeof(window) === 'undefined') {
|
|
6728
|
+
var loc = {
|
|
6729
|
+
hostname: ''
|
|
6730
|
+
};
|
|
6731
|
+
window$1 = {
|
|
6732
|
+
navigator: { userAgent: '' },
|
|
6733
|
+
document: {
|
|
6734
|
+
location: loc,
|
|
6735
|
+
referrer: ''
|
|
6736
|
+
},
|
|
6737
|
+
screen: { width: 0, height: 0 },
|
|
6738
|
+
location: loc
|
|
6739
|
+
};
|
|
6740
|
+
} else {
|
|
6741
|
+
window$1 = window;
|
|
6742
|
+
}
|
|
6433
6743
|
|
|
6434
|
-
|
|
6435
|
-
|
|
6744
|
+
/*
|
|
6745
|
+
* Saved references to long variable names, so that closure compiler can
|
|
6746
|
+
* minimize file size.
|
|
6747
|
+
*/
|
|
6748
|
+
|
|
6749
|
+
var ArrayProto = Array.prototype;
|
|
6750
|
+
var FuncProto = Function.prototype;
|
|
6751
|
+
var ObjProto = Object.prototype;
|
|
6752
|
+
var slice = ArrayProto.slice;
|
|
6753
|
+
var toString = ObjProto.toString;
|
|
6754
|
+
var hasOwnProperty$9 = ObjProto.hasOwnProperty;
|
|
6755
|
+
var windowConsole = window$1.console;
|
|
6756
|
+
var navigator = window$1.navigator;
|
|
6757
|
+
var document$1 = window$1.document;
|
|
6758
|
+
var windowOpera = window$1.opera;
|
|
6759
|
+
var screen = window$1.screen;
|
|
6760
|
+
var userAgent = navigator.userAgent;
|
|
6761
|
+
var nativeBind = FuncProto.bind;
|
|
6762
|
+
var nativeForEach = ArrayProto.forEach;
|
|
6763
|
+
var nativeIndexOf = ArrayProto.indexOf;
|
|
6764
|
+
var nativeMap = ArrayProto.map;
|
|
6765
|
+
var nativeIsArray = Array.isArray;
|
|
6766
|
+
var breaker = {};
|
|
6767
|
+
var _ = {
|
|
6768
|
+
trim: function(str) {
|
|
6769
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
|
|
6770
|
+
return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
|
|
6771
|
+
}
|
|
6436
6772
|
};
|
|
6437
6773
|
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6774
|
+
// Console override
|
|
6775
|
+
var console$1 = {
|
|
6776
|
+
/** @type {function(...*)} */
|
|
6777
|
+
log: function() {
|
|
6778
|
+
if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
|
|
6779
|
+
try {
|
|
6780
|
+
windowConsole.log.apply(windowConsole, arguments);
|
|
6781
|
+
} catch (err) {
|
|
6782
|
+
_.each(arguments, function(arg) {
|
|
6783
|
+
windowConsole.log(arg);
|
|
6784
|
+
});
|
|
6785
|
+
}
|
|
6444
6786
|
}
|
|
6445
|
-
}
|
|
6446
|
-
|
|
6787
|
+
},
|
|
6788
|
+
/** @type {function(...*)} */
|
|
6789
|
+
warn: function() {
|
|
6790
|
+
if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
|
|
6791
|
+
var args = ['Mixpanel warning:'].concat(_.toArray(arguments));
|
|
6792
|
+
try {
|
|
6793
|
+
windowConsole.warn.apply(windowConsole, args);
|
|
6794
|
+
} catch (err) {
|
|
6795
|
+
_.each(args, function(arg) {
|
|
6796
|
+
windowConsole.warn(arg);
|
|
6797
|
+
});
|
|
6798
|
+
}
|
|
6799
|
+
}
|
|
6800
|
+
},
|
|
6801
|
+
/** @type {function(...*)} */
|
|
6802
|
+
error: function() {
|
|
6803
|
+
if (Config.DEBUG && !_.isUndefined(windowConsole) && windowConsole) {
|
|
6804
|
+
var args = ['Mixpanel error:'].concat(_.toArray(arguments));
|
|
6805
|
+
try {
|
|
6806
|
+
windowConsole.error.apply(windowConsole, args);
|
|
6807
|
+
} catch (err) {
|
|
6808
|
+
_.each(args, function(arg) {
|
|
6809
|
+
windowConsole.error(arg);
|
|
6810
|
+
});
|
|
6811
|
+
}
|
|
6812
|
+
}
|
|
6813
|
+
},
|
|
6814
|
+
/** @type {function(...*)} */
|
|
6815
|
+
critical: function() {
|
|
6816
|
+
if (!_.isUndefined(windowConsole) && windowConsole) {
|
|
6817
|
+
var args = ['Mixpanel error:'].concat(_.toArray(arguments));
|
|
6818
|
+
try {
|
|
6819
|
+
windowConsole.error.apply(windowConsole, args);
|
|
6820
|
+
} catch (err) {
|
|
6821
|
+
_.each(args, function(arg) {
|
|
6822
|
+
windowConsole.error(arg);
|
|
6823
|
+
});
|
|
6824
|
+
}
|
|
6825
|
+
}
|
|
6826
|
+
}
|
|
6447
6827
|
};
|
|
6448
6828
|
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6829
|
+
var log_func_with_prefix = function(func, prefix) {
|
|
6830
|
+
return function() {
|
|
6831
|
+
arguments[0] = '[' + prefix + '] ' + arguments[0];
|
|
6832
|
+
return func.apply(console$1, arguments);
|
|
6452
6833
|
};
|
|
6453
|
-
return Date.now();
|
|
6454
6834
|
};
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
}
|
|
6461
|
-
return d.getUTCFullYear() + '-' +
|
|
6462
|
-
pad(d.getUTCMonth() + 1) + '-' +
|
|
6463
|
-
pad(d.getUTCDate()) + 'T' +
|
|
6464
|
-
pad(d.getUTCHours()) + ':' +
|
|
6465
|
-
pad(d.getUTCMinutes()) + ':' +
|
|
6466
|
-
pad(d.getUTCSeconds());
|
|
6835
|
+
var console_with_prefix = function(prefix) {
|
|
6836
|
+
return {
|
|
6837
|
+
log: log_func_with_prefix(console$1.log, prefix),
|
|
6838
|
+
error: log_func_with_prefix(console$1.error, prefix),
|
|
6839
|
+
critical: log_func_with_prefix(console$1.critical, prefix)
|
|
6840
|
+
};
|
|
6467
6841
|
};
|
|
6468
6842
|
|
|
6469
|
-
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6843
|
+
|
|
6844
|
+
// UNDERSCORE
|
|
6845
|
+
// Embed part of the Underscore Library
|
|
6846
|
+
_.bind = function(func, context) {
|
|
6847
|
+
var args, bound;
|
|
6848
|
+
if (nativeBind && func.bind === nativeBind) {
|
|
6849
|
+
return nativeBind.apply(func, slice.call(arguments, 1));
|
|
6850
|
+
}
|
|
6851
|
+
if (!_.isFunction(func)) {
|
|
6852
|
+
throw new TypeError();
|
|
6853
|
+
}
|
|
6854
|
+
args = slice.call(arguments, 2);
|
|
6855
|
+
bound = function() {
|
|
6856
|
+
if (!(this instanceof bound)) {
|
|
6857
|
+
return func.apply(context, args.concat(slice.call(arguments)));
|
|
6474
6858
|
}
|
|
6475
|
-
|
|
6476
|
-
|
|
6859
|
+
var ctor = {};
|
|
6860
|
+
ctor.prototype = func.prototype;
|
|
6861
|
+
var self = new ctor();
|
|
6862
|
+
ctor.prototype = null;
|
|
6863
|
+
var result = func.apply(self, args.concat(slice.call(arguments)));
|
|
6864
|
+
if (Object(result) === result) {
|
|
6865
|
+
return result;
|
|
6866
|
+
}
|
|
6867
|
+
return self;
|
|
6868
|
+
};
|
|
6869
|
+
return bound;
|
|
6477
6870
|
};
|
|
6478
6871
|
|
|
6479
|
-
|
|
6480
|
-
*
|
|
6481
|
-
*
|
|
6482
|
-
*
|
|
6483
|
-
*/
|
|
6872
|
+
/**
|
|
6873
|
+
* @param {*=} obj
|
|
6874
|
+
* @param {function(...*)=} iterator
|
|
6875
|
+
* @param {Object=} context
|
|
6876
|
+
*/
|
|
6877
|
+
_.each = function(obj, iterator, context) {
|
|
6878
|
+
if (obj === null || obj === undefined) {
|
|
6879
|
+
return;
|
|
6880
|
+
}
|
|
6881
|
+
if (nativeForEach && obj.forEach === nativeForEach) {
|
|
6882
|
+
obj.forEach(iterator, context);
|
|
6883
|
+
} else if (obj.length === +obj.length) {
|
|
6884
|
+
for (var i = 0, l = obj.length; i < l; i++) {
|
|
6885
|
+
if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) {
|
|
6886
|
+
return;
|
|
6887
|
+
}
|
|
6888
|
+
}
|
|
6889
|
+
} else {
|
|
6890
|
+
for (var key in obj) {
|
|
6891
|
+
if (hasOwnProperty$9.call(obj, key)) {
|
|
6892
|
+
if (iterator.call(context, obj[key], key, obj) === breaker) {
|
|
6893
|
+
return;
|
|
6894
|
+
}
|
|
6895
|
+
}
|
|
6896
|
+
}
|
|
6897
|
+
}
|
|
6898
|
+
};
|
|
6899
|
+
|
|
6900
|
+
_.extend = function(obj) {
|
|
6901
|
+
_.each(slice.call(arguments, 1), function(source) {
|
|
6902
|
+
for (var prop in source) {
|
|
6903
|
+
if (source[prop] !== void 0) {
|
|
6904
|
+
obj[prop] = source[prop];
|
|
6905
|
+
}
|
|
6906
|
+
}
|
|
6907
|
+
});
|
|
6908
|
+
return obj;
|
|
6909
|
+
};
|
|
6910
|
+
|
|
6911
|
+
_.isArray = nativeIsArray || function(obj) {
|
|
6912
|
+
return toString.call(obj) === '[object Array]';
|
|
6913
|
+
};
|
|
6914
|
+
|
|
6915
|
+
// from a comment on http://dbj.org/dbj/?p=286
|
|
6916
|
+
// fails on only one very rare and deliberate custom object:
|
|
6917
|
+
// var bomb = { toString : undefined, valueOf: function(o) { return "function BOMBA!"; }};
|
|
6918
|
+
_.isFunction = function(f) {
|
|
6919
|
+
try {
|
|
6920
|
+
return /^\s*\bfunction\b/.test(f);
|
|
6921
|
+
} catch (x) {
|
|
6922
|
+
return false;
|
|
6923
|
+
}
|
|
6924
|
+
};
|
|
6925
|
+
|
|
6926
|
+
_.isArguments = function(obj) {
|
|
6927
|
+
return !!(obj && hasOwnProperty$9.call(obj, 'callee'));
|
|
6928
|
+
};
|
|
6929
|
+
|
|
6930
|
+
_.toArray = function(iterable) {
|
|
6931
|
+
if (!iterable) {
|
|
6932
|
+
return [];
|
|
6933
|
+
}
|
|
6934
|
+
if (iterable.toArray) {
|
|
6935
|
+
return iterable.toArray();
|
|
6936
|
+
}
|
|
6937
|
+
if (_.isArray(iterable)) {
|
|
6938
|
+
return slice.call(iterable);
|
|
6939
|
+
}
|
|
6940
|
+
if (_.isArguments(iterable)) {
|
|
6941
|
+
return slice.call(iterable);
|
|
6942
|
+
}
|
|
6943
|
+
return _.values(iterable);
|
|
6944
|
+
};
|
|
6945
|
+
|
|
6946
|
+
_.map = function(arr, callback, context) {
|
|
6947
|
+
if (nativeMap && arr.map === nativeMap) {
|
|
6948
|
+
return arr.map(callback, context);
|
|
6949
|
+
} else {
|
|
6950
|
+
var results = [];
|
|
6951
|
+
_.each(arr, function(item) {
|
|
6952
|
+
results.push(callback.call(context, item));
|
|
6953
|
+
});
|
|
6954
|
+
return results;
|
|
6955
|
+
}
|
|
6956
|
+
};
|
|
6957
|
+
|
|
6958
|
+
_.keys = function(obj) {
|
|
6959
|
+
var results = [];
|
|
6960
|
+
if (obj === null) {
|
|
6961
|
+
return results;
|
|
6962
|
+
}
|
|
6963
|
+
_.each(obj, function(value, key) {
|
|
6964
|
+
results[results.length] = key;
|
|
6965
|
+
});
|
|
6966
|
+
return results;
|
|
6967
|
+
};
|
|
6968
|
+
|
|
6969
|
+
_.values = function(obj) {
|
|
6970
|
+
var results = [];
|
|
6971
|
+
if (obj === null) {
|
|
6972
|
+
return results;
|
|
6973
|
+
}
|
|
6974
|
+
_.each(obj, function(value) {
|
|
6975
|
+
results[results.length] = value;
|
|
6976
|
+
});
|
|
6977
|
+
return results;
|
|
6978
|
+
};
|
|
6979
|
+
|
|
6980
|
+
_.include = function(obj, target) {
|
|
6981
|
+
var found = false;
|
|
6982
|
+
if (obj === null) {
|
|
6983
|
+
return found;
|
|
6984
|
+
}
|
|
6985
|
+
if (nativeIndexOf && obj.indexOf === nativeIndexOf) {
|
|
6986
|
+
return obj.indexOf(target) != -1;
|
|
6987
|
+
}
|
|
6988
|
+
_.each(obj, function(value) {
|
|
6989
|
+
if (found || (found = (value === target))) {
|
|
6990
|
+
return breaker;
|
|
6991
|
+
}
|
|
6992
|
+
});
|
|
6993
|
+
return found;
|
|
6994
|
+
};
|
|
6995
|
+
|
|
6996
|
+
_.includes = function(str, needle) {
|
|
6997
|
+
return str.indexOf(needle) !== -1;
|
|
6998
|
+
};
|
|
6999
|
+
|
|
7000
|
+
// Underscore Addons
|
|
7001
|
+
_.inherit = function(subclass, superclass) {
|
|
7002
|
+
subclass.prototype = new superclass();
|
|
7003
|
+
subclass.prototype.constructor = subclass;
|
|
7004
|
+
subclass.superclass = superclass.prototype;
|
|
7005
|
+
return subclass;
|
|
7006
|
+
};
|
|
7007
|
+
|
|
7008
|
+
_.isObject = function(obj) {
|
|
7009
|
+
return (obj === Object(obj) && !_.isArray(obj));
|
|
7010
|
+
};
|
|
7011
|
+
|
|
7012
|
+
_.isEmptyObject = function(obj) {
|
|
7013
|
+
if (_.isObject(obj)) {
|
|
7014
|
+
for (var key in obj) {
|
|
7015
|
+
if (hasOwnProperty$9.call(obj, key)) {
|
|
7016
|
+
return false;
|
|
7017
|
+
}
|
|
7018
|
+
}
|
|
7019
|
+
return true;
|
|
7020
|
+
}
|
|
7021
|
+
return false;
|
|
7022
|
+
};
|
|
7023
|
+
|
|
7024
|
+
_.isUndefined = function(obj) {
|
|
7025
|
+
return obj === void 0;
|
|
7026
|
+
};
|
|
7027
|
+
|
|
7028
|
+
_.isString = function(obj) {
|
|
7029
|
+
return toString.call(obj) == '[object String]';
|
|
7030
|
+
};
|
|
7031
|
+
|
|
7032
|
+
_.isDate = function(obj) {
|
|
7033
|
+
return toString.call(obj) == '[object Date]';
|
|
7034
|
+
};
|
|
7035
|
+
|
|
7036
|
+
_.isNumber = function(obj) {
|
|
7037
|
+
return toString.call(obj) == '[object Number]';
|
|
7038
|
+
};
|
|
7039
|
+
|
|
7040
|
+
_.isElement = function(obj) {
|
|
7041
|
+
return !!(obj && obj.nodeType === 1);
|
|
7042
|
+
};
|
|
7043
|
+
|
|
7044
|
+
_.encodeDates = function(obj) {
|
|
7045
|
+
_.each(obj, function(v, k) {
|
|
7046
|
+
if (_.isDate(v)) {
|
|
7047
|
+
obj[k] = _.formatDate(v);
|
|
7048
|
+
} else if (_.isObject(v)) {
|
|
7049
|
+
obj[k] = _.encodeDates(v); // recurse
|
|
7050
|
+
}
|
|
7051
|
+
});
|
|
7052
|
+
return obj;
|
|
7053
|
+
};
|
|
7054
|
+
|
|
7055
|
+
_.timestamp = function() {
|
|
7056
|
+
Date.now = Date.now || function() {
|
|
7057
|
+
return +new Date;
|
|
7058
|
+
};
|
|
7059
|
+
return Date.now();
|
|
7060
|
+
};
|
|
7061
|
+
|
|
7062
|
+
_.formatDate = function(d) {
|
|
7063
|
+
// YYYY-MM-DDTHH:MM:SS in UTC
|
|
7064
|
+
function pad(n) {
|
|
7065
|
+
return n < 10 ? '0' + n : n;
|
|
7066
|
+
}
|
|
7067
|
+
return d.getUTCFullYear() + '-' +
|
|
7068
|
+
pad(d.getUTCMonth() + 1) + '-' +
|
|
7069
|
+
pad(d.getUTCDate()) + 'T' +
|
|
7070
|
+
pad(d.getUTCHours()) + ':' +
|
|
7071
|
+
pad(d.getUTCMinutes()) + ':' +
|
|
7072
|
+
pad(d.getUTCSeconds());
|
|
7073
|
+
};
|
|
7074
|
+
|
|
7075
|
+
_.strip_empty_properties = function(p) {
|
|
7076
|
+
var ret = {};
|
|
7077
|
+
_.each(p, function(v, k) {
|
|
7078
|
+
if (_.isString(v) && v.length > 0) {
|
|
7079
|
+
ret[k] = v;
|
|
7080
|
+
}
|
|
7081
|
+
});
|
|
7082
|
+
return ret;
|
|
7083
|
+
};
|
|
7084
|
+
|
|
7085
|
+
/*
|
|
7086
|
+
* this function returns a copy of object after truncating it. If
|
|
7087
|
+
* passed an Array or Object it will iterate through obj and
|
|
7088
|
+
* truncate all the values recursively.
|
|
7089
|
+
*/
|
|
6484
7090
|
_.truncate = function(obj, length) {
|
|
6485
7091
|
var ret;
|
|
6486
7092
|
|
|
@@ -11750,1356 +12356,422 @@ MixpanelLib.prototype._gdpr_call_func = function(func, options) {
|
|
|
11750
12356
|
}, options);
|
|
11751
12357
|
|
|
11752
12358
|
// check if localStorage can be used for recording opt out status, fall back to cookie if not
|
|
11753
|
-
if (!_.localStorage.is_supported()) {
|
|
11754
|
-
options['persistence_type'] = 'cookie';
|
|
11755
|
-
}
|
|
11756
|
-
|
|
11757
|
-
return func(this.get_config('token'), {
|
|
11758
|
-
track: options['track'],
|
|
11759
|
-
trackEventName: options['track_event_name'],
|
|
11760
|
-
trackProperties: options['track_properties'],
|
|
11761
|
-
persistenceType: options['persistence_type'],
|
|
11762
|
-
persistencePrefix: options['cookie_prefix'],
|
|
11763
|
-
cookieDomain: options['cookie_domain'],
|
|
11764
|
-
cookieExpiration: options['cookie_expiration'],
|
|
11765
|
-
crossSiteCookie: options['cross_site_cookie'],
|
|
11766
|
-
crossSubdomainCookie: options['cross_subdomain_cookie'],
|
|
11767
|
-
secureCookie: options['secure_cookie'],
|
|
11768
|
-
ignoreDnt: options['ignore_dnt']
|
|
11769
|
-
});
|
|
11770
|
-
};
|
|
11771
|
-
|
|
11772
|
-
/**
|
|
11773
|
-
* Opt the user in to data tracking and cookies/localstorage for this Mixpanel instance
|
|
11774
|
-
*
|
|
11775
|
-
* ### Usage
|
|
11776
|
-
*
|
|
11777
|
-
* // opt user in
|
|
11778
|
-
* mixpanel.opt_in_tracking();
|
|
11779
|
-
*
|
|
11780
|
-
* // opt user in with specific event name, properties, cookie configuration
|
|
11781
|
-
* mixpanel.opt_in_tracking({
|
|
11782
|
-
* track_event_name: 'User opted in',
|
|
11783
|
-
* track_event_properties: {
|
|
11784
|
-
* 'Email': 'jdoe@example.com'
|
|
11785
|
-
* },
|
|
11786
|
-
* cookie_expiration: 30,
|
|
11787
|
-
* secure_cookie: true
|
|
11788
|
-
* });
|
|
11789
|
-
*
|
|
11790
|
-
* @param {Object} [options] A dictionary of config options to override
|
|
11791
|
-
* @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)
|
|
11792
|
-
* @param {string} [options.track_event_name=$opt_in] Event name to be used for tracking the opt-in action
|
|
11793
|
-
* @param {Object} [options.track_properties] Set of properties to be tracked along with the opt-in action
|
|
11794
|
-
* @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
|
|
11795
|
-
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
11796
|
-
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
11797
|
-
* @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
|
|
11798
|
-
* @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
|
|
11799
|
-
* @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)
|
|
11800
|
-
* @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)
|
|
11801
|
-
* @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)
|
|
11802
|
-
*/
|
|
11803
|
-
MixpanelLib.prototype.opt_in_tracking = function(options) {
|
|
11804
|
-
options = _.extend({
|
|
11805
|
-
'enable_persistence': true
|
|
11806
|
-
}, options);
|
|
11807
|
-
|
|
11808
|
-
this._gdpr_call_func(optIn, options);
|
|
11809
|
-
this._gdpr_update_persistence(options);
|
|
11810
|
-
};
|
|
11811
|
-
|
|
11812
|
-
/**
|
|
11813
|
-
* Opt the user out of data tracking and cookies/localstorage for this Mixpanel instance
|
|
11814
|
-
*
|
|
11815
|
-
* ### Usage
|
|
11816
|
-
*
|
|
11817
|
-
* // opt user out
|
|
11818
|
-
* mixpanel.opt_out_tracking();
|
|
11819
|
-
*
|
|
11820
|
-
* // opt user out with different cookie configuration from Mixpanel instance
|
|
11821
|
-
* mixpanel.opt_out_tracking({
|
|
11822
|
-
* cookie_expiration: 30,
|
|
11823
|
-
* secure_cookie: true
|
|
11824
|
-
* });
|
|
11825
|
-
*
|
|
11826
|
-
* @param {Object} [options] A dictionary of config options to override
|
|
11827
|
-
* @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
|
|
11828
|
-
* @param {boolean} [options.clear_persistence=true] If true, will delete all data stored by the sdk in persistence
|
|
11829
|
-
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
11830
|
-
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
11831
|
-
* @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
|
|
11832
|
-
* @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
|
|
11833
|
-
* @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)
|
|
11834
|
-
* @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)
|
|
11835
|
-
* @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)
|
|
11836
|
-
*/
|
|
11837
|
-
MixpanelLib.prototype.opt_out_tracking = function(options) {
|
|
11838
|
-
options = _.extend({
|
|
11839
|
-
'clear_persistence': true,
|
|
11840
|
-
'delete_user': true
|
|
11841
|
-
}, options);
|
|
11842
|
-
|
|
11843
|
-
// delete user and clear charges since these methods may be disabled by opt-out
|
|
11844
|
-
if (options['delete_user'] && this['people'] && this['people']._identify_called()) {
|
|
11845
|
-
this['people'].delete_user();
|
|
11846
|
-
this['people'].clear_charges();
|
|
11847
|
-
}
|
|
11848
|
-
|
|
11849
|
-
this._gdpr_call_func(optOut, options);
|
|
11850
|
-
this._gdpr_update_persistence(options);
|
|
11851
|
-
};
|
|
11852
|
-
|
|
11853
|
-
/**
|
|
11854
|
-
* Check whether the user has opted in to data tracking and cookies/localstorage for this Mixpanel instance
|
|
11855
|
-
*
|
|
11856
|
-
* ### Usage
|
|
11857
|
-
*
|
|
11858
|
-
* var has_opted_in = mixpanel.has_opted_in_tracking();
|
|
11859
|
-
* // use has_opted_in value
|
|
11860
|
-
*
|
|
11861
|
-
* @param {Object} [options] A dictionary of config options to override
|
|
11862
|
-
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
11863
|
-
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
11864
|
-
* @returns {boolean} current opt-in status
|
|
11865
|
-
*/
|
|
11866
|
-
MixpanelLib.prototype.has_opted_in_tracking = function(options) {
|
|
11867
|
-
return this._gdpr_call_func(hasOptedIn, options);
|
|
11868
|
-
};
|
|
11869
|
-
|
|
11870
|
-
/**
|
|
11871
|
-
* Check whether the user has opted out of data tracking and cookies/localstorage for this Mixpanel instance
|
|
11872
|
-
*
|
|
11873
|
-
* ### Usage
|
|
11874
|
-
*
|
|
11875
|
-
* var has_opted_out = mixpanel.has_opted_out_tracking();
|
|
11876
|
-
* // use has_opted_out value
|
|
11877
|
-
*
|
|
11878
|
-
* @param {Object} [options] A dictionary of config options to override
|
|
11879
|
-
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
11880
|
-
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
11881
|
-
* @returns {boolean} current opt-out status
|
|
11882
|
-
*/
|
|
11883
|
-
MixpanelLib.prototype.has_opted_out_tracking = function(options) {
|
|
11884
|
-
return this._gdpr_call_func(hasOptedOut, options);
|
|
11885
|
-
};
|
|
11886
|
-
|
|
11887
|
-
/**
|
|
11888
|
-
* Clear the user's opt in/out status of data tracking and cookies/localstorage for this Mixpanel instance
|
|
11889
|
-
*
|
|
11890
|
-
* ### Usage
|
|
11891
|
-
*
|
|
11892
|
-
* // clear user's opt-in/out status
|
|
11893
|
-
* mixpanel.clear_opt_in_out_tracking();
|
|
11894
|
-
*
|
|
11895
|
-
* // clear user's opt-in/out status with specific cookie configuration - should match
|
|
11896
|
-
* // configuration used when opt_in_tracking/opt_out_tracking methods were called.
|
|
11897
|
-
* mixpanel.clear_opt_in_out_tracking({
|
|
11898
|
-
* cookie_expiration: 30,
|
|
11899
|
-
* secure_cookie: true
|
|
11900
|
-
* });
|
|
11901
|
-
*
|
|
11902
|
-
* @param {Object} [options] A dictionary of config options to override
|
|
11903
|
-
* @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
|
|
11904
|
-
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
11905
|
-
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
11906
|
-
* @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
|
|
11907
|
-
* @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
|
|
11908
|
-
* @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)
|
|
11909
|
-
* @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)
|
|
11910
|
-
* @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)
|
|
11911
|
-
*/
|
|
11912
|
-
MixpanelLib.prototype.clear_opt_in_out_tracking = function(options) {
|
|
11913
|
-
options = _.extend({
|
|
11914
|
-
'enable_persistence': true
|
|
11915
|
-
}, options);
|
|
11916
|
-
|
|
11917
|
-
this._gdpr_call_func(clearOptInOut, options);
|
|
11918
|
-
this._gdpr_update_persistence(options);
|
|
11919
|
-
};
|
|
11920
|
-
|
|
11921
|
-
MixpanelLib.prototype.report_error = function(msg, err) {
|
|
11922
|
-
console$1.error.apply(console$1.error, arguments);
|
|
11923
|
-
try {
|
|
11924
|
-
if (!err && !(msg instanceof Error)) {
|
|
11925
|
-
msg = new Error(msg);
|
|
11926
|
-
}
|
|
11927
|
-
this.get_config('error_reporter')(msg, err);
|
|
11928
|
-
} catch(err) {
|
|
11929
|
-
console$1.error(err);
|
|
11930
|
-
}
|
|
11931
|
-
};
|
|
11932
|
-
|
|
11933
|
-
// EXPORTS (for closure compiler)
|
|
11934
|
-
|
|
11935
|
-
// MixpanelLib Exports
|
|
11936
|
-
MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
|
|
11937
|
-
MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
|
|
11938
|
-
MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
|
|
11939
|
-
MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
|
|
11940
|
-
MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
|
|
11941
|
-
MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
|
|
11942
|
-
MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
|
|
11943
|
-
MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
|
|
11944
|
-
MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
|
|
11945
|
-
MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
|
|
11946
|
-
MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
|
|
11947
|
-
MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
|
|
11948
|
-
MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
|
|
11949
|
-
MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
|
|
11950
|
-
MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
|
|
11951
|
-
MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
|
|
11952
|
-
MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
|
|
11953
|
-
MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
|
|
11954
|
-
MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
|
|
11955
|
-
MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
|
|
11956
|
-
MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
|
|
11957
|
-
MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
|
|
11958
|
-
MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
|
|
11959
|
-
MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
|
|
11960
|
-
MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
|
|
11961
|
-
MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
|
|
11962
|
-
MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
|
|
11963
|
-
MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
|
|
11964
|
-
MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
|
|
11965
|
-
MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
|
|
11966
|
-
MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
|
|
11967
|
-
|
|
11968
|
-
// MixpanelPersistence Exports
|
|
11969
|
-
MixpanelPersistence.prototype['properties'] = MixpanelPersistence.prototype.properties;
|
|
11970
|
-
MixpanelPersistence.prototype['update_search_keyword'] = MixpanelPersistence.prototype.update_search_keyword;
|
|
11971
|
-
MixpanelPersistence.prototype['update_referrer_info'] = MixpanelPersistence.prototype.update_referrer_info;
|
|
11972
|
-
MixpanelPersistence.prototype['get_cross_subdomain'] = MixpanelPersistence.prototype.get_cross_subdomain;
|
|
11973
|
-
MixpanelPersistence.prototype['clear'] = MixpanelPersistence.prototype.clear;
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
var instances = {};
|
|
11977
|
-
var extend_mp = function() {
|
|
11978
|
-
// add all the sub mixpanel instances
|
|
11979
|
-
_.each(instances, function(instance, name) {
|
|
11980
|
-
if (name !== PRIMARY_INSTANCE_NAME) { mixpanel_master[name] = instance; }
|
|
11981
|
-
});
|
|
11982
|
-
|
|
11983
|
-
// add private functions as _
|
|
11984
|
-
mixpanel_master['_'] = _;
|
|
11985
|
-
};
|
|
11986
|
-
|
|
11987
|
-
var override_mp_init_func = function() {
|
|
11988
|
-
// we override the snippets init function to handle the case where a
|
|
11989
|
-
// user initializes the mixpanel library after the script loads & runs
|
|
11990
|
-
mixpanel_master['init'] = function(token, config, name) {
|
|
11991
|
-
if (name) {
|
|
11992
|
-
// initialize a sub library
|
|
11993
|
-
if (!mixpanel_master[name]) {
|
|
11994
|
-
mixpanel_master[name] = instances[name] = create_mplib(token, config, name);
|
|
11995
|
-
mixpanel_master[name]._loaded();
|
|
11996
|
-
}
|
|
11997
|
-
return mixpanel_master[name];
|
|
11998
|
-
} else {
|
|
11999
|
-
var instance = mixpanel_master;
|
|
12000
|
-
|
|
12001
|
-
if (instances[PRIMARY_INSTANCE_NAME]) {
|
|
12002
|
-
// main mixpanel lib already initialized
|
|
12003
|
-
instance = instances[PRIMARY_INSTANCE_NAME];
|
|
12004
|
-
} else if (token) {
|
|
12005
|
-
// intialize the main mixpanel lib
|
|
12006
|
-
instance = create_mplib(token, config, PRIMARY_INSTANCE_NAME);
|
|
12007
|
-
instance._loaded();
|
|
12008
|
-
instances[PRIMARY_INSTANCE_NAME] = instance;
|
|
12009
|
-
}
|
|
12010
|
-
|
|
12011
|
-
mixpanel_master = instance;
|
|
12012
|
-
if (init_type === INIT_SNIPPET) {
|
|
12013
|
-
window$1[PRIMARY_INSTANCE_NAME] = mixpanel_master;
|
|
12014
|
-
}
|
|
12015
|
-
extend_mp();
|
|
12016
|
-
}
|
|
12017
|
-
};
|
|
12018
|
-
};
|
|
12019
|
-
|
|
12020
|
-
var add_dom_loaded_handler = function() {
|
|
12021
|
-
// Cross browser DOM Loaded support
|
|
12022
|
-
function dom_loaded_handler() {
|
|
12023
|
-
// function flag since we only want to execute this once
|
|
12024
|
-
if (dom_loaded_handler.done) { return; }
|
|
12025
|
-
dom_loaded_handler.done = true;
|
|
12026
|
-
|
|
12027
|
-
DOM_LOADED = true;
|
|
12028
|
-
ENQUEUE_REQUESTS = false;
|
|
12029
|
-
|
|
12030
|
-
_.each(instances, function(inst) {
|
|
12031
|
-
inst._dom_loaded();
|
|
12032
|
-
});
|
|
12033
|
-
}
|
|
12034
|
-
|
|
12035
|
-
function do_scroll_check() {
|
|
12036
|
-
try {
|
|
12037
|
-
document$1.documentElement.doScroll('left');
|
|
12038
|
-
} catch(e) {
|
|
12039
|
-
setTimeout(do_scroll_check, 1);
|
|
12040
|
-
return;
|
|
12041
|
-
}
|
|
12042
|
-
|
|
12043
|
-
dom_loaded_handler();
|
|
12044
|
-
}
|
|
12045
|
-
|
|
12046
|
-
if (document$1.addEventListener) {
|
|
12047
|
-
if (document$1.readyState === 'complete') {
|
|
12048
|
-
// safari 4 can fire the DOMContentLoaded event before loading all
|
|
12049
|
-
// external JS (including this file). you will see some copypasta
|
|
12050
|
-
// on the internet that checks for 'complete' and 'loaded', but
|
|
12051
|
-
// 'loaded' is an IE thing
|
|
12052
|
-
dom_loaded_handler();
|
|
12053
|
-
} else {
|
|
12054
|
-
document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false);
|
|
12055
|
-
}
|
|
12056
|
-
} else if (document$1.attachEvent) {
|
|
12057
|
-
// IE
|
|
12058
|
-
document$1.attachEvent('onreadystatechange', dom_loaded_handler);
|
|
12059
|
-
|
|
12060
|
-
// check to make sure we arn't in a frame
|
|
12061
|
-
var toplevel = false;
|
|
12062
|
-
try {
|
|
12063
|
-
toplevel = window$1.frameElement === null;
|
|
12064
|
-
} catch(e) {
|
|
12065
|
-
// noop
|
|
12066
|
-
}
|
|
12067
|
-
|
|
12068
|
-
if (document$1.documentElement.doScroll && toplevel) {
|
|
12069
|
-
do_scroll_check();
|
|
12070
|
-
}
|
|
12071
|
-
}
|
|
12072
|
-
|
|
12073
|
-
// fallback handler, always will work
|
|
12074
|
-
_.register_event(window$1, 'load', dom_loaded_handler, true);
|
|
12075
|
-
};
|
|
12076
|
-
|
|
12077
|
-
function init_as_module() {
|
|
12078
|
-
init_type = INIT_MODULE;
|
|
12079
|
-
mixpanel_master = new MixpanelLib();
|
|
12080
|
-
|
|
12081
|
-
override_mp_init_func();
|
|
12082
|
-
mixpanel_master['init']();
|
|
12083
|
-
add_dom_loaded_handler();
|
|
12084
|
-
|
|
12085
|
-
return mixpanel_master;
|
|
12086
|
-
}
|
|
12087
|
-
|
|
12088
|
-
var mixpanel = init_as_module();
|
|
12089
|
-
|
|
12090
|
-
var mixpanel_cjs = mixpanel;
|
|
12091
|
-
|
|
12092
|
-
var mixpanel$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), mixpanel_cjs, {
|
|
12093
|
-
'default': mixpanel_cjs
|
|
12094
|
-
}));
|
|
12095
|
-
|
|
12096
|
-
// Needed to avoid error in CJS builds on some bundlers.
|
|
12097
|
-
const mixpanelLib = mixpanel_cjs || mixpanel$1;
|
|
12098
|
-
let mixpanelInstance;
|
|
12099
|
-
const MIXPANEL_EVENT = {
|
|
12100
|
-
VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
|
|
12101
|
-
VISUAL_SDK_CALLED_INIT: 'visual-sdk-called-init',
|
|
12102
|
-
VISUAL_SDK_RENDER_COMPLETE: 'visual-sdk-render-complete',
|
|
12103
|
-
VISUAL_SDK_RENDER_FAILED: 'visual-sdk-render-failed',
|
|
12104
|
-
VISUAL_SDK_TRIGGER: 'visual-sdk-trigger',
|
|
12105
|
-
VISUAL_SDK_ON: 'visual-sdk-on',
|
|
12106
|
-
VISUAL_SDK_IFRAME_LOAD_PERFORMANCE: 'visual-sdk-iframe-load-performance',
|
|
12107
|
-
VISUAL_SDK_EMBED_CREATE: 'visual-sdk-embed-create',
|
|
12108
|
-
VERCEL_INTEGRATION_COMPLETED: 'vercel-integration-completed',
|
|
12109
|
-
};
|
|
12110
|
-
let isMixpanelInitialized = false;
|
|
12111
|
-
let eventQueue = [];
|
|
12112
|
-
/**
|
|
12113
|
-
* Pushes the event with its Property key-value map to mixpanel.
|
|
12114
|
-
*
|
|
12115
|
-
* @param eventId
|
|
12116
|
-
* @param eventProps
|
|
12117
|
-
*/
|
|
12118
|
-
function uploadMixpanelEvent(eventId, eventProps = {}) {
|
|
12119
|
-
if (!isMixpanelInitialized) {
|
|
12120
|
-
eventQueue.push({ eventId, eventProps });
|
|
12121
|
-
return;
|
|
12122
|
-
}
|
|
12123
|
-
mixpanelInstance.track(eventId, eventProps);
|
|
12124
|
-
}
|
|
12125
|
-
/**
|
|
12126
|
-
*
|
|
12127
|
-
*/
|
|
12128
|
-
function emptyQueue() {
|
|
12129
|
-
if (!isMixpanelInitialized) {
|
|
12130
|
-
return;
|
|
12131
|
-
}
|
|
12132
|
-
eventQueue.forEach((event) => {
|
|
12133
|
-
uploadMixpanelEvent(event.eventId, event.eventProps);
|
|
12134
|
-
});
|
|
12135
|
-
eventQueue = [];
|
|
12136
|
-
}
|
|
12137
|
-
/**
|
|
12138
|
-
*
|
|
12139
|
-
* @param sessionInfo
|
|
12140
|
-
*/
|
|
12141
|
-
function initMixpanel(sessionInfo) {
|
|
12142
|
-
var _a;
|
|
12143
|
-
if (!sessionInfo || !sessionInfo.mixpanelToken) {
|
|
12144
|
-
return;
|
|
12145
|
-
}
|
|
12146
|
-
// On a public cluster the user is anonymous, so don't set the identify to
|
|
12147
|
-
// userGUID
|
|
12148
|
-
const isPublicCluster = !!sessionInfo.isPublicUser;
|
|
12149
|
-
const token = sessionInfo.mixpanelToken;
|
|
12150
|
-
try {
|
|
12151
|
-
if (token) {
|
|
12152
|
-
mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
|
|
12153
|
-
if (!isPublicCluster) {
|
|
12154
|
-
mixpanelInstance.identify(sessionInfo.userGUID);
|
|
12155
|
-
}
|
|
12156
|
-
mixpanelInstance.register_once({
|
|
12157
|
-
clusterId: sessionInfo.clusterId,
|
|
12158
|
-
clusterName: sessionInfo.clusterName,
|
|
12159
|
-
releaseVersion: sessionInfo.releaseVersion,
|
|
12160
|
-
hostAppUrl: ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '',
|
|
12161
|
-
});
|
|
12162
|
-
isMixpanelInitialized = true;
|
|
12163
|
-
emptyQueue();
|
|
12164
|
-
}
|
|
12165
|
-
}
|
|
12166
|
-
catch (e) {
|
|
12167
|
-
logger.error('Error initializing mixpanel', e);
|
|
12168
|
-
}
|
|
12169
|
-
}
|
|
12170
|
-
|
|
12171
|
-
let config = {};
|
|
12172
|
-
/**
|
|
12173
|
-
* Gets the configuration embed was initialized with.
|
|
12174
|
-
*
|
|
12175
|
-
* @returns {@link EmbedConfig} The configuration embed was initialized with.
|
|
12176
|
-
* @version SDK: 1.19.0 | ThoughtSpot: *
|
|
12177
|
-
* @group Global methods
|
|
12178
|
-
*/
|
|
12179
|
-
const getEmbedConfig = () => config;
|
|
12180
|
-
|
|
12181
|
-
/**
|
|
12182
|
-
* Fetch wrapper that adds the authentication token to the request.
|
|
12183
|
-
* Use this to call the ThoughtSpot APIs when using the visual embed sdk.
|
|
12184
|
-
*
|
|
12185
|
-
* @param input
|
|
12186
|
-
* @param init
|
|
12187
|
-
* @version SDK: 1.28.0
|
|
12188
|
-
* @group Global methods
|
|
12189
|
-
*/
|
|
12190
|
-
const tokenizedFetch = async (input, init) => {
|
|
12191
|
-
const embedConfig = getEmbedConfig();
|
|
12192
|
-
if (embedConfig.authType !== AuthType.TrustedAuthTokenCookieless) {
|
|
12193
|
-
return fetch(input, init);
|
|
12194
|
-
}
|
|
12195
|
-
const req = new Request(input, init);
|
|
12196
|
-
const authToken = await getAuthenticationToken(embedConfig);
|
|
12197
|
-
if (authToken) {
|
|
12198
|
-
req.headers.append('Authorization', `Bearer ${authToken}`);
|
|
12199
|
-
}
|
|
12200
|
-
return fetch(req);
|
|
12201
|
-
};
|
|
12202
|
-
|
|
12203
|
-
/**
|
|
12204
|
-
*
|
|
12205
|
-
* @param url
|
|
12206
|
-
* @param options
|
|
12207
|
-
*/
|
|
12208
|
-
function tokenisedFailureLoggedFetch(url, options = {}) {
|
|
12209
|
-
return tokenizedFetch(url, options).then(async (r) => {
|
|
12210
|
-
var _a;
|
|
12211
|
-
if (!r.ok && r.type !== 'opaqueredirect' && r.type !== 'opaque') {
|
|
12212
|
-
logger.error('Failure', await ((_a = r.text) === null || _a === void 0 ? void 0 : _a.call(r)));
|
|
12213
|
-
}
|
|
12214
|
-
return r;
|
|
12215
|
-
});
|
|
12216
|
-
}
|
|
12217
|
-
/**
|
|
12218
|
-
*
|
|
12219
|
-
* @param authVerificationUrl
|
|
12220
|
-
*/
|
|
12221
|
-
function fetchSessionInfoService(authVerificationUrl) {
|
|
12222
|
-
return tokenisedFailureLoggedFetch(authVerificationUrl, {
|
|
12223
|
-
credentials: 'include',
|
|
12224
|
-
});
|
|
12225
|
-
}
|
|
12226
|
-
|
|
12227
|
-
// eslint-disable-next-line import/no-mutable-exports
|
|
12228
|
-
let loggedInStatus = false;
|
|
12229
|
-
// eslint-disable-next-line import/no-mutable-exports
|
|
12230
|
-
let samlAuthWindow = null;
|
|
12231
|
-
// eslint-disable-next-line import/no-mutable-exports
|
|
12232
|
-
let samlCompletionPromise = null;
|
|
12233
|
-
let sessionInfo = null;
|
|
12234
|
-
let sessionInfoResolver = null;
|
|
12235
|
-
const sessionInfoPromise = new Promise((resolve) => {
|
|
12236
|
-
sessionInfoResolver = resolve;
|
|
12237
|
-
});
|
|
12238
|
-
let releaseVersion = '';
|
|
12239
|
-
const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
|
|
12240
|
-
/**
|
|
12241
|
-
* Enum for auth failure types. This is the parameter passed to the listner
|
|
12242
|
-
* of {@link AuthStatus.FAILURE}.
|
|
12243
|
-
*
|
|
12244
|
-
* @group Authentication / Init
|
|
12245
|
-
*/
|
|
12246
|
-
var AuthFailureType;
|
|
12247
|
-
(function (AuthFailureType) {
|
|
12248
|
-
AuthFailureType["SDK"] = "SDK";
|
|
12249
|
-
AuthFailureType["NO_COOKIE_ACCESS"] = "NO_COOKIE_ACCESS";
|
|
12250
|
-
AuthFailureType["EXPIRY"] = "EXPIRY";
|
|
12251
|
-
AuthFailureType["OTHER"] = "OTHER";
|
|
12252
|
-
})(AuthFailureType || (AuthFailureType = {}));
|
|
12253
|
-
/**
|
|
12254
|
-
* Enum for auth status emitted by the emitter returned from {@link init}.
|
|
12255
|
-
*
|
|
12256
|
-
* @group Authentication / Init
|
|
12257
|
-
*/
|
|
12258
|
-
var AuthStatus;
|
|
12259
|
-
(function (AuthStatus) {
|
|
12260
|
-
/**
|
|
12261
|
-
* Emits when the SDK fails to authenticate
|
|
12262
|
-
*/
|
|
12263
|
-
AuthStatus["FAILURE"] = "FAILURE";
|
|
12264
|
-
/**
|
|
12265
|
-
* Emits when the SDK authenticates successfully
|
|
12266
|
-
*/
|
|
12267
|
-
AuthStatus["SDK_SUCCESS"] = "SDK_SUCCESS";
|
|
12268
|
-
/**
|
|
12269
|
-
* Emits when the app sends an authentication success message
|
|
12270
|
-
*/
|
|
12271
|
-
AuthStatus["SUCCESS"] = "SUCCESS";
|
|
12272
|
-
/**
|
|
12273
|
-
* Emits when a user logs out
|
|
12274
|
-
*/
|
|
12275
|
-
AuthStatus["LOGOUT"] = "LOGOUT";
|
|
12276
|
-
/**
|
|
12277
|
-
* Emitted when inPopup is true in the SAMLRedirect flow and the
|
|
12278
|
-
* popup is waiting to be triggered either programmatically
|
|
12279
|
-
* or by the trigger button.
|
|
12280
|
-
*
|
|
12281
|
-
* @version SDK: 1.19.0
|
|
12282
|
-
*/
|
|
12283
|
-
AuthStatus["WAITING_FOR_POPUP"] = "WAITING_FOR_POPUP";
|
|
12284
|
-
})(AuthStatus || (AuthStatus = {}));
|
|
12285
|
-
/**
|
|
12286
|
-
* Events which can be triggered on the emitter returned from {@link init}.
|
|
12287
|
-
*
|
|
12288
|
-
* @group Authentication / Init
|
|
12289
|
-
*/
|
|
12290
|
-
var AuthEvent;
|
|
12291
|
-
(function (AuthEvent) {
|
|
12292
|
-
/**
|
|
12293
|
-
* Manually trigger the SSO popup. This is useful when
|
|
12294
|
-
* authStatus is SAMLRedirect/OIDCRedirect and inPopup is set to true
|
|
12295
|
-
*/
|
|
12296
|
-
AuthEvent["TRIGGER_SSO_POPUP"] = "TRIGGER_SSO_POPUP";
|
|
12297
|
-
})(AuthEvent || (AuthEvent = {}));
|
|
12298
|
-
/**
|
|
12299
|
-
*
|
|
12300
|
-
*/
|
|
12301
|
-
function notifyAuthSDKSuccess() {
|
|
12302
|
-
{
|
|
12303
|
-
logger.error('SDK not initialized');
|
|
12304
|
-
return;
|
|
12305
|
-
}
|
|
12306
|
-
}
|
|
12307
|
-
/**
|
|
12308
|
-
*
|
|
12309
|
-
*/
|
|
12310
|
-
function notifyAuthSuccess() {
|
|
12311
|
-
{
|
|
12312
|
-
logger.error('SDK not initialized');
|
|
12313
|
-
return;
|
|
12314
|
-
}
|
|
12315
|
-
}
|
|
12316
|
-
/**
|
|
12317
|
-
*
|
|
12318
|
-
* @param failureType
|
|
12319
|
-
*/
|
|
12320
|
-
function notifyAuthFailure(failureType) {
|
|
12321
|
-
{
|
|
12322
|
-
logger.error('SDK not initialized');
|
|
12323
|
-
return;
|
|
12324
|
-
}
|
|
12325
|
-
}
|
|
12326
|
-
/**
|
|
12327
|
-
*
|
|
12328
|
-
*/
|
|
12329
|
-
function notifyLogout() {
|
|
12330
|
-
{
|
|
12331
|
-
logger.error('SDK not initialized');
|
|
12332
|
-
return;
|
|
12333
|
-
}
|
|
12334
|
-
}
|
|
12335
|
-
const initSession = (sessionDetails) => {
|
|
12336
|
-
const embedConfig = getEmbedConfig();
|
|
12337
|
-
if (sessionInfo == null) {
|
|
12338
|
-
sessionInfo = sessionDetails;
|
|
12339
|
-
if (!embedConfig.disableSDKTracking) {
|
|
12340
|
-
initMixpanel(sessionInfo);
|
|
12341
|
-
}
|
|
12342
|
-
sessionInfoResolver(sessionInfo);
|
|
12343
|
-
}
|
|
12344
|
-
};
|
|
12345
|
-
const getSessionDetails = (sessionInfoResp) => {
|
|
12346
|
-
const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
|
|
12347
|
-
const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
|
|
12348
|
-
const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
|
|
12349
|
-
? prodMixpanelToken
|
|
12350
|
-
: devMixpanelToken;
|
|
12351
|
-
return {
|
|
12352
|
-
userGUID: sessionInfoResp.userGUID,
|
|
12353
|
-
mixpanelToken,
|
|
12354
|
-
isPublicUser: sessionInfoResp.configInfo.isPublicUser,
|
|
12355
|
-
releaseVersion: sessionInfoResp.releaseVersion,
|
|
12356
|
-
clusterId: sessionInfoResp.configInfo.selfClusterId,
|
|
12357
|
-
clusterName: sessionInfoResp.configInfo.selfClusterName,
|
|
12358
|
-
...sessionInfoResp,
|
|
12359
|
-
};
|
|
12360
|
-
};
|
|
12361
|
-
/**
|
|
12362
|
-
* Check if we are logged into the ThoughtSpot cluster
|
|
12363
|
-
*
|
|
12364
|
-
* @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
|
|
12365
|
-
*/
|
|
12366
|
-
async function isLoggedIn(thoughtSpotHost) {
|
|
12367
|
-
const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
|
|
12368
|
-
let response = null;
|
|
12369
|
-
try {
|
|
12370
|
-
response = await fetchSessionInfoService(authVerificationUrl);
|
|
12371
|
-
const sessionInfoResp = await response.json();
|
|
12372
|
-
const sessionDetails = getSessionDetails(sessionInfoResp);
|
|
12373
|
-
// Store user session details from session info
|
|
12374
|
-
initSession(sessionDetails);
|
|
12375
|
-
releaseVersion = sessionInfoResp.releaseVersion;
|
|
12376
|
-
}
|
|
12377
|
-
catch (e) {
|
|
12378
|
-
return false;
|
|
12379
|
-
}
|
|
12380
|
-
return response.status === 200;
|
|
12381
|
-
}
|
|
12382
|
-
/**
|
|
12383
|
-
* Return releaseVersion if available
|
|
12384
|
-
*/
|
|
12385
|
-
function getReleaseVersion() {
|
|
12386
|
-
return releaseVersion;
|
|
12387
|
-
}
|
|
12388
|
-
/**
|
|
12389
|
-
* Check if we are stuck at the SSO redirect URL
|
|
12390
|
-
*/
|
|
12391
|
-
function isAtSSORedirectUrl() {
|
|
12392
|
-
return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
|
|
12393
|
-
}
|
|
12394
|
-
/**
|
|
12395
|
-
* Remove the SSO redirect URL marker
|
|
12396
|
-
*/
|
|
12397
|
-
function removeSSORedirectUrlMarker() {
|
|
12398
|
-
// Note (sunny): This will leave a # around even if it was not in the URL
|
|
12399
|
-
// to begin with. Trying to remove the hash by changing window.location will
|
|
12400
|
-
// reload the page which we don't want. We'll live with adding an
|
|
12401
|
-
// unnecessary hash to the parent page URL until we find any use case where
|
|
12402
|
-
// that creates an issue.
|
|
12403
|
-
window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
|
|
12404
|
-
}
|
|
12405
|
-
/**
|
|
12406
|
-
* Perform token based authentication
|
|
12407
|
-
*
|
|
12408
|
-
* @param embedConfig The embed configuration
|
|
12409
|
-
*/
|
|
12410
|
-
const doTokenAuth = async (embedConfig) => {
|
|
12411
|
-
const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
|
|
12412
|
-
if (!authEndpoint && !getAuthToken) {
|
|
12413
|
-
throw new Error('Either auth endpoint or getAuthToken function must be provided');
|
|
12414
|
-
}
|
|
12415
|
-
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
12416
|
-
if (!loggedInStatus) {
|
|
12417
|
-
const authToken = await getAuthenticationToken(embedConfig);
|
|
12418
|
-
let resp;
|
|
12419
|
-
try {
|
|
12420
|
-
resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
|
|
12421
|
-
}
|
|
12422
|
-
catch (e) {
|
|
12423
|
-
resp = await fetchAuthService(thoughtSpotHost, username, authToken);
|
|
12424
|
-
}
|
|
12425
|
-
// token login issues a 302 when successful
|
|
12426
|
-
loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
|
|
12427
|
-
if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
|
|
12428
|
-
// When 3rd party cookie access is blocked, this will fail because
|
|
12429
|
-
// cookies will not be sent with the call.
|
|
12430
|
-
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
12431
|
-
}
|
|
12432
|
-
}
|
|
12433
|
-
return loggedInStatus;
|
|
12434
|
-
};
|
|
12435
|
-
/**
|
|
12436
|
-
* Validate embedConfig parameters required for cookielessTokenAuth
|
|
12437
|
-
*
|
|
12438
|
-
* @param embedConfig The embed configuration
|
|
12439
|
-
*/
|
|
12440
|
-
const doCookielessTokenAuth = async (embedConfig) => {
|
|
12441
|
-
const { authEndpoint, getAuthToken } = embedConfig;
|
|
12442
|
-
if (!authEndpoint && !getAuthToken) {
|
|
12443
|
-
throw new Error('Either auth endpoint or getAuthToken function must be provided');
|
|
12444
|
-
}
|
|
12445
|
-
let authSuccess = false;
|
|
12446
|
-
try {
|
|
12447
|
-
const authToken = await getAuthenticationToken(embedConfig);
|
|
12448
|
-
if (authToken) {
|
|
12449
|
-
authSuccess = true;
|
|
12450
|
-
}
|
|
12451
|
-
}
|
|
12452
|
-
catch {
|
|
12453
|
-
authSuccess = false;
|
|
12454
|
-
}
|
|
12455
|
-
return authSuccess;
|
|
12456
|
-
};
|
|
12457
|
-
/**
|
|
12458
|
-
* Perform basic authentication to the ThoughtSpot cluster using the cluster
|
|
12459
|
-
* credentials.
|
|
12460
|
-
*
|
|
12461
|
-
* Warning: This feature is primarily intended for developer testing. It is
|
|
12462
|
-
* strongly advised not to use this authentication method in production.
|
|
12463
|
-
*
|
|
12464
|
-
* @param embedConfig The embed configuration
|
|
12465
|
-
*/
|
|
12466
|
-
const doBasicAuth = async (embedConfig) => {
|
|
12467
|
-
const { thoughtSpotHost, username, password } = embedConfig;
|
|
12468
|
-
const loggedIn = await isLoggedIn(thoughtSpotHost);
|
|
12469
|
-
if (!loggedIn) {
|
|
12470
|
-
const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
|
|
12471
|
-
loggedInStatus = response.ok;
|
|
12472
|
-
if (embedConfig.detectCookieAccessSlow) {
|
|
12473
|
-
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
12474
|
-
}
|
|
12475
|
-
}
|
|
12476
|
-
else {
|
|
12477
|
-
loggedInStatus = true;
|
|
12478
|
-
}
|
|
12479
|
-
return loggedInStatus;
|
|
12480
|
-
};
|
|
12481
|
-
/**
|
|
12482
|
-
*
|
|
12483
|
-
* @param ssoURL
|
|
12484
|
-
* @param triggerContainer
|
|
12485
|
-
* @param triggerText
|
|
12486
|
-
*/
|
|
12487
|
-
async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
|
|
12488
|
-
const openPopup = () => {
|
|
12489
|
-
if (samlAuthWindow === null || samlAuthWindow.closed) {
|
|
12490
|
-
samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
|
|
12491
|
-
}
|
|
12492
|
-
else {
|
|
12493
|
-
samlAuthWindow.focus();
|
|
12494
|
-
}
|
|
12495
|
-
};
|
|
12496
|
-
const containerEl = getDOMNode(triggerContainer);
|
|
12497
|
-
if (containerEl) {
|
|
12498
|
-
containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
|
|
12499
|
-
const authElem = document.getElementById('ts-auth-btn');
|
|
12500
|
-
authElem.textContent = triggerText;
|
|
12501
|
-
authElem.addEventListener('click', openPopup, { once: true });
|
|
12502
|
-
}
|
|
12503
|
-
samlCompletionPromise = samlCompletionPromise
|
|
12504
|
-
|| new Promise((resolve, reject) => {
|
|
12505
|
-
window.addEventListener('message', (e) => {
|
|
12506
|
-
if (e.data.type === EmbedEvent.SAMLComplete) {
|
|
12507
|
-
e.source.close();
|
|
12508
|
-
resolve();
|
|
12509
|
-
}
|
|
12510
|
-
});
|
|
12511
|
-
});
|
|
12512
|
-
return samlCompletionPromise;
|
|
12513
|
-
}
|
|
12514
|
-
/**
|
|
12515
|
-
* Perform SAML authentication
|
|
12516
|
-
*
|
|
12517
|
-
* @param embedConfig The embed configuration
|
|
12518
|
-
* @param ssoEndPoint
|
|
12519
|
-
*/
|
|
12520
|
-
const doSSOAuth = async (embedConfig, ssoEndPoint) => {
|
|
12521
|
-
const { thoughtSpotHost } = embedConfig;
|
|
12522
|
-
const loggedIn = await isLoggedIn(thoughtSpotHost);
|
|
12523
|
-
if (loggedIn) {
|
|
12524
|
-
if (isAtSSORedirectUrl()) {
|
|
12525
|
-
removeSSORedirectUrlMarker();
|
|
12526
|
-
}
|
|
12527
|
-
loggedInStatus = true;
|
|
12528
|
-
return;
|
|
12529
|
-
}
|
|
12530
|
-
// we have already tried authentication and it did not succeed, restore
|
|
12531
|
-
// the current URL to the original one and invoke the callback.
|
|
12532
|
-
if (isAtSSORedirectUrl()) {
|
|
12533
|
-
removeSSORedirectUrlMarker();
|
|
12534
|
-
loggedInStatus = false;
|
|
12535
|
-
return;
|
|
12536
|
-
}
|
|
12537
|
-
const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
|
|
12538
|
-
if (embedConfig.inPopup) {
|
|
12539
|
-
await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
|
|
12540
|
-
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
12541
|
-
return;
|
|
12542
|
-
}
|
|
12543
|
-
window.location.href = ssoURL;
|
|
12544
|
-
};
|
|
12545
|
-
const doSamlAuth = async (embedConfig) => {
|
|
12546
|
-
const { thoughtSpotHost } = embedConfig;
|
|
12547
|
-
// redirect for SSO, when the SSO authentication is done, this page will be
|
|
12548
|
-
// loaded again and the same JS will execute again.
|
|
12549
|
-
const ssoRedirectUrl = embedConfig.inPopup
|
|
12550
|
-
? `${thoughtSpotHost}/v2/#/embed/saml-complete`
|
|
12551
|
-
: getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
|
|
12552
|
-
// bring back the page to the same URL
|
|
12553
|
-
const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
|
|
12554
|
-
await doSSOAuth(embedConfig, ssoEndPoint);
|
|
12555
|
-
return loggedInStatus;
|
|
12556
|
-
};
|
|
12557
|
-
const doOIDCAuth = async (embedConfig) => {
|
|
12558
|
-
const { thoughtSpotHost } = embedConfig;
|
|
12559
|
-
// redirect for SSO, when the SSO authentication is done, this page will be
|
|
12560
|
-
// loaded again and the same JS will execute again.
|
|
12561
|
-
const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
|
|
12562
|
-
? `${thoughtSpotHost}/v2/#/embed/saml-complete`
|
|
12563
|
-
: getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
|
|
12564
|
-
// bring back the page to the same URL
|
|
12565
|
-
const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
|
|
12566
|
-
await doSSOAuth(embedConfig, ssoEndPoint);
|
|
12567
|
-
return loggedInStatus;
|
|
12568
|
-
};
|
|
12569
|
-
/**
|
|
12570
|
-
* Perform authentication on the ThoughtSpot cluster
|
|
12571
|
-
*
|
|
12572
|
-
* @param embedConfig The embed configuration
|
|
12573
|
-
*/
|
|
12574
|
-
const authenticate = async (embedConfig) => {
|
|
12575
|
-
const { authType } = embedConfig;
|
|
12576
|
-
switch (authType) {
|
|
12577
|
-
case AuthType.SSO:
|
|
12578
|
-
case AuthType.SAMLRedirect:
|
|
12579
|
-
case AuthType.SAML:
|
|
12580
|
-
return doSamlAuth(embedConfig);
|
|
12581
|
-
case AuthType.OIDC:
|
|
12582
|
-
case AuthType.OIDCRedirect:
|
|
12583
|
-
return doOIDCAuth(embedConfig);
|
|
12584
|
-
case AuthType.AuthServer:
|
|
12585
|
-
case AuthType.TrustedAuthToken:
|
|
12586
|
-
return doTokenAuth(embedConfig);
|
|
12587
|
-
case AuthType.TrustedAuthTokenCookieless:
|
|
12588
|
-
return doCookielessTokenAuth(embedConfig);
|
|
12589
|
-
case AuthType.Basic:
|
|
12590
|
-
return doBasicAuth(embedConfig);
|
|
12591
|
-
default:
|
|
12592
|
-
return Promise.resolve(true);
|
|
12593
|
-
}
|
|
12359
|
+
if (!_.localStorage.is_supported()) {
|
|
12360
|
+
options['persistence_type'] = 'cookie';
|
|
12361
|
+
}
|
|
12362
|
+
|
|
12363
|
+
return func(this.get_config('token'), {
|
|
12364
|
+
track: options['track'],
|
|
12365
|
+
trackEventName: options['track_event_name'],
|
|
12366
|
+
trackProperties: options['track_properties'],
|
|
12367
|
+
persistenceType: options['persistence_type'],
|
|
12368
|
+
persistencePrefix: options['cookie_prefix'],
|
|
12369
|
+
cookieDomain: options['cookie_domain'],
|
|
12370
|
+
cookieExpiration: options['cookie_expiration'],
|
|
12371
|
+
crossSiteCookie: options['cross_site_cookie'],
|
|
12372
|
+
crossSubdomainCookie: options['cross_subdomain_cookie'],
|
|
12373
|
+
secureCookie: options['secure_cookie'],
|
|
12374
|
+
ignoreDnt: options['ignore_dnt']
|
|
12375
|
+
});
|
|
12376
|
+
};
|
|
12377
|
+
|
|
12378
|
+
/**
|
|
12379
|
+
* Opt the user in to data tracking and cookies/localstorage for this Mixpanel instance
|
|
12380
|
+
*
|
|
12381
|
+
* ### Usage
|
|
12382
|
+
*
|
|
12383
|
+
* // opt user in
|
|
12384
|
+
* mixpanel.opt_in_tracking();
|
|
12385
|
+
*
|
|
12386
|
+
* // opt user in with specific event name, properties, cookie configuration
|
|
12387
|
+
* mixpanel.opt_in_tracking({
|
|
12388
|
+
* track_event_name: 'User opted in',
|
|
12389
|
+
* track_event_properties: {
|
|
12390
|
+
* 'Email': 'jdoe@example.com'
|
|
12391
|
+
* },
|
|
12392
|
+
* cookie_expiration: 30,
|
|
12393
|
+
* secure_cookie: true
|
|
12394
|
+
* });
|
|
12395
|
+
*
|
|
12396
|
+
* @param {Object} [options] A dictionary of config options to override
|
|
12397
|
+
* @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)
|
|
12398
|
+
* @param {string} [options.track_event_name=$opt_in] Event name to be used for tracking the opt-in action
|
|
12399
|
+
* @param {Object} [options.track_properties] Set of properties to be tracked along with the opt-in action
|
|
12400
|
+
* @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
|
|
12401
|
+
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
12402
|
+
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
12403
|
+
* @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
|
|
12404
|
+
* @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
|
|
12405
|
+
* @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)
|
|
12406
|
+
* @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)
|
|
12407
|
+
* @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)
|
|
12408
|
+
*/
|
|
12409
|
+
MixpanelLib.prototype.opt_in_tracking = function(options) {
|
|
12410
|
+
options = _.extend({
|
|
12411
|
+
'enable_persistence': true
|
|
12412
|
+
}, options);
|
|
12413
|
+
|
|
12414
|
+
this._gdpr_call_func(optIn, options);
|
|
12415
|
+
this._gdpr_update_persistence(options);
|
|
12416
|
+
};
|
|
12417
|
+
|
|
12418
|
+
/**
|
|
12419
|
+
* Opt the user out of data tracking and cookies/localstorage for this Mixpanel instance
|
|
12420
|
+
*
|
|
12421
|
+
* ### Usage
|
|
12422
|
+
*
|
|
12423
|
+
* // opt user out
|
|
12424
|
+
* mixpanel.opt_out_tracking();
|
|
12425
|
+
*
|
|
12426
|
+
* // opt user out with different cookie configuration from Mixpanel instance
|
|
12427
|
+
* mixpanel.opt_out_tracking({
|
|
12428
|
+
* cookie_expiration: 30,
|
|
12429
|
+
* secure_cookie: true
|
|
12430
|
+
* });
|
|
12431
|
+
*
|
|
12432
|
+
* @param {Object} [options] A dictionary of config options to override
|
|
12433
|
+
* @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
|
|
12434
|
+
* @param {boolean} [options.clear_persistence=true] If true, will delete all data stored by the sdk in persistence
|
|
12435
|
+
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
12436
|
+
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
12437
|
+
* @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
|
|
12438
|
+
* @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
|
|
12439
|
+
* @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)
|
|
12440
|
+
* @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)
|
|
12441
|
+
* @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)
|
|
12442
|
+
*/
|
|
12443
|
+
MixpanelLib.prototype.opt_out_tracking = function(options) {
|
|
12444
|
+
options = _.extend({
|
|
12445
|
+
'clear_persistence': true,
|
|
12446
|
+
'delete_user': true
|
|
12447
|
+
}, options);
|
|
12448
|
+
|
|
12449
|
+
// delete user and clear charges since these methods may be disabled by opt-out
|
|
12450
|
+
if (options['delete_user'] && this['people'] && this['people']._identify_called()) {
|
|
12451
|
+
this['people'].delete_user();
|
|
12452
|
+
this['people'].clear_charges();
|
|
12453
|
+
}
|
|
12454
|
+
|
|
12455
|
+
this._gdpr_call_func(optOut, options);
|
|
12456
|
+
this._gdpr_update_persistence(options);
|
|
12457
|
+
};
|
|
12458
|
+
|
|
12459
|
+
/**
|
|
12460
|
+
* Check whether the user has opted in to data tracking and cookies/localstorage for this Mixpanel instance
|
|
12461
|
+
*
|
|
12462
|
+
* ### Usage
|
|
12463
|
+
*
|
|
12464
|
+
* var has_opted_in = mixpanel.has_opted_in_tracking();
|
|
12465
|
+
* // use has_opted_in value
|
|
12466
|
+
*
|
|
12467
|
+
* @param {Object} [options] A dictionary of config options to override
|
|
12468
|
+
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
12469
|
+
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
12470
|
+
* @returns {boolean} current opt-in status
|
|
12471
|
+
*/
|
|
12472
|
+
MixpanelLib.prototype.has_opted_in_tracking = function(options) {
|
|
12473
|
+
return this._gdpr_call_func(hasOptedIn, options);
|
|
12474
|
+
};
|
|
12475
|
+
|
|
12476
|
+
/**
|
|
12477
|
+
* Check whether the user has opted out of data tracking and cookies/localstorage for this Mixpanel instance
|
|
12478
|
+
*
|
|
12479
|
+
* ### Usage
|
|
12480
|
+
*
|
|
12481
|
+
* var has_opted_out = mixpanel.has_opted_out_tracking();
|
|
12482
|
+
* // use has_opted_out value
|
|
12483
|
+
*
|
|
12484
|
+
* @param {Object} [options] A dictionary of config options to override
|
|
12485
|
+
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
12486
|
+
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
12487
|
+
* @returns {boolean} current opt-out status
|
|
12488
|
+
*/
|
|
12489
|
+
MixpanelLib.prototype.has_opted_out_tracking = function(options) {
|
|
12490
|
+
return this._gdpr_call_func(hasOptedOut, options);
|
|
12491
|
+
};
|
|
12492
|
+
|
|
12493
|
+
/**
|
|
12494
|
+
* Clear the user's opt in/out status of data tracking and cookies/localstorage for this Mixpanel instance
|
|
12495
|
+
*
|
|
12496
|
+
* ### Usage
|
|
12497
|
+
*
|
|
12498
|
+
* // clear user's opt-in/out status
|
|
12499
|
+
* mixpanel.clear_opt_in_out_tracking();
|
|
12500
|
+
*
|
|
12501
|
+
* // clear user's opt-in/out status with specific cookie configuration - should match
|
|
12502
|
+
* // configuration used when opt_in_tracking/opt_out_tracking methods were called.
|
|
12503
|
+
* mixpanel.clear_opt_in_out_tracking({
|
|
12504
|
+
* cookie_expiration: 30,
|
|
12505
|
+
* secure_cookie: true
|
|
12506
|
+
* });
|
|
12507
|
+
*
|
|
12508
|
+
* @param {Object} [options] A dictionary of config options to override
|
|
12509
|
+
* @param {boolean} [options.enable_persistence=true] If true, will re-enable sdk persistence
|
|
12510
|
+
* @param {string} [options.persistence_type=localStorage] Persistence mechanism used - cookie or localStorage - falls back to cookie if localStorage is unavailable
|
|
12511
|
+
* @param {string} [options.cookie_prefix=__mp_opt_in_out] Custom prefix to be used in the cookie/localstorage name
|
|
12512
|
+
* @param {Number} [options.cookie_expiration] Number of days until the opt-in cookie expires (overrides value specified in this Mixpanel instance's config)
|
|
12513
|
+
* @param {string} [options.cookie_domain] Custom cookie domain (overrides value specified in this Mixpanel instance's config)
|
|
12514
|
+
* @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)
|
|
12515
|
+
* @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)
|
|
12516
|
+
* @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)
|
|
12517
|
+
*/
|
|
12518
|
+
MixpanelLib.prototype.clear_opt_in_out_tracking = function(options) {
|
|
12519
|
+
options = _.extend({
|
|
12520
|
+
'enable_persistence': true
|
|
12521
|
+
}, options);
|
|
12522
|
+
|
|
12523
|
+
this._gdpr_call_func(clearOptInOut, options);
|
|
12524
|
+
this._gdpr_update_persistence(options);
|
|
12525
|
+
};
|
|
12526
|
+
|
|
12527
|
+
MixpanelLib.prototype.report_error = function(msg, err) {
|
|
12528
|
+
console$1.error.apply(console$1.error, arguments);
|
|
12529
|
+
try {
|
|
12530
|
+
if (!err && !(msg instanceof Error)) {
|
|
12531
|
+
msg = new Error(msg);
|
|
12532
|
+
}
|
|
12533
|
+
this.get_config('error_reporter')(msg, err);
|
|
12534
|
+
} catch(err) {
|
|
12535
|
+
console$1.error(err);
|
|
12536
|
+
}
|
|
12537
|
+
};
|
|
12538
|
+
|
|
12539
|
+
// EXPORTS (for closure compiler)
|
|
12540
|
+
|
|
12541
|
+
// MixpanelLib Exports
|
|
12542
|
+
MixpanelLib.prototype['init'] = MixpanelLib.prototype.init;
|
|
12543
|
+
MixpanelLib.prototype['reset'] = MixpanelLib.prototype.reset;
|
|
12544
|
+
MixpanelLib.prototype['disable'] = MixpanelLib.prototype.disable;
|
|
12545
|
+
MixpanelLib.prototype['time_event'] = MixpanelLib.prototype.time_event;
|
|
12546
|
+
MixpanelLib.prototype['track'] = MixpanelLib.prototype.track;
|
|
12547
|
+
MixpanelLib.prototype['track_links'] = MixpanelLib.prototype.track_links;
|
|
12548
|
+
MixpanelLib.prototype['track_forms'] = MixpanelLib.prototype.track_forms;
|
|
12549
|
+
MixpanelLib.prototype['track_pageview'] = MixpanelLib.prototype.track_pageview;
|
|
12550
|
+
MixpanelLib.prototype['register'] = MixpanelLib.prototype.register;
|
|
12551
|
+
MixpanelLib.prototype['register_once'] = MixpanelLib.prototype.register_once;
|
|
12552
|
+
MixpanelLib.prototype['unregister'] = MixpanelLib.prototype.unregister;
|
|
12553
|
+
MixpanelLib.prototype['identify'] = MixpanelLib.prototype.identify;
|
|
12554
|
+
MixpanelLib.prototype['alias'] = MixpanelLib.prototype.alias;
|
|
12555
|
+
MixpanelLib.prototype['name_tag'] = MixpanelLib.prototype.name_tag;
|
|
12556
|
+
MixpanelLib.prototype['set_config'] = MixpanelLib.prototype.set_config;
|
|
12557
|
+
MixpanelLib.prototype['get_config'] = MixpanelLib.prototype.get_config;
|
|
12558
|
+
MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
|
|
12559
|
+
MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
|
|
12560
|
+
MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
|
|
12561
|
+
MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
|
|
12562
|
+
MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
|
|
12563
|
+
MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
|
|
12564
|
+
MixpanelLib.prototype['has_opted_in_tracking'] = MixpanelLib.prototype.has_opted_in_tracking;
|
|
12565
|
+
MixpanelLib.prototype['clear_opt_in_out_tracking'] = MixpanelLib.prototype.clear_opt_in_out_tracking;
|
|
12566
|
+
MixpanelLib.prototype['get_group'] = MixpanelLib.prototype.get_group;
|
|
12567
|
+
MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
|
|
12568
|
+
MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
|
|
12569
|
+
MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
|
|
12570
|
+
MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
|
|
12571
|
+
MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
|
|
12572
|
+
MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
|
|
12573
|
+
|
|
12574
|
+
// MixpanelPersistence Exports
|
|
12575
|
+
MixpanelPersistence.prototype['properties'] = MixpanelPersistence.prototype.properties;
|
|
12576
|
+
MixpanelPersistence.prototype['update_search_keyword'] = MixpanelPersistence.prototype.update_search_keyword;
|
|
12577
|
+
MixpanelPersistence.prototype['update_referrer_info'] = MixpanelPersistence.prototype.update_referrer_info;
|
|
12578
|
+
MixpanelPersistence.prototype['get_cross_subdomain'] = MixpanelPersistence.prototype.get_cross_subdomain;
|
|
12579
|
+
MixpanelPersistence.prototype['clear'] = MixpanelPersistence.prototype.clear;
|
|
12580
|
+
|
|
12581
|
+
|
|
12582
|
+
var instances = {};
|
|
12583
|
+
var extend_mp = function() {
|
|
12584
|
+
// add all the sub mixpanel instances
|
|
12585
|
+
_.each(instances, function(instance, name) {
|
|
12586
|
+
if (name !== PRIMARY_INSTANCE_NAME) { mixpanel_master[name] = instance; }
|
|
12587
|
+
});
|
|
12588
|
+
|
|
12589
|
+
// add private functions as _
|
|
12590
|
+
mixpanel_master['_'] = _;
|
|
12594
12591
|
};
|
|
12595
12592
|
|
|
12596
|
-
|
|
12597
|
-
|
|
12598
|
-
|
|
12599
|
-
|
|
12600
|
-
|
|
12601
|
-
|
|
12593
|
+
var override_mp_init_func = function() {
|
|
12594
|
+
// we override the snippets init function to handle the case where a
|
|
12595
|
+
// user initializes the mixpanel library after the script loads & runs
|
|
12596
|
+
mixpanel_master['init'] = function(token, config, name) {
|
|
12597
|
+
if (name) {
|
|
12598
|
+
// initialize a sub library
|
|
12599
|
+
if (!mixpanel_master[name]) {
|
|
12600
|
+
mixpanel_master[name] = instances[name] = create_mplib(token, config, name);
|
|
12601
|
+
mixpanel_master[name]._loaded();
|
|
12602
|
+
}
|
|
12603
|
+
return mixpanel_master[name];
|
|
12604
|
+
} else {
|
|
12605
|
+
var instance = mixpanel_master;
|
|
12606
|
+
|
|
12607
|
+
if (instances[PRIMARY_INSTANCE_NAME]) {
|
|
12608
|
+
// main mixpanel lib already initialized
|
|
12609
|
+
instance = instances[PRIMARY_INSTANCE_NAME];
|
|
12610
|
+
} else if (token) {
|
|
12611
|
+
// intialize the main mixpanel lib
|
|
12612
|
+
instance = create_mplib(token, config, PRIMARY_INSTANCE_NAME);
|
|
12613
|
+
instance._loaded();
|
|
12614
|
+
instances[PRIMARY_INSTANCE_NAME] = instance;
|
|
12615
|
+
}
|
|
12616
|
+
|
|
12617
|
+
mixpanel_master = instance;
|
|
12618
|
+
if (init_type === INIT_SNIPPET) {
|
|
12619
|
+
window$1[PRIMARY_INSTANCE_NAME] = mixpanel_master;
|
|
12620
|
+
}
|
|
12621
|
+
extend_mp();
|
|
12622
|
+
}
|
|
12623
|
+
};
|
|
12602
12624
|
};
|
|
12603
12625
|
|
|
12604
|
-
|
|
12605
|
-
|
|
12606
|
-
|
|
12607
|
-
|
|
12608
|
-
|
|
12609
|
-
|
|
12610
|
-
* @author Ayon Ghosh <ayon.ghosh@thoughtspot.com>
|
|
12611
|
-
*/
|
|
12612
|
-
const urlRegex = new RegExp([
|
|
12613
|
-
'(^(https?:)//)?',
|
|
12614
|
-
'(([^:/?#]*)(?::([0-9]+))?)',
|
|
12615
|
-
'(/{0,1}[^?#]*)',
|
|
12616
|
-
'(\\?[^#]*|)',
|
|
12617
|
-
'(#.*|)$', // hash
|
|
12618
|
-
].join(''));
|
|
12619
|
-
/**
|
|
12620
|
-
* Parse and construct the ThoughtSpot hostname or IP address
|
|
12621
|
-
* from the embed configuration object.
|
|
12622
|
-
*
|
|
12623
|
-
* @param config
|
|
12624
|
-
*/
|
|
12625
|
-
const getThoughtSpotHost = (config) => {
|
|
12626
|
-
if (!config.thoughtSpotHost) {
|
|
12627
|
-
throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
|
|
12628
|
-
}
|
|
12629
|
-
const urlParts = config.thoughtSpotHost.match(urlRegex);
|
|
12630
|
-
if (!urlParts) {
|
|
12631
|
-
throw new Error(ERROR_MESSAGE.INVALID_THOUGHTSPOT_HOST);
|
|
12632
|
-
}
|
|
12633
|
-
const protocol = urlParts[2] || window.location.protocol;
|
|
12634
|
-
const host = urlParts[3];
|
|
12635
|
-
let path = urlParts[6];
|
|
12636
|
-
// Lose the trailing / if any
|
|
12637
|
-
if (path.charAt(path.length - 1) === '/') {
|
|
12638
|
-
path = path.substring(0, path.length - 1);
|
|
12639
|
-
}
|
|
12640
|
-
// const urlParams = urlParts[7];
|
|
12641
|
-
// const hash = urlParts[8];
|
|
12642
|
-
return `${protocol}//${host}${path}`;
|
|
12643
|
-
};
|
|
12644
|
-
const getV2BasePath = (config) => {
|
|
12645
|
-
if (config.basepath) {
|
|
12646
|
-
return config.basepath;
|
|
12647
|
-
}
|
|
12648
|
-
const tsHost = getThoughtSpotHost(config);
|
|
12649
|
-
// This is to handle when e2e's. Search is run on pods for
|
|
12650
|
-
// comp-blink-test-pipeline with baseUrl=https://localhost:8443.
|
|
12651
|
-
// This is to handle when the developer is developing in their local
|
|
12652
|
-
// environment.
|
|
12653
|
-
if (tsHost.includes('://localhost') && !tsHost.includes(':8443')) {
|
|
12654
|
-
return '';
|
|
12655
|
-
}
|
|
12656
|
-
return 'v2';
|
|
12657
|
-
};
|
|
12658
|
-
/**
|
|
12659
|
-
* It is a good idea to keep URLs under 2000 chars.
|
|
12660
|
-
* If this is ever breached, since we pass view configuration through
|
|
12661
|
-
* URL params, we would like to log a warning.
|
|
12662
|
-
* Reference: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
|
|
12663
|
-
*/
|
|
12664
|
-
const URL_MAX_LENGTH = 2000;
|
|
12665
|
-
/**
|
|
12666
|
-
* The default CSS dimensions of the embedded app
|
|
12667
|
-
*/
|
|
12668
|
-
const DEFAULT_EMBED_WIDTH = '100%';
|
|
12669
|
-
const DEFAULT_EMBED_HEIGHT = '100%';
|
|
12626
|
+
var add_dom_loaded_handler = function() {
|
|
12627
|
+
// Cross browser DOM Loaded support
|
|
12628
|
+
function dom_loaded_handler() {
|
|
12629
|
+
// function flag since we only want to execute this once
|
|
12630
|
+
if (dom_loaded_handler.done) { return; }
|
|
12631
|
+
dom_loaded_handler.done = true;
|
|
12670
12632
|
|
|
12671
|
-
|
|
12672
|
-
|
|
12673
|
-
* @param root0
|
|
12674
|
-
* @param root0.query
|
|
12675
|
-
* @param root0.variables
|
|
12676
|
-
* @param root0.thoughtSpotHost
|
|
12677
|
-
* @param root0.isCompositeQuery
|
|
12678
|
-
*/
|
|
12679
|
-
async function graphqlQuery({ query, variables, thoughtSpotHost, isCompositeQuery = false, }) {
|
|
12680
|
-
const operationName = getOperationNameFromQuery(query);
|
|
12681
|
-
try {
|
|
12682
|
-
const response = await fetch(`${thoughtSpotHost}/prism/?op=${operationName}`, {
|
|
12683
|
-
method: 'POST',
|
|
12684
|
-
headers: {
|
|
12685
|
-
'content-type': 'application/json;charset=UTF-8',
|
|
12686
|
-
'x-requested-by': 'ThoughtSpot',
|
|
12687
|
-
accept: '*/*',
|
|
12688
|
-
'accept-language': 'en-us',
|
|
12689
|
-
},
|
|
12690
|
-
body: JSON.stringify({
|
|
12691
|
-
operationName,
|
|
12692
|
-
query,
|
|
12693
|
-
variables,
|
|
12694
|
-
}),
|
|
12695
|
-
credentials: 'include',
|
|
12696
|
-
});
|
|
12697
|
-
const result = await response.json();
|
|
12698
|
-
const dataValues = Object.values(result.data);
|
|
12699
|
-
return (isCompositeQuery) ? result.data : dataValues[0];
|
|
12700
|
-
}
|
|
12701
|
-
catch (error) {
|
|
12702
|
-
return error;
|
|
12703
|
-
}
|
|
12704
|
-
}
|
|
12633
|
+
DOM_LOADED = true;
|
|
12634
|
+
ENQUEUE_REQUESTS = false;
|
|
12705
12635
|
|
|
12706
|
-
|
|
12707
|
-
|
|
12708
|
-
|
|
12709
|
-
|
|
12710
|
-
|
|
12711
|
-
|
|
12712
|
-
|
|
12713
|
-
|
|
12714
|
-
|
|
12715
|
-
|
|
12716
|
-
|
|
12717
|
-
modified
|
|
12718
|
-
columns {
|
|
12719
|
-
id
|
|
12720
|
-
name
|
|
12721
|
-
author
|
|
12722
|
-
authorDisplayName
|
|
12723
|
-
description
|
|
12724
|
-
dataType
|
|
12725
|
-
type
|
|
12726
|
-
modified
|
|
12727
|
-
ownerName
|
|
12728
|
-
owner
|
|
12729
|
-
dataRecency
|
|
12730
|
-
sources {
|
|
12731
|
-
tableId
|
|
12732
|
-
tableName
|
|
12733
|
-
columnId
|
|
12734
|
-
columnName
|
|
12735
|
-
__typename
|
|
12736
|
-
}
|
|
12737
|
-
synonyms
|
|
12738
|
-
cohortAnswerId
|
|
12739
|
-
__typename
|
|
12740
|
-
}
|
|
12741
|
-
relationships
|
|
12742
|
-
destinationRelationships
|
|
12743
|
-
dataSourceId
|
|
12744
|
-
__typename
|
|
12636
|
+
_.each(instances, function(inst) {
|
|
12637
|
+
inst._dom_loaded();
|
|
12638
|
+
});
|
|
12639
|
+
}
|
|
12640
|
+
|
|
12641
|
+
function do_scroll_check() {
|
|
12642
|
+
try {
|
|
12643
|
+
document$1.documentElement.doScroll('left');
|
|
12644
|
+
} catch(e) {
|
|
12645
|
+
setTimeout(do_scroll_check, 1);
|
|
12646
|
+
return;
|
|
12745
12647
|
}
|
|
12746
|
-
}
|
|
12747
|
-
`;
|
|
12748
|
-
const sourceDetailCache = new Map();
|
|
12749
|
-
/**
|
|
12750
|
-
*
|
|
12751
|
-
* @param thoughtSpotHost
|
|
12752
|
-
* @param sourceId
|
|
12753
|
-
*/
|
|
12754
|
-
async function getSourceDetail(thoughtSpotHost, sourceId) {
|
|
12755
|
-
if (sourceDetailCache.get(sourceId)) {
|
|
12756
|
-
return sourceDetailCache.get(sourceId);
|
|
12757
|
-
}
|
|
12758
|
-
const details = await graphqlQuery({
|
|
12759
|
-
query: getSourceDetailQuery,
|
|
12760
|
-
variables: {
|
|
12761
|
-
ids: [sourceId],
|
|
12762
|
-
},
|
|
12763
|
-
thoughtSpotHost,
|
|
12764
|
-
});
|
|
12765
|
-
const souceDetails = details[0];
|
|
12766
|
-
if (souceDetails) {
|
|
12767
|
-
sourceDetailCache.set(sourceId, souceDetails);
|
|
12768
|
-
}
|
|
12769
|
-
return souceDetails;
|
|
12770
|
-
}
|
|
12771
12648
|
|
|
12772
|
-
|
|
12773
|
-
id {
|
|
12774
|
-
sessionId
|
|
12775
|
-
genNo
|
|
12776
|
-
acSession {
|
|
12777
|
-
sessionId
|
|
12778
|
-
genNo
|
|
12649
|
+
dom_loaded_handler();
|
|
12779
12650
|
}
|
|
12780
|
-
|
|
12781
|
-
|
|
12782
|
-
|
|
12783
|
-
|
|
12784
|
-
|
|
12785
|
-
|
|
12786
|
-
|
|
12787
|
-
|
|
12788
|
-
|
|
12789
|
-
|
|
12790
|
-
column {
|
|
12791
|
-
id
|
|
12792
|
-
name
|
|
12793
|
-
referencedColumns {
|
|
12794
|
-
guid
|
|
12795
|
-
displayName
|
|
12796
|
-
}
|
|
12797
|
-
}
|
|
12798
|
-
}
|
|
12799
|
-
}
|
|
12800
|
-
}
|
|
12651
|
+
|
|
12652
|
+
if (document$1.addEventListener) {
|
|
12653
|
+
if (document$1.readyState === 'complete') {
|
|
12654
|
+
// safari 4 can fire the DOMContentLoaded event before loading all
|
|
12655
|
+
// external JS (including this file). you will see some copypasta
|
|
12656
|
+
// on the internet that checks for 'complete' and 'loaded', but
|
|
12657
|
+
// 'loaded' is an IE thing
|
|
12658
|
+
dom_loaded_handler();
|
|
12659
|
+
} else {
|
|
12660
|
+
document$1.addEventListener('DOMContentLoaded', dom_loaded_handler, false);
|
|
12801
12661
|
}
|
|
12802
|
-
}
|
|
12803
|
-
|
|
12804
|
-
|
|
12805
|
-
|
|
12806
|
-
|
|
12807
|
-
|
|
12808
|
-
|
|
12809
|
-
|
|
12810
|
-
|
|
12811
|
-
|
|
12812
|
-
${bachSessionId}
|
|
12813
|
-
}
|
|
12814
|
-
}
|
|
12815
|
-
`;
|
|
12816
|
-
const addColumns = `
|
|
12817
|
-
mutation AddColumns($session: BachSessionIdInput!, $columns: [AnswerColumnInfo!]!) {
|
|
12818
|
-
Answer__addColumn(session: $session, columns: $columns) {
|
|
12819
|
-
${bachSessionId}
|
|
12662
|
+
} else if (document$1.attachEvent) {
|
|
12663
|
+
// IE
|
|
12664
|
+
document$1.attachEvent('onreadystatechange', dom_loaded_handler);
|
|
12665
|
+
|
|
12666
|
+
// check to make sure we arn't in a frame
|
|
12667
|
+
var toplevel = false;
|
|
12668
|
+
try {
|
|
12669
|
+
toplevel = window$1.frameElement === null;
|
|
12670
|
+
} catch(e) {
|
|
12671
|
+
// noop
|
|
12820
12672
|
}
|
|
12821
|
-
|
|
12822
|
-
|
|
12823
|
-
|
|
12824
|
-
query GetTableWithHeadlineData($session: BachSessionIdInput!, $deadline: Int!, $dataPaginationParams: DataPaginationParamsInput!) {
|
|
12825
|
-
getAnswer(session: $session) {
|
|
12826
|
-
${bachSessionId}
|
|
12827
|
-
answer {
|
|
12828
|
-
id
|
|
12829
|
-
visualizations {
|
|
12830
|
-
id
|
|
12831
|
-
... on TableViz {
|
|
12832
|
-
columns {
|
|
12833
|
-
column {
|
|
12834
|
-
id
|
|
12835
|
-
name
|
|
12836
|
-
type
|
|
12837
|
-
aggregationType
|
|
12838
|
-
dataType
|
|
12839
|
-
}
|
|
12840
|
-
}
|
|
12841
|
-
data(deadline: $deadline, pagination: $dataPaginationParams)
|
|
12842
|
-
}
|
|
12843
|
-
}
|
|
12844
|
-
}
|
|
12673
|
+
|
|
12674
|
+
if (document$1.documentElement.doScroll && toplevel) {
|
|
12675
|
+
do_scroll_check();
|
|
12845
12676
|
}
|
|
12846
12677
|
}
|
|
12847
|
-
`;
|
|
12848
12678
|
|
|
12849
|
-
//
|
|
12850
|
-
|
|
12851
|
-
|
|
12852
|
-
|
|
12853
|
-
|
|
12854
|
-
|
|
12855
|
-
|
|
12856
|
-
|
|
12857
|
-
|
|
12858
|
-
|
|
12859
|
-
|
|
12860
|
-
|
|
12861
|
-
|
|
12862
|
-
|
|
12863
|
-
|
|
12864
|
-
|
|
12865
|
-
|
|
12866
|
-
|
|
12867
|
-
|
|
12868
|
-
|
|
12869
|
-
|
|
12870
|
-
|
|
12871
|
-
|
|
12872
|
-
|
|
12873
|
-
|
|
12874
|
-
|
|
12875
|
-
|
|
12876
|
-
|
|
12877
|
-
|
|
12878
|
-
|
|
12879
|
-
|
|
12880
|
-
|
|
12881
|
-
|
|
12882
|
-
|
|
12883
|
-
|
|
12884
|
-
|
|
12885
|
-
|
|
12886
|
-
|
|
12887
|
-
|
|
12888
|
-
|
|
12889
|
-
|
|
12890
|
-
|
|
12891
|
-
|
|
12892
|
-
|
|
12893
|
-
|
|
12894
|
-
|
|
12895
|
-
|
|
12896
|
-
|
|
12897
|
-
|
|
12898
|
-
* Remove columnIds and return updated answer session.
|
|
12899
|
-
*
|
|
12900
|
-
* @param columnIds
|
|
12901
|
-
* @returns
|
|
12902
|
-
*/
|
|
12903
|
-
async removeColumns(columnIds) {
|
|
12904
|
-
return this.executeQuery(removeColumns, {
|
|
12905
|
-
logicalColumnIds: columnIds,
|
|
12906
|
-
});
|
|
12907
|
-
}
|
|
12908
|
-
/**
|
|
12909
|
-
* Add columnIds and return updated answer session.
|
|
12910
|
-
*
|
|
12911
|
-
* @param columnIds
|
|
12912
|
-
* @returns
|
|
12913
|
-
*/
|
|
12914
|
-
async addColumns(columnIds) {
|
|
12915
|
-
return this.executeQuery(addColumns, {
|
|
12916
|
-
columns: columnIds.map((colId) => ({ logicalColumnId: colId })),
|
|
12917
|
-
});
|
|
12918
|
-
}
|
|
12919
|
-
/**
|
|
12920
|
-
* Fetch data from the answer.
|
|
12921
|
-
*
|
|
12922
|
-
* @param offset
|
|
12923
|
-
* @param size
|
|
12924
|
-
* @returns
|
|
12925
|
-
*/
|
|
12926
|
-
async fetchData(offset = 0, size = 1000) {
|
|
12927
|
-
const { answer } = await this.executeQuery(getAnswerData, {
|
|
12928
|
-
deadline: 0,
|
|
12929
|
-
dataPaginationParams: {
|
|
12930
|
-
isClientPaginated: true,
|
|
12931
|
-
offset,
|
|
12932
|
-
size,
|
|
12933
|
-
},
|
|
12934
|
-
});
|
|
12935
|
-
const { columns, data } = answer.visualizations.find((viz) => !!viz.data) || {};
|
|
12936
|
-
return {
|
|
12937
|
-
columns,
|
|
12938
|
-
data,
|
|
12939
|
-
};
|
|
12940
|
-
}
|
|
12941
|
-
/**
|
|
12942
|
-
* Fetch the data for the answer as a CSV blob. This might be
|
|
12943
|
-
* quicker for larger data.
|
|
12944
|
-
*
|
|
12945
|
-
* @param userLocale
|
|
12946
|
-
* @param includeInfo Include the CSV header in the output
|
|
12947
|
-
* @returns Response
|
|
12948
|
-
*/
|
|
12949
|
-
async fetchCSVBlob(userLocale = 'en-us', includeInfo = false) {
|
|
12950
|
-
const fetchUrl = this.getFetchCSVBlobUrl(userLocale, includeInfo);
|
|
12951
|
-
return tokenizedFetch(fetchUrl, {
|
|
12952
|
-
credentials: 'include',
|
|
12953
|
-
});
|
|
12954
|
-
}
|
|
12955
|
-
/**
|
|
12956
|
-
* Just get the internal URL for this answer's data
|
|
12957
|
-
* as a CSV blob.
|
|
12958
|
-
*
|
|
12959
|
-
* @param userLocale
|
|
12960
|
-
* @param includeInfo
|
|
12961
|
-
* @returns
|
|
12962
|
-
*/
|
|
12963
|
-
getFetchCSVBlobUrl(userLocale = 'en-us', includeInfo = false) {
|
|
12964
|
-
return `${this.thoughtSpotHost}/prism/download/answer/csv?sessionId=${this.session.sessionId}&genNo=${this.session.genNo}&userLocale=${userLocale}&exportFileName=data&hideCsvHeader=${!includeInfo}`;
|
|
12965
|
-
}
|
|
12966
|
-
/**
|
|
12967
|
-
* Get underlying data given a point and the output column names.
|
|
12968
|
-
* In case of a context menu action, the selectedPoints are
|
|
12969
|
-
* automatically passed.
|
|
12970
|
-
*
|
|
12971
|
-
* @param outputColumnNames
|
|
12972
|
-
* @param selectedPoints
|
|
12973
|
-
* @example
|
|
12974
|
-
* ```js
|
|
12975
|
-
* embed.on(EmbedEvent.CustomAction, e => {
|
|
12976
|
-
* const underlying = await e.answerService.getUnderlyingDataForPoint([
|
|
12977
|
-
* 'col name 1' // The column should exist in the data source.
|
|
12978
|
-
* ]);
|
|
12979
|
-
* const data = await underlying.fetchData(0, 100);
|
|
12980
|
-
* })
|
|
12981
|
-
* ```
|
|
12982
|
-
* @version SDK: 1.25.0| ThoughtSpot: 9.10.0.cl
|
|
12983
|
-
*/
|
|
12984
|
-
async getUnderlyingDataForPoint(outputColumnNames, selectedPoints) {
|
|
12985
|
-
if (!selectedPoints && !this.selectedPoints) {
|
|
12986
|
-
throw new Error('Needs to be triggered in context of a point');
|
|
12987
|
-
}
|
|
12988
|
-
if (!selectedPoints) {
|
|
12989
|
-
selectedPoints = getSelectedPointsForUnderlyingDataQuery(this.selectedPoints);
|
|
12990
|
-
}
|
|
12991
|
-
const sourceDetail = await this.getSourceDetail();
|
|
12992
|
-
const ouputColumnGuids = getGuidsFromColumnNames(sourceDetail, outputColumnNames);
|
|
12993
|
-
const unAggAnswer = await graphqlQuery({
|
|
12994
|
-
query: getUnaggregatedAnswerSession,
|
|
12995
|
-
variables: {
|
|
12996
|
-
session: this.session,
|
|
12997
|
-
columns: selectedPoints,
|
|
12998
|
-
},
|
|
12999
|
-
thoughtSpotHost: this.thoughtSpotHost,
|
|
13000
|
-
});
|
|
13001
|
-
const unaggAnswerSession = new AnswerService(unAggAnswer.id, unAggAnswer.answer, this.thoughtSpotHost);
|
|
13002
|
-
const currentColumns = new Set(unAggAnswer.answer.visualizations[0].columns
|
|
13003
|
-
.map((c) => c.column.referencedColumns[0].guid));
|
|
13004
|
-
const columnsToAdd = [...ouputColumnGuids].filter((col) => !currentColumns.has(col));
|
|
13005
|
-
if (columnsToAdd.length) {
|
|
13006
|
-
await unaggAnswerSession.addColumns(columnsToAdd);
|
|
13007
|
-
}
|
|
13008
|
-
const columnsToRemove = [...currentColumns].filter((col) => !ouputColumnGuids.has(col));
|
|
13009
|
-
if (columnsToRemove.length) {
|
|
13010
|
-
await unaggAnswerSession.removeColumns(columnsToRemove);
|
|
13011
|
-
}
|
|
13012
|
-
return unaggAnswerSession;
|
|
13013
|
-
}
|
|
13014
|
-
/**
|
|
13015
|
-
* Execute a custom graphql query in the context of the answer.
|
|
13016
|
-
*
|
|
13017
|
-
* @param query graphql query
|
|
13018
|
-
* @param variables graphql variables
|
|
13019
|
-
* @returns
|
|
13020
|
-
*/
|
|
13021
|
-
async executeQuery(query, variables) {
|
|
13022
|
-
const data = await graphqlQuery({
|
|
13023
|
-
query,
|
|
13024
|
-
variables: {
|
|
13025
|
-
session: this.session,
|
|
13026
|
-
...variables,
|
|
13027
|
-
},
|
|
13028
|
-
thoughtSpotHost: this.thoughtSpotHost,
|
|
13029
|
-
isCompositeQuery: false,
|
|
13030
|
-
});
|
|
13031
|
-
this.session = deepMerge(this.session, (data === null || data === void 0 ? void 0 : data.id) || {});
|
|
13032
|
-
return data;
|
|
13033
|
-
}
|
|
13034
|
-
/**
|
|
13035
|
-
* Get the internal session details for the answer.
|
|
13036
|
-
*
|
|
13037
|
-
* @returns
|
|
13038
|
-
*/
|
|
13039
|
-
getSession() {
|
|
13040
|
-
return this.session;
|
|
12679
|
+
// fallback handler, always will work
|
|
12680
|
+
_.register_event(window$1, 'load', dom_loaded_handler, true);
|
|
12681
|
+
};
|
|
12682
|
+
|
|
12683
|
+
function init_as_module() {
|
|
12684
|
+
init_type = INIT_MODULE;
|
|
12685
|
+
mixpanel_master = new MixpanelLib();
|
|
12686
|
+
|
|
12687
|
+
override_mp_init_func();
|
|
12688
|
+
mixpanel_master['init']();
|
|
12689
|
+
add_dom_loaded_handler();
|
|
12690
|
+
|
|
12691
|
+
return mixpanel_master;
|
|
12692
|
+
}
|
|
12693
|
+
|
|
12694
|
+
var mixpanel = init_as_module();
|
|
12695
|
+
|
|
12696
|
+
var mixpanel_cjs = mixpanel;
|
|
12697
|
+
|
|
12698
|
+
var mixpanel$1 = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.assign(/*#__PURE__*/Object.create(null), mixpanel_cjs, {
|
|
12699
|
+
'default': mixpanel_cjs
|
|
12700
|
+
}));
|
|
12701
|
+
|
|
12702
|
+
// Needed to avoid error in CJS builds on some bundlers.
|
|
12703
|
+
const mixpanelLib = mixpanel_cjs || mixpanel$1;
|
|
12704
|
+
let mixpanelInstance;
|
|
12705
|
+
const MIXPANEL_EVENT = {
|
|
12706
|
+
VISUAL_SDK_RENDER_START: 'visual-sdk-render-start',
|
|
12707
|
+
VISUAL_SDK_CALLED_INIT: 'visual-sdk-called-init',
|
|
12708
|
+
VISUAL_SDK_RENDER_COMPLETE: 'visual-sdk-render-complete',
|
|
12709
|
+
VISUAL_SDK_RENDER_FAILED: 'visual-sdk-render-failed',
|
|
12710
|
+
VISUAL_SDK_TRIGGER: 'visual-sdk-trigger',
|
|
12711
|
+
VISUAL_SDK_ON: 'visual-sdk-on',
|
|
12712
|
+
VISUAL_SDK_IFRAME_LOAD_PERFORMANCE: 'visual-sdk-iframe-load-performance',
|
|
12713
|
+
VISUAL_SDK_EMBED_CREATE: 'visual-sdk-embed-create',
|
|
12714
|
+
VERCEL_INTEGRATION_COMPLETED: 'vercel-integration-completed',
|
|
12715
|
+
};
|
|
12716
|
+
let isMixpanelInitialized = false;
|
|
12717
|
+
let eventQueue = [];
|
|
12718
|
+
/**
|
|
12719
|
+
* Pushes the event with its Property key-value map to mixpanel.
|
|
12720
|
+
*
|
|
12721
|
+
* @param eventId
|
|
12722
|
+
* @param eventProps
|
|
12723
|
+
*/
|
|
12724
|
+
function uploadMixpanelEvent(eventId, eventProps = {}) {
|
|
12725
|
+
if (!isMixpanelInitialized) {
|
|
12726
|
+
eventQueue.push({ eventId, eventProps });
|
|
12727
|
+
return;
|
|
13041
12728
|
}
|
|
12729
|
+
mixpanelInstance.track(eventId, eventProps);
|
|
13042
12730
|
}
|
|
13043
12731
|
/**
|
|
13044
12732
|
*
|
|
13045
|
-
* @param sourceDetail
|
|
13046
|
-
* @param colNames
|
|
13047
12733
|
*/
|
|
13048
|
-
function
|
|
13049
|
-
|
|
13050
|
-
|
|
13051
|
-
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
|
|
13055
|
-
|
|
13056
|
-
}));
|
|
12734
|
+
function emptyQueue() {
|
|
12735
|
+
if (!isMixpanelInitialized) {
|
|
12736
|
+
return;
|
|
12737
|
+
}
|
|
12738
|
+
eventQueue.forEach((event) => {
|
|
12739
|
+
uploadMixpanelEvent(event.eventId, event.eventProps);
|
|
12740
|
+
});
|
|
12741
|
+
eventQueue = [];
|
|
13057
12742
|
}
|
|
13058
12743
|
/**
|
|
13059
12744
|
*
|
|
13060
|
-
* @param
|
|
12745
|
+
* @param sessionInfo
|
|
13061
12746
|
*/
|
|
13062
|
-
function
|
|
13063
|
-
|
|
13064
|
-
|
|
13065
|
-
|
|
13066
|
-
|
|
13067
|
-
|
|
13068
|
-
|
|
13069
|
-
|
|
13070
|
-
|
|
13071
|
-
|
|
13072
|
-
|
|
13073
|
-
|
|
13074
|
-
if (
|
|
13075
|
-
|
|
13076
|
-
epochRange: {
|
|
13077
|
-
startEpoch: colVal.value,
|
|
13078
|
-
},
|
|
13079
|
-
}];
|
|
13080
|
-
// Case for custom calendar.
|
|
13081
|
-
}
|
|
13082
|
-
else if ((_a = colVal.value) === null || _a === void 0 ? void 0 : _a.v) {
|
|
13083
|
-
dataValue = [{
|
|
13084
|
-
epochRange: {
|
|
13085
|
-
startEpoch: colVal.value.v.s,
|
|
13086
|
-
endEpoch: colVal.value.v.e,
|
|
13087
|
-
},
|
|
13088
|
-
}];
|
|
12747
|
+
function initMixpanel(sessionInfo) {
|
|
12748
|
+
var _a;
|
|
12749
|
+
if (!sessionInfo || !sessionInfo.mixpanelToken) {
|
|
12750
|
+
return;
|
|
12751
|
+
}
|
|
12752
|
+
// On a public cluster the user is anonymous, so don't set the identify to
|
|
12753
|
+
// userGUID
|
|
12754
|
+
const isPublicCluster = !!sessionInfo.isPublicUser;
|
|
12755
|
+
const token = sessionInfo.mixpanelToken;
|
|
12756
|
+
try {
|
|
12757
|
+
if (token) {
|
|
12758
|
+
mixpanelInstance = mixpanelLib.init(token, undefined, 'tsEmbed');
|
|
12759
|
+
if (!isPublicCluster) {
|
|
12760
|
+
mixpanelInstance.identify(sessionInfo.userGUID);
|
|
13089
12761
|
}
|
|
12762
|
+
mixpanelInstance.register_once({
|
|
12763
|
+
clusterId: sessionInfo.clusterId,
|
|
12764
|
+
clusterName: sessionInfo.clusterName,
|
|
12765
|
+
releaseVersion: sessionInfo.releaseVersion,
|
|
12766
|
+
hostAppUrl: ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.host) || '',
|
|
12767
|
+
});
|
|
12768
|
+
isMixpanelInitialized = true;
|
|
12769
|
+
emptyQueue();
|
|
13090
12770
|
}
|
|
13091
|
-
else {
|
|
13092
|
-
dataValue = [{ value: colVal.value }];
|
|
13093
|
-
}
|
|
13094
|
-
underlyingDataPoint.push({
|
|
13095
|
-
columnId: colVal.column.id,
|
|
13096
|
-
dataValue,
|
|
13097
|
-
});
|
|
13098
12771
|
}
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
}
|
|
13102
|
-
return underlyingDataPoint;
|
|
12772
|
+
catch (e) {
|
|
12773
|
+
logger.error('Error initializing mixpanel', e);
|
|
12774
|
+
}
|
|
13103
12775
|
}
|
|
13104
12776
|
|
|
13105
12777
|
var eventemitter3 = createCommonjsModule(function (module) {
|
|
@@ -13454,6 +13126,399 @@ var createSet = !(_Set && (1 / _setToArray(new _Set([,-0]))[1]) == INFINITY) ? n
|
|
|
13454
13126
|
return new _Set(values);
|
|
13455
13127
|
};
|
|
13456
13128
|
|
|
13129
|
+
/**
|
|
13130
|
+
*
|
|
13131
|
+
* @param url
|
|
13132
|
+
* @param options
|
|
13133
|
+
*/
|
|
13134
|
+
function tokenisedFailureLoggedFetch(url, options = {}) {
|
|
13135
|
+
return tokenizedFetch(url, options).then(async (r) => {
|
|
13136
|
+
var _a;
|
|
13137
|
+
if (!r.ok && r.type !== 'opaqueredirect' && r.type !== 'opaque') {
|
|
13138
|
+
logger.error('Failure', await ((_a = r.text) === null || _a === void 0 ? void 0 : _a.call(r)));
|
|
13139
|
+
}
|
|
13140
|
+
return r;
|
|
13141
|
+
});
|
|
13142
|
+
}
|
|
13143
|
+
/**
|
|
13144
|
+
*
|
|
13145
|
+
* @param authVerificationUrl
|
|
13146
|
+
*/
|
|
13147
|
+
function fetchSessionInfoService(authVerificationUrl) {
|
|
13148
|
+
return tokenisedFailureLoggedFetch(authVerificationUrl, {
|
|
13149
|
+
credentials: 'include',
|
|
13150
|
+
});
|
|
13151
|
+
}
|
|
13152
|
+
|
|
13153
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
13154
|
+
let loggedInStatus = false;
|
|
13155
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
13156
|
+
let samlAuthWindow = null;
|
|
13157
|
+
// eslint-disable-next-line import/no-mutable-exports
|
|
13158
|
+
let samlCompletionPromise = null;
|
|
13159
|
+
let sessionInfo = null;
|
|
13160
|
+
let sessionInfoResolver = null;
|
|
13161
|
+
const sessionInfoPromise = new Promise((resolve) => {
|
|
13162
|
+
sessionInfoResolver = resolve;
|
|
13163
|
+
});
|
|
13164
|
+
let releaseVersion = '';
|
|
13165
|
+
const SSO_REDIRECTION_MARKER_GUID = '5e16222e-ef02-43e9-9fbd-24226bf3ce5b';
|
|
13166
|
+
/**
|
|
13167
|
+
* Enum for auth failure types. This is the parameter passed to the listner
|
|
13168
|
+
* of {@link AuthStatus.FAILURE}.
|
|
13169
|
+
*
|
|
13170
|
+
* @group Authentication / Init
|
|
13171
|
+
*/
|
|
13172
|
+
var AuthFailureType;
|
|
13173
|
+
(function (AuthFailureType) {
|
|
13174
|
+
AuthFailureType["SDK"] = "SDK";
|
|
13175
|
+
AuthFailureType["NO_COOKIE_ACCESS"] = "NO_COOKIE_ACCESS";
|
|
13176
|
+
AuthFailureType["EXPIRY"] = "EXPIRY";
|
|
13177
|
+
AuthFailureType["OTHER"] = "OTHER";
|
|
13178
|
+
})(AuthFailureType || (AuthFailureType = {}));
|
|
13179
|
+
/**
|
|
13180
|
+
* Enum for auth status emitted by the emitter returned from {@link init}.
|
|
13181
|
+
*
|
|
13182
|
+
* @group Authentication / Init
|
|
13183
|
+
*/
|
|
13184
|
+
var AuthStatus;
|
|
13185
|
+
(function (AuthStatus) {
|
|
13186
|
+
/**
|
|
13187
|
+
* Emits when the SDK fails to authenticate
|
|
13188
|
+
*/
|
|
13189
|
+
AuthStatus["FAILURE"] = "FAILURE";
|
|
13190
|
+
/**
|
|
13191
|
+
* Emits when the SDK authenticates successfully
|
|
13192
|
+
*/
|
|
13193
|
+
AuthStatus["SDK_SUCCESS"] = "SDK_SUCCESS";
|
|
13194
|
+
/**
|
|
13195
|
+
* Emits when the app sends an authentication success message
|
|
13196
|
+
*/
|
|
13197
|
+
AuthStatus["SUCCESS"] = "SUCCESS";
|
|
13198
|
+
/**
|
|
13199
|
+
* Emits when a user logs out
|
|
13200
|
+
*/
|
|
13201
|
+
AuthStatus["LOGOUT"] = "LOGOUT";
|
|
13202
|
+
/**
|
|
13203
|
+
* Emitted when inPopup is true in the SAMLRedirect flow and the
|
|
13204
|
+
* popup is waiting to be triggered either programmatically
|
|
13205
|
+
* or by the trigger button.
|
|
13206
|
+
*
|
|
13207
|
+
* @version SDK: 1.19.0
|
|
13208
|
+
*/
|
|
13209
|
+
AuthStatus["WAITING_FOR_POPUP"] = "WAITING_FOR_POPUP";
|
|
13210
|
+
})(AuthStatus || (AuthStatus = {}));
|
|
13211
|
+
/**
|
|
13212
|
+
* Events which can be triggered on the emitter returned from {@link init}.
|
|
13213
|
+
*
|
|
13214
|
+
* @group Authentication / Init
|
|
13215
|
+
*/
|
|
13216
|
+
var AuthEvent;
|
|
13217
|
+
(function (AuthEvent) {
|
|
13218
|
+
/**
|
|
13219
|
+
* Manually trigger the SSO popup. This is useful when
|
|
13220
|
+
* authStatus is SAMLRedirect/OIDCRedirect and inPopup is set to true
|
|
13221
|
+
*/
|
|
13222
|
+
AuthEvent["TRIGGER_SSO_POPUP"] = "TRIGGER_SSO_POPUP";
|
|
13223
|
+
})(AuthEvent || (AuthEvent = {}));
|
|
13224
|
+
/**
|
|
13225
|
+
*
|
|
13226
|
+
*/
|
|
13227
|
+
function notifyAuthSDKSuccess() {
|
|
13228
|
+
{
|
|
13229
|
+
logger.error('SDK not initialized');
|
|
13230
|
+
return;
|
|
13231
|
+
}
|
|
13232
|
+
}
|
|
13233
|
+
/**
|
|
13234
|
+
*
|
|
13235
|
+
*/
|
|
13236
|
+
function notifyAuthSuccess() {
|
|
13237
|
+
{
|
|
13238
|
+
logger.error('SDK not initialized');
|
|
13239
|
+
return;
|
|
13240
|
+
}
|
|
13241
|
+
}
|
|
13242
|
+
/**
|
|
13243
|
+
*
|
|
13244
|
+
* @param failureType
|
|
13245
|
+
*/
|
|
13246
|
+
function notifyAuthFailure(failureType) {
|
|
13247
|
+
{
|
|
13248
|
+
logger.error('SDK not initialized');
|
|
13249
|
+
return;
|
|
13250
|
+
}
|
|
13251
|
+
}
|
|
13252
|
+
/**
|
|
13253
|
+
*
|
|
13254
|
+
*/
|
|
13255
|
+
function notifyLogout() {
|
|
13256
|
+
{
|
|
13257
|
+
logger.error('SDK not initialized');
|
|
13258
|
+
return;
|
|
13259
|
+
}
|
|
13260
|
+
}
|
|
13261
|
+
const initSession = (sessionDetails) => {
|
|
13262
|
+
const embedConfig = getEmbedConfig();
|
|
13263
|
+
if (sessionInfo == null) {
|
|
13264
|
+
sessionInfo = sessionDetails;
|
|
13265
|
+
if (!embedConfig.disableSDKTracking) {
|
|
13266
|
+
initMixpanel(sessionInfo);
|
|
13267
|
+
}
|
|
13268
|
+
sessionInfoResolver(sessionInfo);
|
|
13269
|
+
}
|
|
13270
|
+
};
|
|
13271
|
+
const getSessionDetails = (sessionInfoResp) => {
|
|
13272
|
+
const devMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.devSdkKey;
|
|
13273
|
+
const prodMixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.prodSdkKey;
|
|
13274
|
+
const mixpanelToken = sessionInfoResp.configInfo.mixpanelConfig.production
|
|
13275
|
+
? prodMixpanelToken
|
|
13276
|
+
: devMixpanelToken;
|
|
13277
|
+
return {
|
|
13278
|
+
userGUID: sessionInfoResp.userGUID,
|
|
13279
|
+
mixpanelToken,
|
|
13280
|
+
isPublicUser: sessionInfoResp.configInfo.isPublicUser,
|
|
13281
|
+
releaseVersion: sessionInfoResp.releaseVersion,
|
|
13282
|
+
clusterId: sessionInfoResp.configInfo.selfClusterId,
|
|
13283
|
+
clusterName: sessionInfoResp.configInfo.selfClusterName,
|
|
13284
|
+
...sessionInfoResp,
|
|
13285
|
+
};
|
|
13286
|
+
};
|
|
13287
|
+
/**
|
|
13288
|
+
* Check if we are logged into the ThoughtSpot cluster
|
|
13289
|
+
*
|
|
13290
|
+
* @param thoughtSpotHost The ThoughtSpot cluster hostname or IP
|
|
13291
|
+
*/
|
|
13292
|
+
async function isLoggedIn(thoughtSpotHost) {
|
|
13293
|
+
const authVerificationUrl = `${thoughtSpotHost}${EndPoints.AUTH_VERIFICATION}`;
|
|
13294
|
+
let response = null;
|
|
13295
|
+
try {
|
|
13296
|
+
response = await fetchSessionInfoService(authVerificationUrl);
|
|
13297
|
+
const sessionInfoResp = await response.json();
|
|
13298
|
+
const sessionDetails = getSessionDetails(sessionInfoResp);
|
|
13299
|
+
// Store user session details from session info
|
|
13300
|
+
initSession(sessionDetails);
|
|
13301
|
+
releaseVersion = sessionInfoResp.releaseVersion;
|
|
13302
|
+
}
|
|
13303
|
+
catch (e) {
|
|
13304
|
+
return false;
|
|
13305
|
+
}
|
|
13306
|
+
return response.status === 200;
|
|
13307
|
+
}
|
|
13308
|
+
/**
|
|
13309
|
+
* Return releaseVersion if available
|
|
13310
|
+
*/
|
|
13311
|
+
function getReleaseVersion() {
|
|
13312
|
+
return releaseVersion;
|
|
13313
|
+
}
|
|
13314
|
+
/**
|
|
13315
|
+
* Check if we are stuck at the SSO redirect URL
|
|
13316
|
+
*/
|
|
13317
|
+
function isAtSSORedirectUrl() {
|
|
13318
|
+
return window.location.href.indexOf(SSO_REDIRECTION_MARKER_GUID) >= 0;
|
|
13319
|
+
}
|
|
13320
|
+
/**
|
|
13321
|
+
* Remove the SSO redirect URL marker
|
|
13322
|
+
*/
|
|
13323
|
+
function removeSSORedirectUrlMarker() {
|
|
13324
|
+
// Note (sunny): This will leave a # around even if it was not in the URL
|
|
13325
|
+
// to begin with. Trying to remove the hash by changing window.location will
|
|
13326
|
+
// reload the page which we don't want. We'll live with adding an
|
|
13327
|
+
// unnecessary hash to the parent page URL until we find any use case where
|
|
13328
|
+
// that creates an issue.
|
|
13329
|
+
window.location.hash = window.location.hash.replace(SSO_REDIRECTION_MARKER_GUID, '');
|
|
13330
|
+
}
|
|
13331
|
+
/**
|
|
13332
|
+
* Perform token based authentication
|
|
13333
|
+
*
|
|
13334
|
+
* @param embedConfig The embed configuration
|
|
13335
|
+
*/
|
|
13336
|
+
const doTokenAuth = async (embedConfig) => {
|
|
13337
|
+
const { thoughtSpotHost, username, authEndpoint, getAuthToken, } = embedConfig;
|
|
13338
|
+
if (!authEndpoint && !getAuthToken) {
|
|
13339
|
+
throw new Error('Either auth endpoint or getAuthToken function must be provided');
|
|
13340
|
+
}
|
|
13341
|
+
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
13342
|
+
if (!loggedInStatus) {
|
|
13343
|
+
const authToken = await getAuthenticationToken(embedConfig);
|
|
13344
|
+
let resp;
|
|
13345
|
+
try {
|
|
13346
|
+
resp = await fetchAuthPostService(thoughtSpotHost, username, authToken);
|
|
13347
|
+
}
|
|
13348
|
+
catch (e) {
|
|
13349
|
+
resp = await fetchAuthService(thoughtSpotHost, username, authToken);
|
|
13350
|
+
}
|
|
13351
|
+
// token login issues a 302 when successful
|
|
13352
|
+
loggedInStatus = resp.ok || resp.type === 'opaqueredirect';
|
|
13353
|
+
if (loggedInStatus && embedConfig.detectCookieAccessSlow) {
|
|
13354
|
+
// When 3rd party cookie access is blocked, this will fail because
|
|
13355
|
+
// cookies will not be sent with the call.
|
|
13356
|
+
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
13357
|
+
}
|
|
13358
|
+
}
|
|
13359
|
+
return loggedInStatus;
|
|
13360
|
+
};
|
|
13361
|
+
/**
|
|
13362
|
+
* Validate embedConfig parameters required for cookielessTokenAuth
|
|
13363
|
+
*
|
|
13364
|
+
* @param embedConfig The embed configuration
|
|
13365
|
+
*/
|
|
13366
|
+
const doCookielessTokenAuth = async (embedConfig) => {
|
|
13367
|
+
const { authEndpoint, getAuthToken } = embedConfig;
|
|
13368
|
+
if (!authEndpoint && !getAuthToken) {
|
|
13369
|
+
throw new Error('Either auth endpoint or getAuthToken function must be provided');
|
|
13370
|
+
}
|
|
13371
|
+
let authSuccess = false;
|
|
13372
|
+
try {
|
|
13373
|
+
const authToken = await getAuthenticationToken(embedConfig);
|
|
13374
|
+
if (authToken) {
|
|
13375
|
+
authSuccess = true;
|
|
13376
|
+
}
|
|
13377
|
+
}
|
|
13378
|
+
catch {
|
|
13379
|
+
authSuccess = false;
|
|
13380
|
+
}
|
|
13381
|
+
return authSuccess;
|
|
13382
|
+
};
|
|
13383
|
+
/**
|
|
13384
|
+
* Perform basic authentication to the ThoughtSpot cluster using the cluster
|
|
13385
|
+
* credentials.
|
|
13386
|
+
*
|
|
13387
|
+
* Warning: This feature is primarily intended for developer testing. It is
|
|
13388
|
+
* strongly advised not to use this authentication method in production.
|
|
13389
|
+
*
|
|
13390
|
+
* @param embedConfig The embed configuration
|
|
13391
|
+
*/
|
|
13392
|
+
const doBasicAuth = async (embedConfig) => {
|
|
13393
|
+
const { thoughtSpotHost, username, password } = embedConfig;
|
|
13394
|
+
const loggedIn = await isLoggedIn(thoughtSpotHost);
|
|
13395
|
+
if (!loggedIn) {
|
|
13396
|
+
const response = await fetchBasicAuthService(thoughtSpotHost, username, password);
|
|
13397
|
+
loggedInStatus = response.ok;
|
|
13398
|
+
if (embedConfig.detectCookieAccessSlow) {
|
|
13399
|
+
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
13400
|
+
}
|
|
13401
|
+
}
|
|
13402
|
+
else {
|
|
13403
|
+
loggedInStatus = true;
|
|
13404
|
+
}
|
|
13405
|
+
return loggedInStatus;
|
|
13406
|
+
};
|
|
13407
|
+
/**
|
|
13408
|
+
*
|
|
13409
|
+
* @param ssoURL
|
|
13410
|
+
* @param triggerContainer
|
|
13411
|
+
* @param triggerText
|
|
13412
|
+
*/
|
|
13413
|
+
async function samlPopupFlow(ssoURL, triggerContainer, triggerText) {
|
|
13414
|
+
const openPopup = () => {
|
|
13415
|
+
if (samlAuthWindow === null || samlAuthWindow.closed) {
|
|
13416
|
+
samlAuthWindow = window.open(ssoURL, '_blank', 'location=no,height=570,width=520,scrollbars=yes,status=yes');
|
|
13417
|
+
}
|
|
13418
|
+
else {
|
|
13419
|
+
samlAuthWindow.focus();
|
|
13420
|
+
}
|
|
13421
|
+
};
|
|
13422
|
+
const containerEl = getDOMNode(triggerContainer);
|
|
13423
|
+
if (containerEl) {
|
|
13424
|
+
containerEl.innerHTML = '<button id="ts-auth-btn" class="ts-auth-btn" style="margin: auto;"></button>';
|
|
13425
|
+
const authElem = document.getElementById('ts-auth-btn');
|
|
13426
|
+
authElem.textContent = triggerText;
|
|
13427
|
+
authElem.addEventListener('click', openPopup, { once: true });
|
|
13428
|
+
}
|
|
13429
|
+
samlCompletionPromise = samlCompletionPromise
|
|
13430
|
+
|| new Promise((resolve, reject) => {
|
|
13431
|
+
window.addEventListener('message', (e) => {
|
|
13432
|
+
if (e.data.type === EmbedEvent.SAMLComplete) {
|
|
13433
|
+
e.source.close();
|
|
13434
|
+
resolve();
|
|
13435
|
+
}
|
|
13436
|
+
});
|
|
13437
|
+
});
|
|
13438
|
+
return samlCompletionPromise;
|
|
13439
|
+
}
|
|
13440
|
+
/**
|
|
13441
|
+
* Perform SAML authentication
|
|
13442
|
+
*
|
|
13443
|
+
* @param embedConfig The embed configuration
|
|
13444
|
+
* @param ssoEndPoint
|
|
13445
|
+
*/
|
|
13446
|
+
const doSSOAuth = async (embedConfig, ssoEndPoint) => {
|
|
13447
|
+
const { thoughtSpotHost } = embedConfig;
|
|
13448
|
+
const loggedIn = await isLoggedIn(thoughtSpotHost);
|
|
13449
|
+
if (loggedIn) {
|
|
13450
|
+
if (isAtSSORedirectUrl()) {
|
|
13451
|
+
removeSSORedirectUrlMarker();
|
|
13452
|
+
}
|
|
13453
|
+
loggedInStatus = true;
|
|
13454
|
+
return;
|
|
13455
|
+
}
|
|
13456
|
+
// we have already tried authentication and it did not succeed, restore
|
|
13457
|
+
// the current URL to the original one and invoke the callback.
|
|
13458
|
+
if (isAtSSORedirectUrl()) {
|
|
13459
|
+
removeSSORedirectUrlMarker();
|
|
13460
|
+
loggedInStatus = false;
|
|
13461
|
+
return;
|
|
13462
|
+
}
|
|
13463
|
+
const ssoURL = `${thoughtSpotHost}${ssoEndPoint}`;
|
|
13464
|
+
if (embedConfig.inPopup) {
|
|
13465
|
+
await samlPopupFlow(ssoURL, embedConfig.authTriggerContainer, embedConfig.authTriggerText);
|
|
13466
|
+
loggedInStatus = await isLoggedIn(thoughtSpotHost);
|
|
13467
|
+
return;
|
|
13468
|
+
}
|
|
13469
|
+
window.location.href = ssoURL;
|
|
13470
|
+
};
|
|
13471
|
+
const doSamlAuth = async (embedConfig) => {
|
|
13472
|
+
const { thoughtSpotHost } = embedConfig;
|
|
13473
|
+
// redirect for SSO, when the SSO authentication is done, this page will be
|
|
13474
|
+
// loaded again and the same JS will execute again.
|
|
13475
|
+
const ssoRedirectUrl = embedConfig.inPopup
|
|
13476
|
+
? `${thoughtSpotHost}/v2/#/embed/saml-complete`
|
|
13477
|
+
: getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
|
|
13478
|
+
// bring back the page to the same URL
|
|
13479
|
+
const ssoEndPoint = `${EndPoints.SAML_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
|
|
13480
|
+
await doSSOAuth(embedConfig, ssoEndPoint);
|
|
13481
|
+
return loggedInStatus;
|
|
13482
|
+
};
|
|
13483
|
+
const doOIDCAuth = async (embedConfig) => {
|
|
13484
|
+
const { thoughtSpotHost } = embedConfig;
|
|
13485
|
+
// redirect for SSO, when the SSO authentication is done, this page will be
|
|
13486
|
+
// loaded again and the same JS will execute again.
|
|
13487
|
+
const ssoRedirectUrl = embedConfig.noRedirect || embedConfig.inPopup
|
|
13488
|
+
? `${thoughtSpotHost}/v2/#/embed/saml-complete`
|
|
13489
|
+
: getRedirectUrl(window.location.href, SSO_REDIRECTION_MARKER_GUID, embedConfig.redirectPath);
|
|
13490
|
+
// bring back the page to the same URL
|
|
13491
|
+
const ssoEndPoint = `${EndPoints.OIDC_LOGIN_TEMPLATE(encodeURIComponent(ssoRedirectUrl))}`;
|
|
13492
|
+
await doSSOAuth(embedConfig, ssoEndPoint);
|
|
13493
|
+
return loggedInStatus;
|
|
13494
|
+
};
|
|
13495
|
+
/**
|
|
13496
|
+
* Perform authentication on the ThoughtSpot cluster
|
|
13497
|
+
*
|
|
13498
|
+
* @param embedConfig The embed configuration
|
|
13499
|
+
*/
|
|
13500
|
+
const authenticate = async (embedConfig) => {
|
|
13501
|
+
const { authType } = embedConfig;
|
|
13502
|
+
switch (authType) {
|
|
13503
|
+
case AuthType.SSO:
|
|
13504
|
+
case AuthType.SAMLRedirect:
|
|
13505
|
+
case AuthType.SAML:
|
|
13506
|
+
return doSamlAuth(embedConfig);
|
|
13507
|
+
case AuthType.OIDC:
|
|
13508
|
+
case AuthType.OIDCRedirect:
|
|
13509
|
+
return doOIDCAuth(embedConfig);
|
|
13510
|
+
case AuthType.AuthServer:
|
|
13511
|
+
case AuthType.TrustedAuthToken:
|
|
13512
|
+
return doTokenAuth(embedConfig);
|
|
13513
|
+
case AuthType.TrustedAuthTokenCookieless:
|
|
13514
|
+
return doCookielessTokenAuth(embedConfig);
|
|
13515
|
+
case AuthType.Basic:
|
|
13516
|
+
return doBasicAuth(embedConfig);
|
|
13517
|
+
default:
|
|
13518
|
+
return Promise.resolve(true);
|
|
13519
|
+
}
|
|
13520
|
+
};
|
|
13521
|
+
|
|
13457
13522
|
/* eslint-disable camelcase */
|
|
13458
13523
|
const CONFIG_DEFAULTS = {
|
|
13459
13524
|
loginFailedMessage: 'Not logged in',
|
|
@@ -13667,6 +13732,8 @@ function processTrigger(iFrame, messageType, thoughtSpotHost, data) {
|
|
|
13667
13732
|
});
|
|
13668
13733
|
}
|
|
13669
13734
|
|
|
13735
|
+
var name="@thoughtspot/visual-embed-sdk";var version="1.28.5-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={".":{"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","embedded","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,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};
|
|
13736
|
+
|
|
13670
13737
|
/**
|
|
13671
13738
|
* Copyright (c) 2022
|
|
13672
13739
|
*
|
|
@@ -13965,6 +14032,15 @@ class TsEmbed {
|
|
|
13965
14032
|
if (this.embedConfig.pendoTrackingKey) {
|
|
13966
14033
|
queryParams[Param.PendoTrackingKey] = this.embedConfig.pendoTrackingKey;
|
|
13967
14034
|
}
|
|
14035
|
+
if (this.embedConfig.numberFormatLocale) {
|
|
14036
|
+
queryParams[Param.NumberFormatLocale] = this.embedConfig.numberFormatLocale;
|
|
14037
|
+
}
|
|
14038
|
+
if (this.embedConfig.dateFormatLocale) {
|
|
14039
|
+
queryParams[Param.DateFormatLocale] = this.embedConfig.dateFormatLocale;
|
|
14040
|
+
}
|
|
14041
|
+
if (this.embedConfig.currencyFormat) {
|
|
14042
|
+
queryParams[Param.CurrencyFormat] = this.embedConfig.currencyFormat;
|
|
14043
|
+
}
|
|
13968
14044
|
const { disabledActions, disabledActionReason, hiddenActions, visibleActions, hiddenTabs, visibleTabs, showAlerts, additionalFlags, locale, customizations, contextMenuTrigger, linkOverride, insertInToSlide, } = this.viewConfig;
|
|
13969
14045
|
if (Array.isArray(visibleActions) && Array.isArray(hiddenActions)) {
|
|
13970
14046
|
this.handleError('You cannot have both hidden actions and visible actions');
|
|
@@ -14769,16 +14845,6 @@ class SearchBarEmbed extends TsEmbed {
|
|
|
14769
14845
|
* @summary TS Sage embed
|
|
14770
14846
|
* @author Mourya Balabhadra <mourya.balabhadra@thoughtspot.com>
|
|
14771
14847
|
*/
|
|
14772
|
-
const HiddenActionItemByDefaultForSageEmbed = [
|
|
14773
|
-
Action.Save,
|
|
14774
|
-
Action.Pin,
|
|
14775
|
-
Action.EditACopy,
|
|
14776
|
-
Action.SaveAsView,
|
|
14777
|
-
Action.UpdateTML,
|
|
14778
|
-
Action.EditTML,
|
|
14779
|
-
Action.AnswerDelete,
|
|
14780
|
-
Action.Share,
|
|
14781
|
-
];
|
|
14782
14848
|
/**
|
|
14783
14849
|
* Embed ThoughtSpot LLM and GPT-based Natural Language Search component.
|
|
14784
14850
|
*
|
|
@@ -14798,8 +14864,7 @@ class SageEmbed extends V1Embed {
|
|
|
14798
14864
|
* @returns {string} query string
|
|
14799
14865
|
*/
|
|
14800
14866
|
getEmbedParams() {
|
|
14801
|
-
|
|
14802
|
-
const { disableWorksheetChange, hideWorksheetSelector, showObjectSuggestions, hideSampleQuestions, isProductTour, hideSearchBarTitle, hideSageAnswerHeader, hideAutocompleteSuggestions, } = this.viewConfig;
|
|
14867
|
+
const { disableWorksheetChange, hideWorksheetSelector, showObjectSuggestions, hideSampleQuestions, isProductTour, hideSageAnswerHeader, hideAutocompleteSuggestions, } = this.viewConfig;
|
|
14803
14868
|
const params = this.getBaseQueryParams();
|
|
14804
14869
|
params[Param.EmbedApp] = true;
|
|
14805
14870
|
params[Param.IsSageEmbed] = true;
|
|
@@ -14812,12 +14877,7 @@ class SageEmbed extends V1Embed {
|
|
|
14812
14877
|
}
|
|
14813
14878
|
params[Param.HideSampleQuestions] = !!hideSampleQuestions;
|
|
14814
14879
|
params[Param.IsProductTour] = !!isProductTour;
|
|
14815
|
-
params[Param.HideSearchBarTitle] = !!hideSearchBarTitle;
|
|
14816
14880
|
params[Param.HideSageAnswerHeader] = !!hideSageAnswerHeader;
|
|
14817
|
-
params[Param.HideActions] = [
|
|
14818
|
-
...((_a = params[Param.HideActions]) !== null && _a !== void 0 ? _a : []),
|
|
14819
|
-
...HiddenActionItemByDefaultForSageEmbed,
|
|
14820
|
-
];
|
|
14821
14881
|
return getQueryParamString(params, true);
|
|
14822
14882
|
}
|
|
14823
14883
|
/**
|
|
@@ -14899,7 +14959,7 @@ class SearchEmbed extends TsEmbed {
|
|
|
14899
14959
|
}
|
|
14900
14960
|
getEmbedParams() {
|
|
14901
14961
|
var _a;
|
|
14902
|
-
const { hideResults,
|
|
14962
|
+
const { hideResults, enableSearchAssist, forceTable, searchOptions, runtimeFilters, dataSource, dataSources, excludeRuntimeFiltersfromURL, hideSearchBar, dataPanelV2 = false, useLastSelectedSources = false, runtimeParameters, collapseSearchBarInitially = false, enableCustomColumnGroups = false, } = this.viewConfig;
|
|
14903
14963
|
const queryParams = this.getBaseQueryParams();
|
|
14904
14964
|
queryParams[Param.HideActions] = [
|
|
14905
14965
|
...((_a = queryParams[Param.HideActions]) !== null && _a !== void 0 ? _a : []),
|
|
@@ -14936,6 +14996,8 @@ class SearchEmbed extends TsEmbed {
|
|
|
14936
14996
|
queryParams[Param.UseLastSelectedDataSource] = false;
|
|
14937
14997
|
}
|
|
14938
14998
|
queryParams[Param.searchEmbed] = true;
|
|
14999
|
+
queryParams[Param.CollapseSearchBarInitially] = collapseSearchBarInitially;
|
|
15000
|
+
queryParams[Param.EnableCustomColumnGroups] = enableCustomColumnGroups;
|
|
14939
15001
|
let query = '';
|
|
14940
15002
|
const queryParamsString = getQueryParamString(queryParams, true);
|
|
14941
15003
|
if (queryParamsString) {
|
|
@@ -15068,7 +15130,7 @@ class AppEmbed extends V1Embed {
|
|
|
15068
15130
|
* embedded Liveboard or visualization.
|
|
15069
15131
|
*/
|
|
15070
15132
|
getEmbedParams() {
|
|
15071
|
-
const { tag, hideObjects, liveboardV2, showPrimaryNavbar, disableProfileAndHelp, hideApplicationSwitcher, hideOrgSwitcher, enableSearchAssist, fullHeight, dataPanelV2 = false, hideLiveboardHeader = false, showLiveboardTitle = true, showLiveboardDescription = true, hideHomepageLeftNav = false, modularHomeExperience = false, isLiveboardHeaderSticky = true, enableAskSage, } = this.viewConfig;
|
|
15133
|
+
const { tag, hideObjects, liveboardV2, showPrimaryNavbar, disableProfileAndHelp, hideApplicationSwitcher, hideOrgSwitcher, enableSearchAssist, fullHeight, dataPanelV2 = false, hideLiveboardHeader = false, showLiveboardTitle = true, showLiveboardDescription = true, hideHomepageLeftNav = false, modularHomeExperience = false, isLiveboardHeaderSticky = true, enableAskSage, collapseSearchBarInitially = false, enable2ColumnLayout, enableCustomColumnGroups = false, } = this.viewConfig;
|
|
15072
15134
|
let params = {};
|
|
15073
15135
|
params[Param.EmbedApp] = true;
|
|
15074
15136
|
params[Param.PrimaryNavHidden] = !showPrimaryNavbar;
|
|
@@ -15079,6 +15141,7 @@ class AppEmbed extends V1Embed {
|
|
|
15079
15141
|
params[Param.ShowLiveboardTitle] = showLiveboardTitle;
|
|
15080
15142
|
params[Param.ShowLiveboardDescription] = !!showLiveboardDescription;
|
|
15081
15143
|
params[Param.LiveboardHeaderSticky] = isLiveboardHeaderSticky;
|
|
15144
|
+
params[Param.IsFullAppEmbed] = true;
|
|
15082
15145
|
params = this.getBaseQueryParams(params);
|
|
15083
15146
|
if (fullHeight === true) {
|
|
15084
15147
|
params[Param.fullHeight] = true;
|
|
@@ -15095,12 +15158,17 @@ class AppEmbed extends V1Embed {
|
|
|
15095
15158
|
if (enableSearchAssist !== undefined) {
|
|
15096
15159
|
params[Param.EnableSearchAssist] = enableSearchAssist;
|
|
15097
15160
|
}
|
|
15161
|
+
if (enable2ColumnLayout !== undefined) {
|
|
15162
|
+
params[Param.Enable2ColumnLayout] = enable2ColumnLayout;
|
|
15163
|
+
}
|
|
15098
15164
|
if (enableAskSage) {
|
|
15099
15165
|
params[Param.enableAskSage] = enableAskSage;
|
|
15100
15166
|
}
|
|
15101
15167
|
params[Param.DataPanelV2Enabled] = dataPanelV2;
|
|
15102
15168
|
params[Param.HideHomepageLeftNav] = hideHomepageLeftNav;
|
|
15103
15169
|
params[Param.ModularHomeExperienceEnabled] = modularHomeExperience;
|
|
15170
|
+
params[Param.CollapseSearchBarInitially] = collapseSearchBarInitially;
|
|
15171
|
+
params[Param.EnableCustomColumnGroups] = enableCustomColumnGroups;
|
|
15104
15172
|
const queryParams = getQueryParamString(params, true);
|
|
15105
15173
|
return queryParams;
|
|
15106
15174
|
}
|
|
@@ -15249,9 +15317,11 @@ class LiveboardEmbed extends V1Embed {
|
|
|
15249
15317
|
responder({ type: EmbedEvent.EmbedIframeCenter, data: obj });
|
|
15250
15318
|
};
|
|
15251
15319
|
this.setIframeHeightForNonEmbedLiveboard = (data) => {
|
|
15252
|
-
if (
|
|
15253
|
-
|
|
15320
|
+
if (data.data.currentPath.startsWith('/embed/viz/')
|
|
15321
|
+
|| data.data.currentPath.startsWith('/embed/insights/viz/')) {
|
|
15322
|
+
return;
|
|
15254
15323
|
}
|
|
15324
|
+
this.setIFrameHeight(this.defaultHeight);
|
|
15255
15325
|
};
|
|
15256
15326
|
if (this.viewConfig.fullHeight === true) {
|
|
15257
15327
|
this.on(EmbedEvent.RouteChange, this.setIframeHeightForNonEmbedLiveboard);
|
|
@@ -15267,7 +15337,7 @@ class LiveboardEmbed extends V1Embed {
|
|
|
15267
15337
|
let params = {};
|
|
15268
15338
|
params[Param.EmbedApp] = true;
|
|
15269
15339
|
params = this.getBaseQueryParams(params);
|
|
15270
|
-
const { enableVizTransformations, fullHeight, defaultHeight, visibleVizs, liveboardV2, vizId, hideTabPanel, activeTabId, hideLiveboardHeader, showLiveboardDescription, showLiveboardTitle, isLiveboardHeaderSticky = true, enableAskSage, } = this.viewConfig;
|
|
15340
|
+
const { enableVizTransformations, fullHeight, defaultHeight, visibleVizs, liveboardV2, vizId, hideTabPanel, activeTabId, hideLiveboardHeader, showLiveboardDescription, showLiveboardTitle, isLiveboardHeaderSticky = true, enableAskSage, enable2ColumnLayout, } = this.viewConfig;
|
|
15271
15341
|
const preventLiveboardFilterRemoval = this.viewConfig.preventLiveboardFilterRemoval
|
|
15272
15342
|
|| this.viewConfig.preventPinboardFilterRemoval;
|
|
15273
15343
|
if (fullHeight === true) {
|
|
@@ -15292,6 +15362,9 @@ class LiveboardEmbed extends V1Embed {
|
|
|
15292
15362
|
if (liveboardV2 !== undefined) {
|
|
15293
15363
|
params[Param.LiveboardV2Enabled] = liveboardV2;
|
|
15294
15364
|
}
|
|
15365
|
+
if (enable2ColumnLayout !== undefined) {
|
|
15366
|
+
params[Param.Enable2ColumnLayout] = enable2ColumnLayout;
|
|
15367
|
+
}
|
|
15295
15368
|
if (hideTabPanel) {
|
|
15296
15369
|
params[Param.HideTabPanel] = hideTabPanel;
|
|
15297
15370
|
}
|