From a4670add1255788cbbae542b18172f54854a6276 Mon Sep 17 00:00:00 2001 From: zhe Date: Thu, 19 Jun 2025 11:35:27 +0800 Subject: [PATCH 1/2] Update --- .../methods-and-properties.md | 2 + .../embed-library-properties.md | 157 ++++++++++++++---- .../embed-report-properties.md | 33 ++++ .../images/information-window-limitations.png | Bin 0 -> 32199 bytes docs/images/information-window-size.png | Bin 0 -> 11913 bytes .../information-window.md | 34 ++++ .../mstr-dossier.md | 48 +++++- .../oauth2-apis.md | 140 ++++++++++++++++ docs/whats-new-in-the-embedding-sdk.md | 12 +- sidebars.js | 2 + 10 files changed, 387 insertions(+), 41 deletions(-) create mode 100644 docs/images/information-window-limitations.png create mode 100644 docs/images/information-window-size.png create mode 100644 docs/native-embedding-architecture/information-window.md create mode 100644 docs/support-for-different-authentication-environments/oauth2-apis.md diff --git a/docs/add-functionality/methods-and-properties.md b/docs/add-functionality/methods-and-properties.md index 7ea9207..d1249cc 100644 --- a/docs/add-functionality/methods-and-properties.md +++ b/docs/add-functionality/methods-and-properties.md @@ -73,6 +73,8 @@ The `url` property refers to the full URL of the dashboard to be embedded. There 1. Use `serverURL`, `configAppId`, `applicationID`, `objectID`, and `pageKey` properties. 1. If the `configAppId` property is not provided, embedding SDK will build the URL using: `serverURL` + '/app/' + `applicationID` + '/' + `objectID` + '/' + `pageKey`. 1. Otherwise the URL will be: `serverURL` + '/app/' + 'config/' + `configAppId` + '/' + `applicationID` + '/' + `objectID` + '/' + `pageKey`. +1. The `configAppId` refers to the application Id of the embeded dashboard. +1. The `applicationID` refers to the project Id of the embeded dashboard. #### Required? diff --git a/docs/embed-library-main-page/embed-library-properties.md b/docs/embed-library-main-page/embed-library-properties.md index 016722c..86b20ed 100644 --- a/docs/embed-library-main-page/embed-library-properties.md +++ b/docs/embed-library-main-page/embed-library-properties.md @@ -3,19 +3,24 @@ title: Properties for an embedded Library home page description: Describes the properties that can be set for an embedded Library home page. --- -When you embed a Library home page into a web page, you use the `embedLibraryPage(props)` method under the `microstrategy.embeddingContexts` namespace. +When you embed a Library home page into a web page, you use the `embedLibraryPage(props)` method +under the `microstrategy.embeddingContexts` namespace. ## Method ### `microstrategy.embeddingContexts.embedLibraryPage(props)` -This method creates an iFrame on the web page (in the location specified by the `placeholder` property) and inserts a link to the Library home page URL (specified by the `serverUrl` property). +This method creates an iFrame on the web page (in the location specified by the `placeholder` +property) and inserts a link to the Library home page URL (specified by the `serverUrl` property). #### Return value This method returns a promise, which is resolved when the Library home page is loaded. -The `props` parameter contains required key:value pairs that defines the Library Server URL and the `
` placeholder where the iFrame containing the Library home page will be created. It can also contain other optional key:value pairs to customize the UI, authentication and custom error handler. +The `props` parameter contains required key:value pairs that defines the Library Server URL and +the `
` placeholder where the iFrame containing the Library home page will be created. It can +also contain other optional key:value pairs to customize the UI, authentication and custom error +handler. The `props` parameter could contain the following key:value pairs: @@ -128,7 +133,8 @@ N/A ### `customAuthenticationType` -Specifies the token type returned by the `getLoginToken` function. There are two possible values, which can be provided by the CustomAuthenticationType enumeration. +Specifies the token type returned by the `getLoginToken` function. There are two possible values, +which can be provided by the CustomAuthenticationType enumeration. #### Required? @@ -144,7 +150,9 @@ N/A ### `getLoginToken` -Specifies a function that returns a promise, which is resolved with either authorization token (`authToken`) or the identity token (`identityToken`) The token type is specified by the customAuthenticationType property. +Specifies a function that returns a promise, which is resolved with either authorization token +(`authToken`) or the identity token (`identityToken`) The token type is specified by the +customAuthenticationType property. #### Required? @@ -156,9 +164,12 @@ See the sample code in the next column for the default implementation of this fu #### Sample -When `customAuthenticationType` is set to `CustomAuthenticationType.AUTH_TOKEN`, the following sample demonstrates how to send a fetch request to get `authToken` with your credentials. You can do this using an `XMLHttpRequest`, if your browser does not support `fetch`. +When `customAuthenticationType` is set to `CustomAuthenticationType.AUTH_TOKEN`, the following +sample demonstrates how to send a fetch request to get `authToken` with your credentials. You can do +this using an `XMLHttpRequest`, if your browser does not support `fetch`. -The `getLoginToken` function can be found in [the `getLoginToken` doc](../add-functionality/methods-and-properties#getlogintoken) +The `getLoginToken` function can be found in +[the `getLoginToken` doc](../add-functionality/methods-and-properties#getlogintoken) ```js microstrategy.embeddingContexts.embedLibraryPage({ @@ -173,15 +184,20 @@ microstrategy.embeddingContexts.embedLibraryPage({ }); ``` -When `customAuthenticationType` is set to `CustomAuthenticationType.IDENTITY_TOKEN`, you need to add a component to your web server. Refer to Use Custom Authentication for more information. +When `customAuthenticationType` is set to `CustomAuthenticationType.IDENTITY_TOKEN`, you need to add +a component to your web server. Refer to Use Custom Authentication for more information. ### `disableCustomErrorHandlerOnCreate` To disable the custom error handler, set `disableCustomErrorHandlerOnCreate` to true. -If this flag is set, all the errors occur in the initial loading process and manual actions would be handled by OOTB Library itself, an error dialog would pop up. +If this flag is set, all the errors occur in the initial loading process and manual actions would be +handled by OOTB Library itself, an error dialog would pop up. -You could also refer to [Custom error handling during dashboard creation](../add-functionality/error-handling.md#custom-error-handling-during-dashboard-creation) to see the usage of this parameter in `microstrategy.dossier.create`, which has the same effect as in `microstrategy.embeddingContexts.embedLibraryPage` function. +You could also refer to +[Custom error handling during dashboard creation](../add-functionality/error-handling.md#custom-error-handling-during-dashboard-creation) +to see the usage of this parameter in `microstrategy.dossier.create`, which has the same effect as +in `microstrategy.embeddingContexts.embedLibraryPage` function. #### Required? @@ -203,9 +219,13 @@ microstrategy.embeddingContexts.embedLibraryPage({ ### `errorHandler` -The custom error handler that executes when the error occurs in the initial loading process. It's a callback function that contains one parameter, `error`. The error object has the property `message`, which contains the detailed error message. +The custom error handler that executes when the error occurs in the initial loading process. It's a +callback function that contains one parameter, `error`. The error object has the property `message`, +which contains the detailed error message. -Whether `errorHandler` is set, the error occured inside the library home page would output an error in the browser console. The detailed behavior could be seen in [The overall Library error behavior in embed case](../add-functionality/error-handling.md#the-overall-library-error-behavior-in-embed-case). +Whether `errorHandler` is set, the error occured inside the library home page would output an error +in the browser console. The detailed behavior could be seen in +[The overall Library error behavior in embed case](../add-functionality/error-handling.md#the-overall-library-error-behavior-in-embed-case). #### Required? @@ -230,12 +250,18 @@ microstrategy.embeddingContexts.embedLibraryPage({ ### `sessionErrorHandler` -The custom error handler that executes when an session expiration error occurs. It's a callback function that contains one parameter, `error`. The error object has the property `message`, which contains the detailed error message. +The custom error handler that executes when an session expiration error occurs. It's a callback +function that contains one parameter, `error`. The error object has the property `message`, which +contains the detailed error message. When session expires: -- If `sessionErrorHandler` is not set, the embedded page would redirect to the OOTB library login page. -- If `sessionErrorHandler` is set, the session error handler would be triggered and the embedded page would not change for 1 minute. If after 1 minute, the error handler doesn't do anything(like reauthentication and refresh page) to renew the session, the embedded page would redirect to the OOTB Library login page. +- If `sessionErrorHandler` is not set, the embedded page would redirect to the OOTB library login + page. +- If `sessionErrorHandler` is set, the session error handler would be triggered and the embedded + page would not change for 1 minute. If after 1 minute, the error handler doesn't do anything(like + reauthentication and refresh page) to renew the session, the embedded page would redirect to the + OOTB Library login page. #### Required? @@ -264,8 +290,10 @@ Specifies the application that the user wants to show in the embedded page. The application in Strategy has 2 categories: -- If the application selects library home page as its home screen, the library home page would be embedded with the application's configuration. -- If the application selects a dashboard as its home screen, the embedding would fail and an error would occur. +- If the application selects library home page as its home screen, the library home page would be + embedded with the application's configuration. +- If the application selects a dashboard as its home screen, the embedding would fail and an error + would occur. #### Required? @@ -281,15 +309,19 @@ N/A ### `customUi` -Specifies the custom UI settings on the embedded pages, including Library home page, dashboard consumption page,dashboard authoring page, and report consumption page. +Specifies the custom UI settings on the embedded pages, including Library home page, dashboard +consumption page,dashboard authoring page, and report consumption page. #### Properties -Please see all the properties in [The customized UI settings in Embedding SDK](./embed-custom-ui-on-all-pages.md) +Please see all the properties in +[The customized UI settings in Embedding SDK](./embed-custom-ui-on-all-pages.md) #### The navigation bar custom setting behavior -The property `customUi.library.navigationBar.enabled` would affect the library home page UI together with the navigation bar setting in the application settings. There are 2 related item in the application settings in Workstation: +The property `customUi.library.navigationBar.enabled` would affect the library home page UI together +with the navigation bar setting in the application settings. There are 2 related item in the +application settings in Workstation: - Disable toolbar - Collapse toolbar by default @@ -298,32 +330,44 @@ The property `customUi.library.navigationBar.enabled` would affect the library h The detailed embedding behavior is as below: -- If `customUi.library.navigationBar.enabled` is false, the navigation bar is disabled by the Embedding SDK settings, and it would never be shown on the embedded library page. +- If `customUi.library.navigationBar.enabled` is false, the navigation bar is disabled by the + Embedding SDK settings, and it would never be shown on the embedded library page. -- If `customUi.library.navigationBar.enabled` is true, the setting would still be combined with the settings in the application, to determine the final visibility of the navigation bar: +- If `customUi.library.navigationBar.enabled` is true, the setting would still be combined with the + settings in the application, to determine the final visibility of the navigation bar: - If the current application disables the navigation bar, the navigation bar would never be shown. - If the current application enables the navigation bar: - - If you choose "Collapse toolbar by default" in application settings, the navigation bar is collapsible: + - If you choose "Collapse toolbar by default" in application settings, the navigation bar is + collapsible: - - If `customUi.library.sidebar.show` is false or not set, on the embedded library page, the navigation bar would be collapsed at the start, and only would be expanded/visible when the user expands it manually. + - If `customUi.library.sidebar.show` is false or not set, on the embedded library page, the + navigation bar would be collapsed at the start, and only would be expanded/visible when the + user expands it manually. - - If `customUi.library.sidebar.show` is true, as on the OOTB library page, the sidebar couldn’t be expand unless the navigation bar is visible, the navigation bar would be expanded and shown in this case. + - If `customUi.library.sidebar.show` is true, as on the OOTB library page, the sidebar + couldn’t be expand unless the navigation bar is visible, the navigation bar would be + expanded and shown in this case. - - If you don't choose "Collapse toolbar by default", the navigation bar would be shown on the embedded library page. + - If you don't choose "Collapse toolbar by default", the navigation bar would be shown on the + embedded library page. #### The sidebar custom setting behavior -`customUi.library.navigationBar.enabled` would also affect the library home page UI together with the sidebar setting in the application settings: +`customUi.library.navigationBar.enabled` would also affect the library home page UI together with +the sidebar setting in the application settings: ![Application sidebar settings](../images/custom-app-sidebar-setting.png) The special behaviors are as below: -- If sidebar is disabled in the application settings, whether setting `customUi.library.sidebar.show` to true or false, the sidebar couldn't be shown. -- If the navigation bar is enabled in `customUi.library.navigationBar.enabled` and application settings, and "Collapse toolbar by default" is enabled by default, when `customUi.library.sidebar.show` is true, the navigation bar would be expanded and shown. +- If sidebar is disabled in the application settings, whether setting + `customUi.library.sidebar.show` to true or false, the sidebar couldn't be shown. +- If the navigation bar is enabled in `customUi.library.navigationBar.enabled` and application + settings, and "Collapse toolbar by default" is enabled by default, when + `customUi.library.sidebar.show` is true, the navigation bar would be expanded and shown. ### `libraryItemSelectMode` @@ -368,11 +412,17 @@ Specifies the page on the sidebar entries that you want to embed. }; ``` -- `currentPage.key`: This field specifies the key of the page that the user wants to embed. Its available values are the menu items in the sidebar, which could be in ['home', 'insights', 'subscriptions', 'defaultGroups', 'myGroups', 'contentDiscovery']. +- `currentPage.key`: This field specifies the key of the page that the user wants to embed. Its + available values are the menu items in the sidebar, which could be in ['home', 'insights', + 'subscriptions', 'defaultGroups', 'myGroups', 'contentDiscovery']. -- `currentPage.targetGroup`: This field is only necessary when `currentPage.key` is 'defaultGroups' or 'myGroups', as on library home page the user can't select these 2 menu items but only could select the group items under them. It specifies which group item the user wants to select. +- `currentPage.targetGroup`: This field is only necessary when `currentPage.key` is 'defaultGroups' + or 'myGroups', as on library home page the user can't select these 2 menu items but only could + select the group items under them. It specifies which group item the user wants to select. -- `currentPage.targetGroup.id`: The id of the group the user wants to select. Its available values could be got from the API `EmbeddingContext.libraryPage.getAllMyGroups()` or `EmbeddingContext.libraryPage.getAllDefaultGroups()`. +- `currentPage.targetGroup.id`: The id of the group the user wants to select. Its available values + could be got from the API `EmbeddingContext.libraryPage.getAllMyGroups()` or + `EmbeddingContext.libraryPage.getAllDefaultGroups()`. - `currentPage.targetGroup.name`: The name of the group the user wants to select. @@ -380,7 +430,9 @@ Specifies the page on the sidebar entries that you want to embed. - `currentPage`: Not required - `currentPage.key`: Required if `currentPage` is provided -- `currentPage.targetGroup.id` and `currentPage.targetGroup.name`: The user must at least provide one of them. When both of them are provided, `currentPage.targetGroup.id` would have higher priority. +- `currentPage.targetGroup.id` and `currentPage.targetGroup.name`: The user must at least provide + one of them. When both of them are provided, `currentPage.targetGroup.id` would have higher + priority. #### Default value @@ -401,3 +453,42 @@ microstrategy.embeddingContexts.embedLibraryPage({ }, }); ``` + +### `settings` + +Configure global settings for the embedded library page. + +`settings` format: + +```javascript +{ + filter: { + projects: ["B7CA92F04B9FAE8D941C3E9B7E0CD754"]; + } +} +``` + +- `settings.filter.projects`: This field allows you to filter the library to display content from a + specific project. Currently, only one project can be specified at a time. + +#### Required? + +- `settings.filter.projects`: Not required + +#### Default value + +N/A + +#### Sample + +```js +microstrategy.embeddingContexts.embedLibraryPage({ + serverUrl: url, + placeholder: container, + settings: { + filter: { + projects: ["B7CA92F04B9FAE8D941C3E9B7E0CD754"], + }, + }, +}); +``` diff --git a/docs/embed-report-page/embed-report-properties.md b/docs/embed-report-page/embed-report-properties.md index f3535cb..18663ba 100644 --- a/docs/embed-report-page/embed-report-properties.md +++ b/docs/embed-report-page/embed-report-properties.md @@ -327,3 +327,36 @@ The detailed embedding behavior is below: - If you choose "Collapse toolbar by default" in the application settings, the navigation bar is collapsed at the start and is only expanded/visible when the user expands it manually. - If you don't choose "Collapse toolbar by default", the navigation bar is shown on the embedded report page. + +### `settings` + +#### Required? + +No + +#### Properties + +##### `reportConsumption` + +Use the `reportConsumption` object to customize the options on the report consumption page. The detailed properties contain: + +- `disableManipulationsAutoSaving` + + - Disable the report instance manipulation auto saving or not. + - Default value: `false`. + +### `instance` + +Use this `instance` object to specify a report based dashboard instance for the embedded report. If you would like to make some manipulation to the report based dashboard instance before it is embedded, you can use this property, e.g., sorting a column. If the `instance` is used, the Embedding SDK will use it instead of creating a new report based dashboard instance. + +#### Required? + +No + +#### Properties + +- `mid` - This instance ID. + +#### Default value + +`null` diff --git a/docs/images/information-window-limitations.png b/docs/images/information-window-limitations.png new file mode 100644 index 0000000000000000000000000000000000000000..c8b3bbd51e4adac3434c82079e1d1b6d1178c416 GIT binary patch literal 32199 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 literal 0 HcmV?d00001 diff --git a/docs/images/information-window-size.png b/docs/images/information-window-size.png new file mode 100644 index 0000000000000000000000000000000000000000..97714802b9e0cb067dc8746990e5d72d59d51123 GIT binary patch literal 11913 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 literal 0 HcmV?d00001 diff --git a/docs/native-embedding-architecture/information-window.md b/docs/native-embedding-architecture/information-window.md new file mode 100644 index 0000000..ca4f80d --- /dev/null +++ b/docs/native-embedding-architecture/information-window.md @@ -0,0 +1,34 @@ +--- +title: Information Window +description: Interactive contextual information display for visualizations +--- + + + +## Overview + +The Information Window feature enhances data visualization interactivity by providing contextual details in a dynamic overlay. When a user clicks on a visualization element, a contextual window appears displaying additional information that is automatically filtered based on the selected element. + +## Implementation + +To implement the Information Window feature, please refer to the [MstrDossier API documentation](mstr-dossier.md) for the required parameters and implementation details. + +## Behavior Specifications + +### Size Management + +The Information Window automatically adjusts its dimensions based on the content and maintains the optimal width-to-height ratio consistent with MicroStrategyLibrary standards: + +![Information Window Size Adaptation](../images/information-window-size.png) + +### Positioning Logic + +The Information Window intelligently positions itself relative to the interaction point. When a user clicks on a visualization element, the window appears proximal to the click location while ensuring it remains fully visible within the viewport. + +## Technical Limitations + +The Information Window feature has specific compatibility constraints: + +![Information Window Compatibility Constraints](../images/information-window-limitations.png) + +Certain selector components and filtering mechanisms are not compatible with the Information Window rendering system. For optimal implementation, avoid using these unsupported configurations. diff --git a/docs/native-embedding-architecture/mstr-dossier.md b/docs/native-embedding-architecture/mstr-dossier.md index fe338d3..55a7b9b 100644 --- a/docs/native-embedding-architecture/mstr-dossier.md +++ b/docs/native-embedding-architecture/mstr-dossier.md @@ -17,13 +17,15 @@ The object returned from the `MstrEnvironment.loadDossier()` function, which all #### Input Parameters -| Parameter Name | Data Type | Description | Is Required | -| ------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | -| props | Array | This parameter cannot be empty. It describes the visualizations that must appear on the page. Each visualization must have a valid container. If you call `refresh()` for a second time, the visualizations rendered in the former `refresh()` call are destroyed first, then all the visualizations specified in the second `refresh()` call are shown on page by page. | true | -| props[i].key | String | The visualization key id. | true | -| props[i].container | HTMLElement | The HTML element used for displaying the visualization. The HTML element must be in the current DOM tree of the client’s page. All elements must exist and cannot be in iframes. The `Node.contains()` function is used to determine this and is compatible with all browsers. | true | -| options | Object | An object containing optional parameters to control the behavior of the `refresh()` function. | false | -| options.signal | AbortSignal | An `AbortSignal` object that allows you to abort the refresh operation. This signal is typically created by an `AbortController` and can be used to cancel the operation by calling `AbortController.abort()` if needed. | false | +| Parameter Name | Data Type | Description | Is Required | +| -------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | +| props | Array | This parameter cannot be empty. It describes the visualizations that must appear on the page. Each visualization must have a valid container. If you call `refresh()` for a second time, the visualizations rendered in the former `refresh()` call are destroyed first, then all the visualizations specified in the second `refresh()` call are shown on page by page. | true | +| props[i].key | String | The visualization key id. | true | +| props[i].container | HTMLElement | The HTML element used for displaying the visualization. The HTML element must be in the current DOM tree of the client's page. All elements must exist and cannot be in iframes. The `Node.contains()` function is used to determine this and is compatible with all browsers. | true | +| props[i].infoWindow | Object | An object that controls the information window behavior for the visualization. | false | +| props[i].infoWindow.enable | Boolean | When set to `true`, enables the information window rendering for the visualization. | false | +| options | Object | An object containing optional parameters to control the behavior of the `refresh()` function. | false | +| options.signal | AbortSignal | An `AbortSignal` object that allows you to abort the refresh operation. This signal is typically created by an `AbortController` and can be used to cancel the operation by calling `AbortController.abort()` if needed. | false | #### Response @@ -94,6 +96,37 @@ if (shouldAbortRefresh) { } ``` +With InfoWindow: + +```js +try { + const environment = await microstrategy.embeddingComponent.environments.create({ + serverUrl: "https://demo.microstrategy.com/MicroStrategyLibrary", + getAuthToken: () => { + // Logic similar to the existing Native Embedding SDK. + }, + }); + const dossier = await environment.loadDossier({ + projectId: "B19DEDCC11D4E0EFC000EB9495D0F44F", + objectId: "D9AB379D11EC92C1D9DC0080EFD415BB", + }); + // Begin here + const containerHtmlElement = document.getElementById("containerA"); + await dossier.refresh([ + { + key: "K66", + container: containerHtmlElement, + infoWindow: { + enable: true, + }, + }, + ]); + // Your own code after the visualizations are all loaded +} catch (error) { + // Add your own handling logic here +} +``` + #### API Errors | Error Case | Error Category | Handling Module | Error Handling | @@ -107,6 +140,7 @@ if (shouldAbortRefresh) { | A container is occupied by other dossiers | Invalid input | Native Embedding SDK | Caught by the `catch()` of the promise object | | Other REST API errors | Other | Native Embedding SDK | Caught by the `catch()` of the promise object | | The key is the visualization key of the visualization in the panel | Invalid input | Native Embedding SDK | console err message in console "The visualization `${VisualizationKey}` is a visualization in a panel, which isn't supported." | +| Info window is not found for the specified visualization key | Invalid input | Native Embedding SDK | Console error message: `Info window is not found for visualization key:${vizKey}.` | | Object you pass to AbortController.abort(), or `AbortError: signal is aborted without reason` otherwise. | Abort Error | Native Embedding SDK | Caught by the `catch()` of the promise object | ### The get information API diff --git a/docs/support-for-different-authentication-environments/oauth2-apis.md b/docs/support-for-different-authentication-environments/oauth2-apis.md new file mode 100644 index 0000000..e254946 --- /dev/null +++ b/docs/support-for-different-authentication-environments/oauth2-apis.md @@ -0,0 +1,140 @@ +--- +title: Library OAuth2 authentication APIs +description: Describes the Embedding SDK APIs that is available for Library OAuth2 authentication. +--- + +To simplify the [Library OAuth2](https://doc-dev.microstrategy.com/producthelp/2021/Workstation/en-us/Content/oauth2.htm) login workflow, we expose new APIs + +`microstrategy.auth.oauthLogin(serverUrl, options)` + +`microstrategy.auth.oauthRefreshToken(serverUrl, options)` + +The details of those new APIs are as below: + +### `microstrategy.auth.oauthLogin(serverUrl, options)` + +#### Description + +This API can be used to start the Library OAuth2 login workflow on the embedding scenario. + +#### Input Parameters + +- `serverUrl` (`string`): + The URL of a Library server that has been successfully configured with OAuth2. + +- `options` (`OAuth2LoginOptions`): + An object containing the following fields: + + - `clientId` (`string`): + The client identifier issued by the authorization server during OAuth2 client registration. + - `clientSecret` (`string`, optional): + The client secret corresponding to the clientId, used to authenticate the client with the authorization server. + + If provided together with `requireRefreshToken: true`, a refresh token will be issued as part of the login response. + + - `requireRefreshToken` (`boolean`, optional): + Specifies whether a refresh token should be requested during login. + + Only takes effect if `clientSecret` is provided. + + If true, both an access token and a refresh token will be returned. + + If false (or omitted), only an access token will be returned. + +#### Return type + +Returns a `Promise` that resolves to an object containing the following fields: + +```ts +{ + accessToken: string; + refreshToken?: string; +} +``` + +- accessToken: The OAuth2 access token for authenticating subsequent requests. +- refreshToken (optional): The refresh token that can be used to obtain a new access token when the + current one expires. + +#### Example + +```js +microstrategy.embeddingContexts.embedLibraryPage({ + serverUrl: "{YOUR_LIBRARY_SERVER_URL}", + placeholder: document.getElementById("LibraryHomePageContainer"), + enableCustomAuthentication: true, + customAuthenticationType: microstrategy.dossier.CustomAuthenticationType.AUTH_TOKEN, + getLoginToken: async () => { + const data = await microstrategy.auth.oauthLogin("{YOUR_LIBRARY_SERVER_URL}", { + clientId: "{YOUR_OAUTH2_CLIENT_ID}", + clientSecret: "{YOUR_OAUTH2_CLIENT_SECRET}", + requireRefreshToken: true, + }); + return data.accessToken; + }, +}); +``` + +### `microstrategy.auth.oauthRefreshToken(serverUrl, options)` + +#### Description + +This API allows obtaining a new access token using a previously acquired refresh token. + +#### Input Parameters + +- `serverUrl` (`string`): + The URL of a Library server that has been successfully configured with OAuth2. + +- `options` (`OAuth2RefreshTokenOptions`): + An object containing the following fields: + + - `clientId` (`string`): + The client identifier issued by the authorization server during OAuth2 client registration. + + - `clientSecret` (`string`): + The client secret corresponding to the clientId, used to authenticate the client with the authorization server. + + - `refreshToken` (`string`): + The refresh token that was previously obtained during login. + +#### Return type + +Returns a `Promise` that resolves to an object containing the following fields: + +```ts +{ + accessToken: string; + refreshToken: string; +} +``` + +- accessToken: The OAuth2 access token for authenticating subsequent requests. +- refreshToken: The refresh token that can be used to obtain a new access token when the + current one expires. + +#### Example + +```js +const data = await microstrategy.auth.oauthRefreshToken("{YOUR_LIBRARY_SERVER_URL}", { + clientId: "{YOUR_OAUTH2_CLIENT_ID}", + clientSecret: "{YOUR_OAUTH2_CLIENT_SECRET}", + refreshToken: "{YOUR_REFRESH_TOKEN}", +}); +const { accessToken } = data; +const { refreshToken } = data; +``` + +#### API errors + +This API would have the wrong behavior or report an error in the cases below: + +- When `serverUrl` is not a Library server that supports OAuth2 login. +- If you receive a `HTTP Status 400 - Bad Request` response, ensure that the redirectUrl is [correctly configured](https://doc-dev.microstrategy.com/producthelp/2021/Workstation/en-us/Content/config_oauth2.htm). The expected format for the redirectUrl is: `YOUR_LIBRARY_SERVER_URL/static/embedding/auth-end.html?origin=YOUR_EMBEDDING_ORIGIN` and Make sure to replace: + + - `YOUR_LIBRARY_SERVER_URL` with the actual Library server URL. + - `YOUR_EMBEDDING_ORIGIN` with the origin of the embedding application. For example, if your embedding page URL is `https://example.com:8443/path/demo.html`, then the origin is `https://example.com:8443`. + +- When the client application can't get the Strategy login window because of + [COOP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy) + setting is too strict. diff --git a/docs/whats-new-in-the-embedding-sdk.md b/docs/whats-new-in-the-embedding-sdk.md index 90f7cce..5c2d36b 100644 --- a/docs/whats-new-in-the-embedding-sdk.md +++ b/docs/whats-new-in-the-embedding-sdk.md @@ -5,7 +5,17 @@ description: In each release, changes are made to make the MicroStrategy SDK mor In each release, changes are made to make the MicroStrategy SDK more powerful and easier to use. -## MicroStrategy ONE March 2025 +## Strategy ONE June 2025 + +- [Information Window](./native-embedding-architecture/information-window.md) + - Introduce the Information Window feature to enhance data visualization interactivity by providing contextual details in a dynamic overlay. + +## Strategy ONE April 2025 + +- [Properties for an embedded Library home page.](./embed-library-main-page/embed-library-properties.md#settings) + - Introduce `settings.filter.projects` to filter the library to display content from a specific project. + +## Strategy ONE March 2025 - [Embed MicroStrategy document consumption page.](./embed-document-consumption-page/embed-document-consumption-page.md) - Provide API to embed a document consumption page. diff --git a/sidebars.js b/sidebars.js index 6540a1c..1014782 100644 --- a/sidebars.js +++ b/sidebars.js @@ -36,6 +36,7 @@ const sidebars = { "support-for-different-authentication-environments/authentication-saml", "support-for-different-authentication-environments/new-authentication-apis", "support-for-different-authentication-environments/seamless-login", + "support-for-different-authentication-environments/oauth2-apis", ], }, { @@ -140,6 +141,7 @@ const sidebars = { "native-embedding-architecture/dossier-info-api", "native-embedding-architecture/apply-filter", "native-embedding-architecture/event-handling", + "native-embedding-architecture/information-window", ], }, "samples", From 3f4ef2d8b05f3965a5a04bc4b8f25e20ae0efd95 Mon Sep 17 00:00:00 2001 From: zhe Date: Fri, 20 Jun 2025 15:56:27 +0800 Subject: [PATCH 2/2] update --- .../apply-filter.md | 43 ++++++++++++++++++- docs/whats-new-in-the-embedding-sdk.md | 4 +- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/docs/native-embedding-architecture/apply-filter.md b/docs/native-embedding-architecture/apply-filter.md index 0f66a90..c296d5f 100644 --- a/docs/native-embedding-architecture/apply-filter.md +++ b/docs/native-embedding-architecture/apply-filter.md @@ -274,7 +274,9 @@ Here are some examples for the filter object in the `MstrDossier.applyFilter()` #### On-Page selectors -To apply selections to on-page selectors, use the same input as chapter-level filters. +##### Attribute Element Filter + +To apply selections on Attribute Element filter inside a page, use the same input as chapter-level filters. - Select the element list of the selector @@ -326,6 +328,45 @@ To apply selections to on-page selectors, use the same input as chapter-level fi } ``` +##### Attribute/Metric Selector + +To apply selections on an Attribute/Metric selector inside a page, you can use the following input: + +- Select the object list of the selector + + ```js + try { + await mstrDossier.applyFilter({ + key: "W76", + currentSelection: { + objectItems: [ + { + id: "", + name: "", + }, + ], + }, + }); + } catch (error) { + // Your own error handling code + } + ``` + +- Unset the selection of the selector + + ```js + try { + await mstrDossier.applyFilter({ + key: "W76", + currentSelection: { + selectionStatus: "unfiltered", + }, + }); + } catch (error) { + // Your own error handling code + } + ``` + #### Visualizations used as filters - Select attribute elements of the visualization diff --git a/docs/whats-new-in-the-embedding-sdk.md b/docs/whats-new-in-the-embedding-sdk.md index 5c2d36b..e6ca828 100644 --- a/docs/whats-new-in-the-embedding-sdk.md +++ b/docs/whats-new-in-the-embedding-sdk.md @@ -8,7 +8,9 @@ In each release, changes are made to make the MicroStrategy SDK more powerful an ## Strategy ONE June 2025 - [Information Window](./native-embedding-architecture/information-window.md) - - Introduce the Information Window feature to enhance data visualization interactivity by providing contextual details in a dynamic overlay. + - Introduce the Information Window feature in Native Embedding SDK to enhance data visualization interactivity by providing contextual details in a dynamic overlay. +- [Retrieve and apply filters](./native-embedding-architecture/apply-filter#attributemetric-selector) + - Support the Attribute/Metric selector in `MstrDossier.applyFilter()` and `MstrDossier.applyFilters()` in Native Embedding SDK. ## Strategy ONE April 2025