diff --git a/.gitignore b/.gitignore index 640fe628..75dcda63 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ dist/powerbi.js.map *.js.map package-lock.json demo/package-lock.json +.vscode diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 4479811e..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,6 +0,0 @@ -// Place your settings in this file to overwrite default and user settings. -{ - "editor.tabSize": 2, - "editor.insertSpaces": true, - "editor.detectIndentation": false -} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index a7b839de..00000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "0.1.0", - "command": "npm", - "isShellCommand": true, - "showOutput": "always", - "suppressTaskName": true, - "tasks": [ - { - "taskName": "build", - "args": [ - "run", - "build" - ], - "isBuildCommand": true - }, - { - "taskName": "test", - "args": [ - "run", - "test", - "--", - "--chrome" - ], - "isTestCommand": true - } - ] -} \ No newline at end of file diff --git a/dist/powerbi-client.d.ts b/dist/powerbi-client.d.ts index 4dff3966..1926be6a 100644 --- a/dist/powerbi-client.d.ts +++ b/dist/powerbi-client.d.ts @@ -1,6 +1,18 @@ -// powerbi-client v2.18.1 +// powerbi-client v2.18.4 // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +declare module "config" { + /** @ignore */ /** */ + const config: { + version: string; + type: string; + }; + export default config; +} +declare module "errors" { + export const APINotSupportedForRDLError = "This API is currently not supported for RDL reports"; + export const EmbedUrlNotSupported = "Embed URL is invalid for this scenario. Please use Power BI REST APIs to get the valid URL"; +} declare module "util" { import { HttpPostMessage } from 'http-post-message'; /** @@ -105,21 +117,9 @@ declare module "util" { */ export function getTimeDiffInMilliseconds(start: Date, end: Date): number; } -declare module "config" { - /** @ignore */ /** */ - const config: { - version: string; - type: string; - }; - export default config; -} -declare module "errors" { - export const APINotSupportedForRDLError = "This API is currently not supported for RDL reports"; - export const EmbedUrlNotSupported = "Embed URL is invalid for this scenario. Please use Power BI REST APIs to get the valid URL"; -} declare module "embed" { import * as models from 'powerbi-models'; - import { Service, IEventHandler, IEvent, ICustomEvent } from "service"; + import { ICustomEvent, IEvent, IEventHandler, Service } from "service"; global { interface Document { mozCancelFullScreen: any; @@ -177,6 +177,12 @@ declare module "embed" { static maxFrontLoadTimes: number; /** @hidden */ allowedEvents: string[]; + /** @hidden */ + protected commands: models.ICommandExtension[]; + /** @hidden */ + protected initialLayoutType: models.LayoutType; + /** @hidden */ + groups: models.IMenuGroupExtension[]; /** * Gets or sets the event handler registered for this embed component. * @@ -573,7 +579,7 @@ declare module "ifilterable" { } } declare module "visualDescriptor" { - import { ExportDataType, FiltersOperations, ICloneVisualRequest, ICloneVisualResponse, IExportDataResult, IFilter, ISlicerState, ISortByVisualRequest, IVisualLayout } from 'powerbi-models'; + import { ExportDataType, FiltersOperations, ICloneVisualRequest, ICloneVisualResponse, IExportDataResult, IFilter, ISlicerState, ISortByVisualRequest, IVisualLayout, VisualContainerDisplayMode } from 'powerbi-models'; import { IHttpPostMessageResponse } from 'http-post-message'; import { IFilterable } from "ifilterable"; import { IPageNode } from "page"; @@ -731,11 +737,50 @@ declare module "visualDescriptor" { * ``` */ sortBy(request: ISortByVisualRequest): Promise>; + /** + * Updates the position of a visual. + * + * ```javascript + * visual.moveVisual(x, y, z) + * .catch(error => { ... }); + * ``` + * + * @param {number} x + * @param {number} y + * @param {number} z + * @returns {Promise>} + */ + moveVisual(x: number, y: number, z?: number): Promise>; + /** + * Updates the display state of a visual. + * + * ```javascript + * visual.setVisualDisplayState(displayState) + * .catch(error => { ... }); + * ``` + * + * @param {VisualContainerDisplayMode} displayState + * @returns {Promise>} + */ + setVisualDisplayState(displayState: VisualContainerDisplayMode): Promise>; + /** + * Resize a visual. + * + * ```javascript + * visual.resizeVisual(width, height) + * .catch(error => { ... }); + * ``` + * + * @param {number} width + * @param {number} height + * @returns {Promise>} + */ + resizeVisual(width: number, height: number): Promise>; } } declare module "page" { import { IHttpPostMessageResponse } from 'http-post-message'; - import { DisplayOption, FiltersOperations, ICustomPageSize, IFilter, LayoutType, SectionVisibility } from 'powerbi-models'; + import { DisplayOption, FiltersOperations, ICustomPageSize, IFilter, IVisual, LayoutType, PageSizeType, SectionVisibility, VisualContainerDisplayMode } from 'powerbi-models'; import { IFilterable } from "ifilterable"; import { IReportNode } from "report"; import { VisualDescriptor } from "visualDescriptor"; @@ -796,6 +841,12 @@ declare module "page" { * @type {ICustomPageSize} */ defaultSize: ICustomPageSize; + /** + * Mobile view page size (if defined) as saved in the report. + * + * @type {ICustomPageSize} + */ + mobileSize: ICustomPageSize; /** * Page display options as saved in the report. * @@ -812,7 +863,7 @@ declare module "page" { * @param {SectionVisibility} [visibility] * @hidden */ - constructor(report: IReportNode, name: string, displayName?: string, isActivePage?: boolean, visibility?: SectionVisibility, defaultSize?: ICustomPageSize, defaultDisplayOption?: DisplayOption); + constructor(report: IReportNode, name: string, displayName?: string, isActivePage?: boolean, visibility?: SectionVisibility, defaultSize?: ICustomPageSize, defaultDisplayOption?: DisplayOption, mobileSize?: ICustomPageSize); /** * Gets all page level filters within the report. * @@ -900,6 +951,89 @@ declare module "page" { * @returns {Promise} */ getVisuals(): Promise; + /** + * Gets a visual by name on the page. + * + * ```javascript + * page.getVisualByName(visualName: string) + * .then(visual => { + * ... + * }); + * ``` + * + * @param {string} visualName + * @returns {Promise} + */ + getVisualByName(visualName: string): Promise; + /** + * Updates the display state of a visual in a page. + * + * ```javascript + * page.setVisualDisplayState(visualName, displayState) + * .catch(error => { ... }); + * ``` + * + * @param {string} visualName + * @param {VisualContainerDisplayMode} displayState + * @returns {Promise>} + */ + setVisualDisplayState(visualName: string, displayState: VisualContainerDisplayMode): Promise>; + /** + * Updates the position of a visual in a page. + * + * ```javascript + * page.moveVisual(visualName, x, y, z) + * .catch(error => { ... }); + * ``` + * + * @param {string} visualName + * @param {number} x + * @param {number} y + * @param {number} z + * @returns {Promise>} + */ + moveVisual(visualName: string, x: number, y: number, z?: number): Promise>; + /** + * Resize a visual in a page. + * + * ```javascript + * page.resizeVisual(visualName, width, height) + * .catch(error => { ... }); + * ``` + * + * @param {string} visualName + * @param {number} width + * @param {number} height + * @returns {Promise>} + */ + resizeVisual(visualName: string, width: number, height: number): Promise>; + /** + * Updates the size of active page. + * + * ```javascript + * page.resizePage(pageSizeType, width, height) + * .catch(error => { ... }); + * ``` + * + * @param {PageSizeType} pageSizeType + * @param {number} width + * @param {number} height + * @returns {Promise>} + */ + resizePage(pageSizeType: PageSizeType, width?: number, height?: number): Promise>; + /** + * Gets the list of slicer visuals on the page. + * + * ```javascript + * page.getSlicers() + * .then(slicers => { + * ... + * }); + * ``` + * + * @returns {Promise} + */ + getSlicers(): Promise; /** * Checks if page has layout. * @@ -914,7 +1048,7 @@ declare module "page" { } } declare module "report" { - import { IReportLoadConfiguration, IReportEmbedConfiguration, FiltersOperations, IError, IFilter, IReportTheme, ISettings, SectionVisibility, ViewMode, IEmbedConfiguration, IEmbedConfigurationBase } from 'powerbi-models'; + import { IReportLoadConfiguration, IReportEmbedConfiguration, FiltersOperations, IError, IFilter, IReportTheme, ISettings, LayoutType, SectionVisibility, ViewMode, IEmbedConfiguration, IEmbedConfigurationBase, MenuLocation, PageSizeType, VisualContainerDisplayMode } from 'powerbi-models'; import { IHttpPostMessageResponse } from 'http-post-message'; import { IService, Service } from "service"; import { Embed } from "embed"; @@ -1098,6 +1232,33 @@ declare module "report" { * @returns {Promise} */ getPages(): Promise; + /** + * Gets a report page by its name. + * + * ```javascript + * report.getPageByName(pageName) + * .then(page => { + * ... + * }); + * ``` + * + * @param {string} pageName + * @returns {Promise} + */ + getPageByName(pageName: string): Promise; + /** + * Gets the active report page. + * + * ```javascript + * report.getActivePage() + * .then(activePage => { + * ... + * }); + * ``` + * + * @returns {Promise} + */ + getActivePage(): Promise; /** * Creates an instance of a Page. * @@ -1234,6 +1395,163 @@ declare module "report" { * @returns {Promise} */ arePersistentFiltersApplied(): Promise; + /** + * Remove context menu extension command. + * + * ```javascript + * report.removeContextMenuCommand(commandName, contextMenuTitle) + * .catch(error => { + * ... + * }); + * ``` + * + * @param {string} commandName + * @param {string} contextMenuTitle + * @returns {Promise>} + */ + removeContextMenuCommand(commandName: string, contextMenuTitle: string): Promise>; + /** + * Add context menu extension command. + * + * ```javascript + * report.addContextMenuCommand(commandName, commandTitle, contextMenuTitle, menuLocation, visualName, visualType, groupName) + * .catch(error => { + * ... + * }); + * ``` + * + * @param {string} commandName + * @param {string} commandTitle + * @param {string} contextMenuTitle + * @param {MenuLocation} menuLocation + * @param {string} visualName + * @param {string} visualType + * @param {string} groupName + * @returns {Promise>} + */ + addContextMenuCommand(commandName: string, commandTitle: string, contextMenuTitle: string, menuLocation: MenuLocation, visualName: string, visualType: string, groupName?: string): Promise>; + /** + * Remove options menu extension command. + * + * ```javascript + * report.removeOptionsMenuCommand(commandName, optionsMenuTitle) + * .then({ + * ... + * }); + * ``` + * + * @param {string} commandName + * @param {string} optionsMenuTitle + * @returns {Promise>} + */ + removeOptionsMenuCommand(commandName: string, optionsMenuTitle: string): Promise>; + /** + * Add options menu extension command. + * + * ```javascript + * report.addOptionsMenuCommand(commandName, commandTitle, optionsMenuTitle, menuLocation, visualName, visualType, groupName, commandIcon) + * .catch(error => { + * ... + * }); + * ``` + * + * @param {string} commandName + * @param {string} commandTitle + * @param {string} optionMenuTitle + * @param {MenuLocation} menuLocation + * @param {string} visualName + * @param {string} visualType + * @param {string} groupName + * @param {string} commandIcon + * @returns {Promise>} + */ + addOptionsMenuCommand(commandName: string, commandTitle: string, optionsMenuTitle?: string, menuLocation?: MenuLocation, visualName?: string, visualType?: string, groupName?: string, commandIcon?: string): Promise>; + /** + * Updates the display state of a visual in a page. + * + * ```javascript + * report.setVisualDisplayState(pageName, visualName, displayState) + * .catch(error => { ... }); + * ``` + * + * @param {string} pageName + * @param {string} visualName + * @param {VisualContainerDisplayMode} displayState + * @returns {Promise>} + */ + setVisualDisplayState(pageName: string, visualName: string, displayState: VisualContainerDisplayMode): Promise>; + /** + * Resize a visual in a page. + * + * ```javascript + * report.resizeVisual(pageName, visualName, width, height) + * .catch(error => { ... }); + * ``` + * + * @param {string} pageName + * @param {string} visualName + * @param {number} width + * @param {number} height + * @returns {Promise>} + */ + resizeVisual(pageName: string, visualName: string, width: number, height: number): Promise>; + /** + * Updates the size of active page in report. + * + * ```javascript + * report.resizeActivePage(pageSizeType, width, height) + * .catch(error => { ... }); + * ``` + * + * @param {PageSizeType} pageSizeType + * @param {number} width + * @param {number} height + * @returns {Promise>} + */ + resizeActivePage(pageSizeType: PageSizeType, width?: number, height?: number): Promise>; + /** + * Updates the position of a visual in a page. + * + * ```javascript + * report.moveVisual(pageName, visualName, x, y, z) + * .catch(error => { ... }); + * ``` + * + * @param {string} pageName + * @param {string} visualName + * @param {number} x + * @param {number} y + * @param {number} z + * @returns {Promise>} + */ + moveVisual(pageName: string, visualName: string, x: number, y: number, z?: number): Promise>; + /** + * Updates the report layout + * + * ```javascript + * report.switchLayout(layoutType); + * ``` + * + * @param {LayoutType} layoutType + * @returns {Promise>} + */ + switchLayout(layoutType: LayoutType): Promise>; + /** + * @hidden + */ + private createMenuCommand; + /** + * @hidden + */ + private findCommandMenuIndex; + /** + * @hidden + */ + private buildLayoutSettingsObject; + /** + * @hidden + */ + private validateVisual; /** * @hidden */ @@ -1809,6 +2127,10 @@ declare module "service" { * @hidden */ private embedExisting; + /** + * @hidden + */ + private registerApplicationContextHook; /** * Adds an event handler for DOMContentLoaded, which searches the DOM for elements that have the 'powerbi-embed-url' attribute, * and automatically attempts to embed a powerbi component based on information from other powerbi-* attributes. @@ -1977,6 +2299,425 @@ declare module "factories" { export const wpmpFactory: IWpmpFactory; export const routerFactory: IRouterFactory; } +declare module "FilterBuilders/filterBuilder" { + import { IFilterTarget } from "powerbi-models"; + /** + * Generic filter builder for BasicFilter, AdvancedFilter, RelativeDate, RelativeTime and TopN + * + * @class + */ + export class FilterBuilder { + target: IFilterTarget; + /** + * Sets target property for filter with target object + * + * ```javascript + * const target = { + * table: 'table1', + * column: 'column1' + * }; + * + * const filterBuilder = new FilterBuilder().withTargetObject(target); + * ``` + * + * @returns {FilterBuilder} + */ + withTargetObject(target: IFilterTarget): this; + /** + * Sets target property for filter with column target object + * + * ``` + * const filterBuilder = new FilterBuilder().withColumnTarget(tableName, columnName); + * ``` + * + * @returns {FilterBuilder} + */ + withColumnTarget(tableName: string, columnName: string): this; + /** + * Sets target property for filter with measure target object + * + * ``` + * const filterBuilder = new FilterBuilder().withMeasureTarget(tableName, measure); + * ``` + * + * @returns {FilterBuilder} + */ + withMeasureTarget(tableName: string, measure: string): this; + /** + * Sets target property for filter with hierarchy level target object + * + * ``` + * const filterBuilder = new FilterBuilder().withHierarchyLevelTarget(tableName, hierarchy, hierarchyLevel); + * ``` + * + * @returns {FilterBuilder} + */ + withHierarchyLevelTarget(tableName: string, hierarchy: string, hierarchyLevel: string): this; + /** + * Sets target property for filter with column aggregation target object + * + * ``` + * const filterBuilder = new FilterBuilder().withColumnAggregation(tableName, columnName, aggregationFunction); + * ``` + * + * @returns {FilterBuilder} + */ + withColumnAggregation(tableName: string, columnName: string, aggregationFunction: string): this; + /** + * Sets target property for filter with hierarchy level aggregation target object + * + * ``` + * const filterBuilder = new FilterBuilder().withHierarchyLevelAggregationTarget(tableName, hierarchy, hierarchyLevel, aggregationFunction); + * ``` + * + * @returns {FilterBuilder} + */ + withHierarchyLevelAggregationTarget(tableName: string, hierarchy: string, hierarchyLevel: string, aggregationFunction: string): this; + } +} +declare module "FilterBuilders/basicFilterBuilder" { + import { BasicFilter } from "powerbi-models"; + import { FilterBuilder } from "FilterBuilders/filterBuilder"; + /** + * Power BI Basic filter builder component + * + * @export + * @class BasicFilterBuilder + * @extends {FilterBuilder} + */ + export class BasicFilterBuilder extends FilterBuilder { + private values; + private operator; + private isRequireSingleSelection; + /** + * Sets In as operator for Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().in([values]); + * ``` + * + * @returns {BasicFilterBuilder} + */ + in(values: Array<(string | number | boolean)>): BasicFilterBuilder; + /** + * Sets NotIn as operator for Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().notIn([values]); + * ``` + * + * @returns {BasicFilterBuilder} + */ + notIn(values: Array<(string | number | boolean)>): BasicFilterBuilder; + /** + * Sets All as operator for Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().all(); + * ``` + * + * @returns {BasicFilterBuilder} + */ + all(): BasicFilterBuilder; + /** + * Sets required single selection property for Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().requireSingleSelection(isRequireSingleSelection); + * ``` + * + * @returns {BasicFilterBuilder} + */ + requireSingleSelection(isRequireSingleSelection?: boolean): BasicFilterBuilder; + /** + * Creates Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().build(); + * ``` + * + * @returns {BasicFilter} + */ + build(): BasicFilter; + } +} +declare module "FilterBuilders/advancedFilterBuilder" { + import { AdvancedFilter, AdvancedFilterConditionOperators } from "powerbi-models"; + import { FilterBuilder } from "FilterBuilders/filterBuilder"; + /** + * Power BI Advanced filter builder component + * + * @export + * @class AdvancedFilterBuilder + * @extends {FilterBuilder} + */ + export class AdvancedFilterBuilder extends FilterBuilder { + private logicalOperator; + private conditions; + /** + * Sets And as logical operator for Advanced filter + * + * ```javascript + * + * const advancedFilterBuilder = new AdvancedFilterBuilder().and(); + * ``` + * + * @returns {AdvancedFilterBuilder} + */ + and(): AdvancedFilterBuilder; + /** + * Sets Or as logical operator for Advanced filter + * + * ```javascript + * + * const advancedFilterBuilder = new AdvancedFilterBuilder().or(); + * ``` + * + * @returns {AdvancedFilterBuilder} + */ + or(): AdvancedFilterBuilder; + /** + * Adds a condition in Advanced filter + * + * ```javascript + * + * // Add two conditions + * const advancedFilterBuilder = new AdvancedFilterBuilder().addCondition("Contains", "Wash").addCondition("Contains", "Park"); + * ``` + * + * @returns {AdvancedFilterBuilder} + */ + addCondition(operator: AdvancedFilterConditionOperators, value?: (string | number | boolean | Date)): AdvancedFilterBuilder; + /** + * Creates Advanced filter + * + * ```javascript + * + * const advancedFilterBuilder = new AdvancedFilterBuilder().build(); + * ``` + * + * @returns {AdvancedFilter} + */ + build(): AdvancedFilter; + } +} +declare module "FilterBuilders/topNFilterBuilder" { + import { ITarget, TopNFilter } from "powerbi-models"; + import { FilterBuilder } from "FilterBuilders/filterBuilder"; + /** + * Power BI Top N filter builder component + * + * @export + * @class TopNFilterBuilder + * @extends {FilterBuilder} + */ + export class TopNFilterBuilder extends FilterBuilder { + private itemCount; + private operator; + private orderByTargetValue; + /** + * Sets Top as operator for Top N filter + * + * ```javascript + * + * const topNFilterBuilder = new TopNFilterBuilder().top(itemCount); + * ``` + * + * @returns {TopNFilterBuilder} + */ + top(itemCount: number): TopNFilterBuilder; + /** + * Sets Bottom as operator for Top N filter + * + * ```javascript + * + * const topNFilterBuilder = new TopNFilterBuilder().bottom(itemCount); + * ``` + * + * @returns {TopNFilterBuilder} + */ + bottom(itemCount: number): TopNFilterBuilder; + /** + * Sets order by for Top N filter + * + * ```javascript + * + * const topNFilterBuilder = new TopNFilterBuilder().orderByTarget(target); + * ``` + * + * @returns {TopNFilterBuilder} + */ + orderByTarget(target: ITarget): TopNFilterBuilder; + /** + * Creates Top N filter + * + * ```javascript + * + * const topNFilterBuilder = new TopNFilterBuilder().build(); + * ``` + * + * @returns {TopNFilter} + */ + build(): TopNFilter; + } +} +declare module "FilterBuilders/relativeDateFilterBuilder" { + import { RelativeDateFilter, RelativeDateFilterTimeUnit } from "powerbi-models"; + import { FilterBuilder } from "FilterBuilders/filterBuilder"; + /** + * Power BI Relative Date filter builder component + * + * @export + * @class RelativeDateFilterBuilder + * @extends {FilterBuilder} + */ + export class RelativeDateFilterBuilder extends FilterBuilder { + private operator; + private timeUnitsCount; + private timeUnitType; + private isTodayIncluded; + /** + * Sets inLast as operator for Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().inLast(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeDateFilterBuilder} + */ + inLast(timeUnitsCount: number, timeUnitType: RelativeDateFilterTimeUnit): RelativeDateFilterBuilder; + /** + * Sets inThis as operator for Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().inThis(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeDateFilterBuilder} + */ + inThis(timeUnitsCount: number, timeUnitType: RelativeDateFilterTimeUnit): RelativeDateFilterBuilder; + /** + * Sets inNext as operator for Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().inNext(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeDateFilterBuilder} + */ + inNext(timeUnitsCount: number, timeUnitType: RelativeDateFilterTimeUnit): RelativeDateFilterBuilder; + /** + * Sets includeToday for Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().includeToday(includeToday); + * ``` + * + * @param {boolean} includeToday - Denotes if today is included or not + * @returns {RelativeDateFilterBuilder} + */ + includeToday(includeToday: boolean): RelativeDateFilterBuilder; + /** + * Creates Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().build(); + * ``` + * + * @returns {RelativeDateFilter} + */ + build(): RelativeDateFilter; + } +} +declare module "FilterBuilders/relativeTimeFilterBuilder" { + import { RelativeTimeFilter, RelativeDateFilterTimeUnit } from "powerbi-models"; + import { FilterBuilder } from "FilterBuilders/filterBuilder"; + /** + * Power BI Relative Time filter builder component + * + * @export + * @class RelativeTimeFilterBuilder + * @extends {FilterBuilder} + */ + export class RelativeTimeFilterBuilder extends FilterBuilder { + private operator; + private timeUnitsCount; + private timeUnitType; + /** + * Sets inLast as operator for Relative Time filter + * + * ```javascript + * + * const relativeTimeFilterBuilder = new RelativeTimeFilterBuilder().inLast(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeTimeFilterBuilder} + */ + inLast(timeUnitsCount: number, timeUnitType: RelativeDateFilterTimeUnit): RelativeTimeFilterBuilder; + /** + * Sets inThis as operator for Relative Time filter + * + * ```javascript + * + * const relativeTimeFilterBuilder = new RelativeTimeFilterBuilder().inThis(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeTimeFilterBuilder} + */ + inThis(timeUnitsCount: number, timeUnitType: RelativeDateFilterTimeUnit): RelativeTimeFilterBuilder; + /** + * Sets inNext as operator for Relative Time filter + * + * ```javascript + * + * const relativeTimeFilterBuilder = new RelativeTimeFilterBuilder().inNext(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeTimeFilterBuilder} + */ + inNext(timeUnitsCount: number, timeUnitType: RelativeDateFilterTimeUnit): RelativeTimeFilterBuilder; + /** + * Creates Relative Time filter + * + * ```javascript + * + * const relativeTimeFilterBuilder = new RelativeTimeFilterBuilder().build(); + * ``` + * + * @returns {RelativeTimeFilter} + */ + build(): RelativeTimeFilter; + } +} +declare module "FilterBuilders/index" { + export { BasicFilterBuilder } from "FilterBuilders/basicFilterBuilder"; + export { AdvancedFilterBuilder } from "FilterBuilders/advancedFilterBuilder"; + export { TopNFilterBuilder } from "FilterBuilders/topNFilterBuilder"; + export { RelativeDateFilterBuilder } from "FilterBuilders/relativeDateFilterBuilder"; + export { RelativeTimeFilterBuilder } from "FilterBuilders/relativeTimeFilterBuilder"; +} declare module "powerbi-client" { /** * @hidden @@ -1994,6 +2735,7 @@ declare module "powerbi-client" { export { Qna } from "qna"; export { Visual } from "visual"; export { VisualDescriptor } from "visualDescriptor"; + export { BasicFilterBuilder, AdvancedFilterBuilder, TopNFilterBuilder, RelativeDateFilterBuilder, RelativeTimeFilterBuilder } from "FilterBuilders/index"; global { interface Window { powerbi: service.Service; diff --git a/dist/powerbi.js b/dist/powerbi.js index 612f8128..2b6e0d56 100644 --- a/dist/powerbi.js +++ b/dist/powerbi.js @@ -1,4 +1,4 @@ -// powerbi-client v2.18.1 +// powerbi-client v2.18.4 // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. (function webpackUniversalModuleDefinition(root, factory) { @@ -290,7 +290,7 @@ return /******/ (function(modules) { // webpackBootstrap /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { -// powerbi-models v1.9.0 +// powerbi-models v1.9.3 // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. (function webpackUniversalModuleDefinition(root, factory) { @@ -404,7 +404,7 @@ var __extends = (this && this.__extends) || (function () { }; })(); Object.defineProperty(exports, "__esModule", { value: true }); -exports.validateCustomTheme = exports.validateCommandsSettings = exports.validateVisualSettings = exports.validateVisualHeader = exports.validateExportDataRequest = exports.validateQnaInterpretInputData = exports.validateLoadQnaConfiguration = exports.validateSaveAsParameters = exports.validateUpdateFiltersRequest = exports.validateFilter = exports.validatePage = exports.validateTileLoad = exports.validateDashboardLoad = exports.validateCreateReport = exports.validatePaginatedReportLoad = exports.validateReportLoad = exports.validateMenuGroupExtension = exports.validateExtension = exports.validateCustomPageSize = exports.validateVisualizationsPane = exports.validateSyncSlicersPane = exports.validateSelectionPane = exports.validatePageNavigationPane = exports.validateFieldsPane = exports.validateFiltersPane = exports.validateBookmarksPane = exports.validatePanes = exports.validateSettings = exports.validateCaptureBookmarkRequest = exports.validateApplyBookmarkStateRequest = exports.validateApplyBookmarkByNameRequest = exports.validateAddBookmarkRequest = exports.validatePlayBookmarkRequest = exports.validateSlicerState = exports.validateSlicer = exports.validateVisualSelector = exports.isIExtensionArray = exports.isIExtensions = exports.isGroupedMenuExtension = exports.isFlatMenuExtension = exports.isReportFiltersArray = exports.isOnLoadFilters = exports.VisualDataRoleKindPreference = exports.VisualDataRoleKind = exports.CommandDisplayOption = exports.SlicerTargetSelector = exports.VisualTypeSelector = exports.VisualSelector = exports.PageSelector = exports.Selector = exports.SortDirection = exports.LegendPosition = exports.TextAlignment = exports.CommonErrorCodes = exports.BookmarksPlayMode = exports.ExportDataType = exports.QnaMode = exports.PageNavigationPosition = exports.isColumnAggr = exports.isHierarchyLevelAggr = exports.isHierarchyLevel = exports.isColumn = exports.isMeasure = exports.getFilterType = exports.isBasicFilterWithKeys = exports.isFilterKeyColumnsTarget = exports.AdvancedFilter = exports.TupleFilter = exports.BasicFilterWithKeys = exports.BasicFilter = exports.RelativeTimeFilter = exports.RelativeDateFilter = exports.TopNFilter = exports.IncludeExcludeFilter = exports.NotSupportedFilter = exports.Filter = exports.RelativeDateOperators = exports.RelativeDateFilterTimeUnit = exports.FilterType = exports.FiltersLevel = exports.FiltersOperations = exports.MenuLocation = exports.ContrastMode = exports.TokenType = exports.ViewMode = exports.Permissions = exports.SectionVisibility = exports.HyperlinkClickBehavior = exports.LayoutType = exports.VisualContainerDisplayMode = exports.BackgroundType = exports.DisplayOption = exports.PageSizeType = exports.TraceType = void 0; +exports.validateCustomTheme = exports.validateCommandsSettings = exports.validateVisualSettings = exports.validateVisualHeader = exports.validateExportDataRequest = exports.validateQnaInterpretInputData = exports.validateLoadQnaConfiguration = exports.validateSaveAsParameters = exports.validateUpdateFiltersRequest = exports.validateFilter = exports.validatePage = exports.validateTileLoad = exports.validateDashboardLoad = exports.validateCreateReport = exports.validatePaginatedReportLoad = exports.validateReportLoad = exports.validateMenuGroupExtension = exports.validateExtension = exports.validateCustomPageSize = exports.validateVisualizationsPane = exports.validateSyncSlicersPane = exports.validateSelectionPane = exports.validatePageNavigationPane = exports.validateFieldsPane = exports.validateFiltersPane = exports.validateBookmarksPane = exports.validatePanes = exports.validateSettings = exports.validateCaptureBookmarkRequest = exports.validateApplyBookmarkStateRequest = exports.validateApplyBookmarkByNameRequest = exports.validateAddBookmarkRequest = exports.validatePlayBookmarkRequest = exports.validateSlicerState = exports.validateSlicer = exports.validateVisualSelector = exports.isIExtensionArray = exports.isIExtensions = exports.isGroupedMenuExtension = exports.isFlatMenuExtension = exports.isReportFiltersArray = exports.isOnLoadFilters = exports.VisualDataRoleKindPreference = exports.VisualDataRoleKind = exports.CommandDisplayOption = exports.SlicerTargetSelector = exports.VisualTypeSelector = exports.VisualSelector = exports.PageSelector = exports.Selector = exports.SortDirection = exports.LegendPosition = exports.TextAlignment = exports.CommonErrorCodes = exports.BookmarksPlayMode = exports.ExportDataType = exports.QnaMode = exports.PageNavigationPosition = exports.isColumnAggr = exports.isHierarchyLevelAggr = exports.isHierarchyLevel = exports.isColumn = exports.isMeasure = exports.getFilterType = exports.isBasicFilterWithKeys = exports.isFilterKeyColumnsTarget = exports.AdvancedFilter = exports.TupleFilter = exports.IdentityFilter = exports.BasicFilterWithKeys = exports.BasicFilter = exports.RelativeTimeFilter = exports.RelativeDateFilter = exports.TopNFilter = exports.IncludeExcludeFilter = exports.NotSupportedFilter = exports.Filter = exports.RelativeDateOperators = exports.RelativeDateFilterTimeUnit = exports.FilterType = exports.FiltersLevel = exports.FiltersOperations = exports.MenuLocation = exports.ContrastMode = exports.TokenType = exports.ViewMode = exports.Permissions = exports.SectionVisibility = exports.HyperlinkClickBehavior = exports.LayoutType = exports.VisualContainerDisplayMode = exports.BackgroundType = exports.DisplayOption = exports.PageSizeType = exports.TraceType = void 0; var validator_1 = __webpack_require__(1); var TraceType; (function (TraceType) { @@ -423,6 +423,7 @@ var PageSizeType; PageSizeType[PageSizeType["Cortana"] = 2] = "Cortana"; PageSizeType[PageSizeType["Letter"] = 3] = "Letter"; PageSizeType[PageSizeType["Custom"] = 4] = "Custom"; + PageSizeType[PageSizeType["Mobile"] = 5] = "Mobile"; })(PageSizeType = exports.PageSizeType || (exports.PageSizeType = {})); var DisplayOption; (function (DisplayOption) { @@ -512,6 +513,7 @@ var FilterType; FilterType[FilterType["TopN"] = 5] = "TopN"; FilterType[FilterType["Tuple"] = 6] = "Tuple"; FilterType[FilterType["RelativeTime"] = 7] = "RelativeTime"; + FilterType[FilterType["Identity"] = 8] = "Identity"; })(FilterType = exports.FilterType || (exports.FilterType = {})); var RelativeDateFilterTimeUnit; (function (RelativeDateFilterTimeUnit) { @@ -723,6 +725,24 @@ var BasicFilterWithKeys = /** @class */ (function (_super) { return BasicFilterWithKeys; }(BasicFilter)); exports.BasicFilterWithKeys = BasicFilterWithKeys; +var IdentityFilter = /** @class */ (function (_super) { + __extends(IdentityFilter, _super); + function IdentityFilter(target, operator) { + var _this = _super.call(this, target, FilterType.Identity) || this; + _this.operator = operator; + _this.schemaUrl = IdentityFilter.schemaUrl; + return _this; + } + IdentityFilter.prototype.toJSON = function () { + var filter = _super.prototype.toJSON.call(this); + filter.operator = this.operator; + filter.target = this.target; + return filter; + }; + IdentityFilter.schemaUrl = "http://powerbi.com/product/schema#identity"; + return IdentityFilter; +}(Filter)); +exports.IdentityFilter = IdentityFilter; var TupleFilter = /** @class */ (function (_super) { __extends(TupleFilter, _super); function TupleFilter(target, operator, values) { @@ -6124,280 +6144,1000 @@ return /******/ (function(modules) { // webpackBootstrap /***/ }), -/***/ "./src/bookmarksManager.ts": -/*!*********************************!*\ - !*** ./src/bookmarksManager.ts ***! - \*********************************/ +/***/ "./src/FilterBuilders/advancedFilterBuilder.ts": +/*!*****************************************************!*\ + !*** ./src/FilterBuilders/advancedFilterBuilder.ts ***! + \*****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); Object.defineProperty(exports, "__esModule", { value: true }); -exports.BookmarksManager = void 0; -var util_1 = __webpack_require__(/*! ./util */ "./src/util.ts"); -var errors_1 = __webpack_require__(/*! ./errors */ "./src/errors.ts"); +exports.AdvancedFilterBuilder = void 0; +var powerbi_models_1 = __webpack_require__(/*! powerbi-models */ "./node_modules/powerbi-models/dist/models.js"); +var filterBuilder_1 = __webpack_require__(/*! ./filterBuilder */ "./src/FilterBuilders/filterBuilder.ts"); /** - * Manages report bookmarks. + * Power BI Advanced filter builder component * * @export - * @class BookmarksManager - * @implements {IBookmarksManager} + * @class AdvancedFilterBuilder + * @extends {FilterBuilder} */ -var BookmarksManager = /** @class */ (function () { - /** - * @hidden - */ - function BookmarksManager(service, config, iframe) { - this.service = service; - this.config = config; - this.iframe = iframe; +var AdvancedFilterBuilder = /** @class */ (function (_super) { + __extends(AdvancedFilterBuilder, _super); + function AdvancedFilterBuilder() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.conditions = []; + return _this; } /** - * Gets bookmarks that are defined in the report. + * Sets And as logical operator for Advanced filter * * ```javascript - * // Gets bookmarks that are defined in the report - * bookmarksManager.getBookmarks() - * .then(bookmarks => { - * ... - * }); - * ``` - * - * @returns {Promise} - */ - BookmarksManager.prototype.getBookmarks = function () { - return __awaiter(this, void 0, void 0, function () { - var response, response_1; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (util_1.isRDLEmbed(this.config.embedUrl)) { - return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; - } - _a.label = 1; - case 1: - _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, this.service.hpm.get("/report/bookmarks", { uid: this.config.uniqueId }, this.iframe.contentWindow)]; - case 2: - response = _a.sent(); - return [2 /*return*/, response.body]; - case 3: - response_1 = _a.sent(); - throw response_1.body; - case 4: return [2 /*return*/]; - } - }); - }); - }; - /** - * Apply bookmark by name. * - * ```javascript - * bookmarksManager.apply(bookmarkName) + * const advancedFilterBuilder = new AdvancedFilterBuilder().and(); * ``` * - * @param {string} bookmarkName The name of the bookmark to be applied - * @returns {Promise>} + * @returns {AdvancedFilterBuilder} */ - BookmarksManager.prototype.apply = function (bookmarkName) { - return __awaiter(this, void 0, void 0, function () { - var request, response_2; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (util_1.isRDLEmbed(this.config.embedUrl)) { - return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; - } - request = { - name: bookmarkName - }; - _a.label = 1; - case 1: - _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, this.service.hpm.post("/report/bookmarks/applyByName", request, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; - case 2: return [2 /*return*/, _a.sent()]; - case 3: - response_2 = _a.sent(); - throw response_2.body; - case 4: return [2 /*return*/]; - } - }); - }); + AdvancedFilterBuilder.prototype.and = function () { + this.logicalOperator = "And"; + return this; }; /** - * Play bookmarks: Enter or Exit bookmarks presentation mode. + * Sets Or as logical operator for Advanced filter * * ```javascript - * // Enter presentation mode. - * bookmarksManager.play(BookmarksPlayMode.Presentation) + * + * const advancedFilterBuilder = new AdvancedFilterBuilder().or(); * ``` * - * @param {BookmarksPlayMode} playMode Play mode can be either `Presentation` or `Off` - * @returns {Promise>} + * @returns {AdvancedFilterBuilder} */ - BookmarksManager.prototype.play = function (playMode) { - return __awaiter(this, void 0, void 0, function () { - var playBookmarkRequest, response_3; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (util_1.isRDLEmbed(this.config.embedUrl)) { - return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; - } - playBookmarkRequest = { - playMode: playMode - }; - _a.label = 1; - case 1: - _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, this.service.hpm.post("/report/bookmarks/play", playBookmarkRequest, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; - case 2: return [2 /*return*/, _a.sent()]; - case 3: - response_3 = _a.sent(); - throw response_3.body; - case 4: return [2 /*return*/]; - } - }); - }); + AdvancedFilterBuilder.prototype.or = function () { + this.logicalOperator = "Or"; + return this; }; /** - * Capture bookmark from current state. + * Adds a condition in Advanced filter * * ```javascript - * bookmarksManager.capture(options) + * + * // Add two conditions + * const advancedFilterBuilder = new AdvancedFilterBuilder().addCondition("Contains", "Wash").addCondition("Contains", "Park"); * ``` * - * @param {ICaptureBookmarkOptions} [options] Options for bookmark capturing - * @returns {Promise} + * @returns {AdvancedFilterBuilder} */ - BookmarksManager.prototype.capture = function (options) { - return __awaiter(this, void 0, void 0, function () { - var request, response, response_4; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (util_1.isRDLEmbed(this.config.embedUrl)) { - return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; - } - request = { - options: options || {} - }; - _a.label = 1; - case 1: - _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, this.service.hpm.post("/report/bookmarks/capture", request, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; - case 2: - response = _a.sent(); - return [2 /*return*/, response.body]; - case 3: - response_4 = _a.sent(); - throw response_4.body; - case 4: return [2 /*return*/]; - } - }); - }); + AdvancedFilterBuilder.prototype.addCondition = function (operator, value) { + var condition = { + operator: operator, + value: value + }; + this.conditions.push(condition); + return this; }; /** - * Apply bookmark state. + * Creates Advanced filter * * ```javascript - * bookmarksManager.applyState(bookmarkState) + * + * const advancedFilterBuilder = new AdvancedFilterBuilder().build(); * ``` * - * @param {string} state A base64 bookmark state to be applied - * @returns {Promise>} + * @returns {AdvancedFilter} */ - BookmarksManager.prototype.applyState = function (state) { - return __awaiter(this, void 0, void 0, function () { - var request, response_5; - return __generator(this, function (_a) { - switch (_a.label) { - case 0: - if (util_1.isRDLEmbed(this.config.embedUrl)) { - return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; - } - request = { - state: state - }; - _a.label = 1; - case 1: - _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, this.service.hpm.post("/report/bookmarks/applyState", request, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; - case 2: return [2 /*return*/, _a.sent()]; - case 3: - response_5 = _a.sent(); - throw response_5.body; - case 4: return [2 /*return*/]; - } - }); - }); + AdvancedFilterBuilder.prototype.build = function () { + var advancedFilter = new powerbi_models_1.AdvancedFilter(this.target, this.logicalOperator, this.conditions); + return advancedFilter; }; - return BookmarksManager; -}()); -exports.BookmarksManager = BookmarksManager; + return AdvancedFilterBuilder; +}(filterBuilder_1.FilterBuilder)); +exports.AdvancedFilterBuilder = AdvancedFilterBuilder; /***/ }), -/***/ "./src/config.ts": -/*!***********************!*\ - !*** ./src/config.ts ***! - \***********************/ +/***/ "./src/FilterBuilders/basicFilterBuilder.ts": +/*!**************************************************!*\ + !*** ./src/FilterBuilders/basicFilterBuilder.ts ***! + \**************************************************/ /*! no static exports found */ -/***/ (function(module, exports) { +/***/ (function(module, exports, __webpack_require__) { // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -Object.defineProperty(exports, "__esModule", { value: true }); -/** @ignore */ /** */ -var config = { - version: '2.18.1', - type: 'js' -}; -exports.default = config; - - -/***/ }), - -/***/ "./src/create.ts": -/*!***********************!*\ +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BasicFilterBuilder = void 0; +var powerbi_models_1 = __webpack_require__(/*! powerbi-models */ "./node_modules/powerbi-models/dist/models.js"); +var filterBuilder_1 = __webpack_require__(/*! ./filterBuilder */ "./src/FilterBuilders/filterBuilder.ts"); +/** + * Power BI Basic filter builder component + * + * @export + * @class BasicFilterBuilder + * @extends {FilterBuilder} + */ +var BasicFilterBuilder = /** @class */ (function (_super) { + __extends(BasicFilterBuilder, _super); + function BasicFilterBuilder() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.isRequireSingleSelection = false; + return _this; + } + /** + * Sets In as operator for Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().in([values]); + * ``` + * + * @returns {BasicFilterBuilder} + */ + BasicFilterBuilder.prototype.in = function (values) { + this.operator = "In"; + this.values = values; + return this; + }; + /** + * Sets NotIn as operator for Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().notIn([values]); + * ``` + * + * @returns {BasicFilterBuilder} + */ + BasicFilterBuilder.prototype.notIn = function (values) { + this.operator = "NotIn"; + this.values = values; + return this; + }; + /** + * Sets All as operator for Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().all(); + * ``` + * + * @returns {BasicFilterBuilder} + */ + BasicFilterBuilder.prototype.all = function () { + this.operator = "All"; + this.values = []; + return this; + }; + /** + * Sets required single selection property for Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().requireSingleSelection(isRequireSingleSelection); + * ``` + * + * @returns {BasicFilterBuilder} + */ + BasicFilterBuilder.prototype.requireSingleSelection = function (isRequireSingleSelection) { + if (isRequireSingleSelection === void 0) { isRequireSingleSelection = false; } + this.isRequireSingleSelection = isRequireSingleSelection; + return this; + }; + /** + * Creates Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().build(); + * ``` + * + * @returns {BasicFilter} + */ + BasicFilterBuilder.prototype.build = function () { + var basicFilter = new powerbi_models_1.BasicFilter(this.target, this.operator, this.values); + basicFilter.requireSingleSelection = this.isRequireSingleSelection; + return basicFilter; + }; + return BasicFilterBuilder; +}(filterBuilder_1.FilterBuilder)); +exports.BasicFilterBuilder = BasicFilterBuilder; + + +/***/ }), + +/***/ "./src/FilterBuilders/filterBuilder.ts": +/*!*********************************************!*\ + !*** ./src/FilterBuilders/filterBuilder.ts ***! + \*********************************************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +Object.defineProperty(exports, "__esModule", { value: true }); +exports.FilterBuilder = void 0; +/** + * Generic filter builder for BasicFilter, AdvancedFilter, RelativeDate, RelativeTime and TopN + * + * @class + */ +var FilterBuilder = /** @class */ (function () { + function FilterBuilder() { + } + /** + * Sets target property for filter with target object + * + * ```javascript + * const target = { + * table: 'table1', + * column: 'column1' + * }; + * + * const filterBuilder = new FilterBuilder().withTargetObject(target); + * ``` + * + * @returns {FilterBuilder} + */ + FilterBuilder.prototype.withTargetObject = function (target) { + this.target = target; + return this; + }; + /** + * Sets target property for filter with column target object + * + * ``` + * const filterBuilder = new FilterBuilder().withColumnTarget(tableName, columnName); + * ``` + * + * @returns {FilterBuilder} + */ + FilterBuilder.prototype.withColumnTarget = function (tableName, columnName) { + this.target = { table: tableName, column: columnName }; + return this; + }; + /** + * Sets target property for filter with measure target object + * + * ``` + * const filterBuilder = new FilterBuilder().withMeasureTarget(tableName, measure); + * ``` + * + * @returns {FilterBuilder} + */ + FilterBuilder.prototype.withMeasureTarget = function (tableName, measure) { + this.target = { table: tableName, measure: measure }; + return this; + }; + /** + * Sets target property for filter with hierarchy level target object + * + * ``` + * const filterBuilder = new FilterBuilder().withHierarchyLevelTarget(tableName, hierarchy, hierarchyLevel); + * ``` + * + * @returns {FilterBuilder} + */ + FilterBuilder.prototype.withHierarchyLevelTarget = function (tableName, hierarchy, hierarchyLevel) { + this.target = { table: tableName, hierarchy: hierarchy, hierarchyLevel: hierarchyLevel }; + return this; + }; + /** + * Sets target property for filter with column aggregation target object + * + * ``` + * const filterBuilder = new FilterBuilder().withColumnAggregation(tableName, columnName, aggregationFunction); + * ``` + * + * @returns {FilterBuilder} + */ + FilterBuilder.prototype.withColumnAggregation = function (tableName, columnName, aggregationFunction) { + this.target = { table: tableName, column: columnName, aggregationFunction: aggregationFunction }; + return this; + }; + /** + * Sets target property for filter with hierarchy level aggregation target object + * + * ``` + * const filterBuilder = new FilterBuilder().withHierarchyLevelAggregationTarget(tableName, hierarchy, hierarchyLevel, aggregationFunction); + * ``` + * + * @returns {FilterBuilder} + */ + FilterBuilder.prototype.withHierarchyLevelAggregationTarget = function (tableName, hierarchy, hierarchyLevel, aggregationFunction) { + this.target = { table: tableName, hierarchy: hierarchy, hierarchyLevel: hierarchyLevel, aggregationFunction: aggregationFunction }; + return this; + }; + return FilterBuilder; +}()); +exports.FilterBuilder = FilterBuilder; + + +/***/ }), + +/***/ "./src/FilterBuilders/index.ts": +/*!*************************************!*\ + !*** ./src/FilterBuilders/index.ts ***! + \*************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RelativeTimeFilterBuilder = exports.RelativeDateFilterBuilder = exports.TopNFilterBuilder = exports.AdvancedFilterBuilder = exports.BasicFilterBuilder = void 0; +var basicFilterBuilder_1 = __webpack_require__(/*! ./basicFilterBuilder */ "./src/FilterBuilders/basicFilterBuilder.ts"); +Object.defineProperty(exports, "BasicFilterBuilder", { enumerable: true, get: function () { return basicFilterBuilder_1.BasicFilterBuilder; } }); +var advancedFilterBuilder_1 = __webpack_require__(/*! ./advancedFilterBuilder */ "./src/FilterBuilders/advancedFilterBuilder.ts"); +Object.defineProperty(exports, "AdvancedFilterBuilder", { enumerable: true, get: function () { return advancedFilterBuilder_1.AdvancedFilterBuilder; } }); +var topNFilterBuilder_1 = __webpack_require__(/*! ./topNFilterBuilder */ "./src/FilterBuilders/topNFilterBuilder.ts"); +Object.defineProperty(exports, "TopNFilterBuilder", { enumerable: true, get: function () { return topNFilterBuilder_1.TopNFilterBuilder; } }); +var relativeDateFilterBuilder_1 = __webpack_require__(/*! ./relativeDateFilterBuilder */ "./src/FilterBuilders/relativeDateFilterBuilder.ts"); +Object.defineProperty(exports, "RelativeDateFilterBuilder", { enumerable: true, get: function () { return relativeDateFilterBuilder_1.RelativeDateFilterBuilder; } }); +var relativeTimeFilterBuilder_1 = __webpack_require__(/*! ./relativeTimeFilterBuilder */ "./src/FilterBuilders/relativeTimeFilterBuilder.ts"); +Object.defineProperty(exports, "RelativeTimeFilterBuilder", { enumerable: true, get: function () { return relativeTimeFilterBuilder_1.RelativeTimeFilterBuilder; } }); + + +/***/ }), + +/***/ "./src/FilterBuilders/relativeDateFilterBuilder.ts": +/*!*********************************************************!*\ + !*** ./src/FilterBuilders/relativeDateFilterBuilder.ts ***! + \*********************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RelativeDateFilterBuilder = void 0; +var powerbi_models_1 = __webpack_require__(/*! powerbi-models */ "./node_modules/powerbi-models/dist/models.js"); +var filterBuilder_1 = __webpack_require__(/*! ./filterBuilder */ "./src/FilterBuilders/filterBuilder.ts"); +/** + * Power BI Relative Date filter builder component + * + * @export + * @class RelativeDateFilterBuilder + * @extends {FilterBuilder} + */ +var RelativeDateFilterBuilder = /** @class */ (function (_super) { + __extends(RelativeDateFilterBuilder, _super); + function RelativeDateFilterBuilder() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.isTodayIncluded = true; + return _this; + } + /** + * Sets inLast as operator for Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().inLast(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeDateFilterBuilder} + */ + RelativeDateFilterBuilder.prototype.inLast = function (timeUnitsCount, timeUnitType) { + this.operator = powerbi_models_1.RelativeDateOperators.InLast; + this.timeUnitsCount = timeUnitsCount; + this.timeUnitType = timeUnitType; + return this; + }; + /** + * Sets inThis as operator for Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().inThis(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeDateFilterBuilder} + */ + RelativeDateFilterBuilder.prototype.inThis = function (timeUnitsCount, timeUnitType) { + this.operator = powerbi_models_1.RelativeDateOperators.InThis; + this.timeUnitsCount = timeUnitsCount; + this.timeUnitType = timeUnitType; + return this; + }; + /** + * Sets inNext as operator for Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().inNext(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeDateFilterBuilder} + */ + RelativeDateFilterBuilder.prototype.inNext = function (timeUnitsCount, timeUnitType) { + this.operator = powerbi_models_1.RelativeDateOperators.InNext; + this.timeUnitsCount = timeUnitsCount; + this.timeUnitType = timeUnitType; + return this; + }; + /** + * Sets includeToday for Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().includeToday(includeToday); + * ``` + * + * @param {boolean} includeToday - Denotes if today is included or not + * @returns {RelativeDateFilterBuilder} + */ + RelativeDateFilterBuilder.prototype.includeToday = function (includeToday) { + this.isTodayIncluded = includeToday; + return this; + }; + /** + * Creates Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().build(); + * ``` + * + * @returns {RelativeDateFilter} + */ + RelativeDateFilterBuilder.prototype.build = function () { + var relativeDateFilter = new powerbi_models_1.RelativeDateFilter(this.target, this.operator, this.timeUnitsCount, this.timeUnitType, this.isTodayIncluded); + return relativeDateFilter; + }; + return RelativeDateFilterBuilder; +}(filterBuilder_1.FilterBuilder)); +exports.RelativeDateFilterBuilder = RelativeDateFilterBuilder; + + +/***/ }), + +/***/ "./src/FilterBuilders/relativeTimeFilterBuilder.ts": +/*!*********************************************************!*\ + !*** ./src/FilterBuilders/relativeTimeFilterBuilder.ts ***! + \*********************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RelativeTimeFilterBuilder = void 0; +var powerbi_models_1 = __webpack_require__(/*! powerbi-models */ "./node_modules/powerbi-models/dist/models.js"); +var filterBuilder_1 = __webpack_require__(/*! ./filterBuilder */ "./src/FilterBuilders/filterBuilder.ts"); +/** + * Power BI Relative Time filter builder component + * + * @export + * @class RelativeTimeFilterBuilder + * @extends {FilterBuilder} + */ +var RelativeTimeFilterBuilder = /** @class */ (function (_super) { + __extends(RelativeTimeFilterBuilder, _super); + function RelativeTimeFilterBuilder() { + return _super !== null && _super.apply(this, arguments) || this; + } + /** + * Sets inLast as operator for Relative Time filter + * + * ```javascript + * + * const relativeTimeFilterBuilder = new RelativeTimeFilterBuilder().inLast(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeTimeFilterBuilder} + */ + RelativeTimeFilterBuilder.prototype.inLast = function (timeUnitsCount, timeUnitType) { + this.operator = powerbi_models_1.RelativeDateOperators.InLast; + this.timeUnitsCount = timeUnitsCount; + this.timeUnitType = timeUnitType; + return this; + }; + /** + * Sets inThis as operator for Relative Time filter + * + * ```javascript + * + * const relativeTimeFilterBuilder = new RelativeTimeFilterBuilder().inThis(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeTimeFilterBuilder} + */ + RelativeTimeFilterBuilder.prototype.inThis = function (timeUnitsCount, timeUnitType) { + this.operator = powerbi_models_1.RelativeDateOperators.InThis; + this.timeUnitsCount = timeUnitsCount; + this.timeUnitType = timeUnitType; + return this; + }; + /** + * Sets inNext as operator for Relative Time filter + * + * ```javascript + * + * const relativeTimeFilterBuilder = new RelativeTimeFilterBuilder().inNext(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeTimeFilterBuilder} + */ + RelativeTimeFilterBuilder.prototype.inNext = function (timeUnitsCount, timeUnitType) { + this.operator = powerbi_models_1.RelativeDateOperators.InNext; + this.timeUnitsCount = timeUnitsCount; + this.timeUnitType = timeUnitType; + return this; + }; + /** + * Creates Relative Time filter + * + * ```javascript + * + * const relativeTimeFilterBuilder = new RelativeTimeFilterBuilder().build(); + * ``` + * + * @returns {RelativeTimeFilter} + */ + RelativeTimeFilterBuilder.prototype.build = function () { + var relativeTimeFilter = new powerbi_models_1.RelativeTimeFilter(this.target, this.operator, this.timeUnitsCount, this.timeUnitType); + return relativeTimeFilter; + }; + return RelativeTimeFilterBuilder; +}(filterBuilder_1.FilterBuilder)); +exports.RelativeTimeFilterBuilder = RelativeTimeFilterBuilder; + + +/***/ }), + +/***/ "./src/FilterBuilders/topNFilterBuilder.ts": +/*!*************************************************!*\ + !*** ./src/FilterBuilders/topNFilterBuilder.ts ***! + \*************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TopNFilterBuilder = void 0; +var powerbi_models_1 = __webpack_require__(/*! powerbi-models */ "./node_modules/powerbi-models/dist/models.js"); +var filterBuilder_1 = __webpack_require__(/*! ./filterBuilder */ "./src/FilterBuilders/filterBuilder.ts"); +/** + * Power BI Top N filter builder component + * + * @export + * @class TopNFilterBuilder + * @extends {FilterBuilder} + */ +var TopNFilterBuilder = /** @class */ (function (_super) { + __extends(TopNFilterBuilder, _super); + function TopNFilterBuilder() { + return _super !== null && _super.apply(this, arguments) || this; + } + /** + * Sets Top as operator for Top N filter + * + * ```javascript + * + * const topNFilterBuilder = new TopNFilterBuilder().top(itemCount); + * ``` + * + * @returns {TopNFilterBuilder} + */ + TopNFilterBuilder.prototype.top = function (itemCount) { + this.operator = "Top"; + this.itemCount = itemCount; + return this; + }; + /** + * Sets Bottom as operator for Top N filter + * + * ```javascript + * + * const topNFilterBuilder = new TopNFilterBuilder().bottom(itemCount); + * ``` + * + * @returns {TopNFilterBuilder} + */ + TopNFilterBuilder.prototype.bottom = function (itemCount) { + this.operator = "Bottom"; + this.itemCount = itemCount; + return this; + }; + /** + * Sets order by for Top N filter + * + * ```javascript + * + * const topNFilterBuilder = new TopNFilterBuilder().orderByTarget(target); + * ``` + * + * @returns {TopNFilterBuilder} + */ + TopNFilterBuilder.prototype.orderByTarget = function (target) { + this.orderByTargetValue = target; + return this; + }; + /** + * Creates Top N filter + * + * ```javascript + * + * const topNFilterBuilder = new TopNFilterBuilder().build(); + * ``` + * + * @returns {TopNFilter} + */ + TopNFilterBuilder.prototype.build = function () { + var topNFilter = new powerbi_models_1.TopNFilter(this.target, this.operator, this.itemCount, this.orderByTargetValue); + return topNFilter; + }; + return TopNFilterBuilder; +}(filterBuilder_1.FilterBuilder)); +exports.TopNFilterBuilder = TopNFilterBuilder; + + +/***/ }), + +/***/ "./src/bookmarksManager.ts": +/*!*********************************!*\ + !*** ./src/bookmarksManager.ts ***! + \*********************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BookmarksManager = void 0; +var util_1 = __webpack_require__(/*! ./util */ "./src/util.ts"); +var errors_1 = __webpack_require__(/*! ./errors */ "./src/errors.ts"); +/** + * Manages report bookmarks. + * + * @export + * @class BookmarksManager + * @implements {IBookmarksManager} + */ +var BookmarksManager = /** @class */ (function () { + /** + * @hidden + */ + function BookmarksManager(service, config, iframe) { + this.service = service; + this.config = config; + this.iframe = iframe; + } + /** + * Gets bookmarks that are defined in the report. + * + * ```javascript + * // Gets bookmarks that are defined in the report + * bookmarksManager.getBookmarks() + * .then(bookmarks => { + * ... + * }); + * ``` + * + * @returns {Promise} + */ + BookmarksManager.prototype.getBookmarks = function () { + return __awaiter(this, void 0, void 0, function () { + var response, response_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (util_1.isRDLEmbed(this.config.embedUrl)) { + return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; + } + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.service.hpm.get("/report/bookmarks", { uid: this.config.uniqueId }, this.iframe.contentWindow)]; + case 2: + response = _a.sent(); + return [2 /*return*/, response.body]; + case 3: + response_1 = _a.sent(); + throw response_1.body; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Apply bookmark by name. + * + * ```javascript + * bookmarksManager.apply(bookmarkName) + * ``` + * + * @param {string} bookmarkName The name of the bookmark to be applied + * @returns {Promise>} + */ + BookmarksManager.prototype.apply = function (bookmarkName) { + return __awaiter(this, void 0, void 0, function () { + var request, response_2; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (util_1.isRDLEmbed(this.config.embedUrl)) { + return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; + } + request = { + name: bookmarkName + }; + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.service.hpm.post("/report/bookmarks/applyByName", request, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; + case 2: return [2 /*return*/, _a.sent()]; + case 3: + response_2 = _a.sent(); + throw response_2.body; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Play bookmarks: Enter or Exit bookmarks presentation mode. + * + * ```javascript + * // Enter presentation mode. + * bookmarksManager.play(BookmarksPlayMode.Presentation) + * ``` + * + * @param {BookmarksPlayMode} playMode Play mode can be either `Presentation` or `Off` + * @returns {Promise>} + */ + BookmarksManager.prototype.play = function (playMode) { + return __awaiter(this, void 0, void 0, function () { + var playBookmarkRequest, response_3; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (util_1.isRDLEmbed(this.config.embedUrl)) { + return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; + } + playBookmarkRequest = { + playMode: playMode + }; + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.service.hpm.post("/report/bookmarks/play", playBookmarkRequest, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; + case 2: return [2 /*return*/, _a.sent()]; + case 3: + response_3 = _a.sent(); + throw response_3.body; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Capture bookmark from current state. + * + * ```javascript + * bookmarksManager.capture(options) + * ``` + * + * @param {ICaptureBookmarkOptions} [options] Options for bookmark capturing + * @returns {Promise} + */ + BookmarksManager.prototype.capture = function (options) { + return __awaiter(this, void 0, void 0, function () { + var request, response, response_4; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (util_1.isRDLEmbed(this.config.embedUrl)) { + return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; + } + request = { + options: options || {} + }; + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.service.hpm.post("/report/bookmarks/capture", request, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; + case 2: + response = _a.sent(); + return [2 /*return*/, response.body]; + case 3: + response_4 = _a.sent(); + throw response_4.body; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Apply bookmark state. + * + * ```javascript + * bookmarksManager.applyState(bookmarkState) + * ``` + * + * @param {string} state A base64 bookmark state to be applied + * @returns {Promise>} + */ + BookmarksManager.prototype.applyState = function (state) { + return __awaiter(this, void 0, void 0, function () { + var request, response_5; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (util_1.isRDLEmbed(this.config.embedUrl)) { + return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; + } + request = { + state: state + }; + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.service.hpm.post("/report/bookmarks/applyState", request, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; + case 2: return [2 /*return*/, _a.sent()]; + case 3: + response_5 = _a.sent(); + throw response_5.body; + case 4: return [2 /*return*/]; + } + }); + }); + }; + return BookmarksManager; +}()); +exports.BookmarksManager = BookmarksManager; + + +/***/ }), + +/***/ "./src/config.ts": +/*!***********************!*\ + !*** ./src/config.ts ***! + \***********************/ +/*! no static exports found */ +/***/ (function(module, exports) { + +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +Object.defineProperty(exports, "__esModule", { value: true }); +/** @ignore */ /** */ +var config = { + version: '2.18.4', + type: 'js' +}; +exports.default = config; + + +/***/ }), + +/***/ "./src/create.ts": +/*!***********************!*\ !*** ./src/create.ts ***! \***********************/ /*! no static exports found */ @@ -6755,9 +7495,9 @@ var __generator = (this && this.__generator) || function (thisArg, body) { Object.defineProperty(exports, "__esModule", { value: true }); exports.Embed = void 0; var models = __webpack_require__(/*! powerbi-models */ "./node_modules/powerbi-models/dist/models.js"); -var util_1 = __webpack_require__(/*! ./util */ "./src/util.ts"); var sdkConfig = __webpack_require__(/*! ./config */ "./src/config.ts"); var errors_1 = __webpack_require__(/*! ./errors */ "./src/errors.ts"); +var util_1 = __webpack_require__(/*! ./util */ "./src/util.ts"); /** * Base class for all Power BI embed components * @@ -6779,6 +7519,7 @@ var Embed = /** @class */ (function () { * @hidden */ function Embed(service, element, config, iframe, phasedRender, isBootstrap) { + var _a; /** @hidden */ this.allowedEvents = []; if (util_1.autoAuthInEmbedUrl(config.embedUrl)) { @@ -6791,12 +7532,16 @@ var Embed = /** @class */ (function () { this.iframe = iframe; this.iframeLoaded = false; this.embedtype = config.type.toLowerCase(); + this.commands = []; + this.groups = []; + var registerQueryCallback = !!((_a = config.eventHooks) === null || _a === void 0 ? void 0 : _a.applicationContextProvider); + delete config.eventHooks; this.populateConfig(config, isBootstrap); if (this.embedtype === 'create') { - this.setIframe(false /* set EventListener to call create() on 'load' event*/, phasedRender, isBootstrap); + this.setIframe(false /* set EventListener to call create() on 'load' event*/, phasedRender, isBootstrap, registerQueryCallback); } else { - this.setIframe(true /* set EventListener to call load() on 'load' event*/, phasedRender, isBootstrap); + this.setIframe(true /* set EventListener to call load() on 'load' event*/, phasedRender, isBootstrap, registerQueryCallback); } } /** @@ -7121,6 +7866,8 @@ var Embed = /** @class */ (function () { * @returns {void} */ Embed.prototype.populateConfig = function (config, isBootstrap) { + var _this = this; + var _a, _b, _c, _d, _e, _f, _g, _h, _j; if (this.bootstrapConfig) { this.config = util_1.assign({}, this.bootstrapConfig, config); // reset bootstrapConfig because we do not want to merge it in re-embed scenario. @@ -7135,6 +7882,18 @@ var Embed = /** @class */ (function () { this.config.groupId = this.getGroupId(); this.addLocaleToEmbedUrl(config); this.config.uniqueId = this.getUniqueId(); + var extensions = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.settings) === null || _b === void 0 ? void 0 : _b.extensions; + this.commands = (_c = extensions === null || extensions === void 0 ? void 0 : extensions.commands) !== null && _c !== void 0 ? _c : []; + this.groups = (_d = extensions === null || extensions === void 0 ? void 0 : extensions.groups) !== null && _d !== void 0 ? _d : []; + this.initialLayoutType = (_g = (_f = (_e = this.config) === null || _e === void 0 ? void 0 : _e.settings) === null || _f === void 0 ? void 0 : _f.layoutType) !== null && _g !== void 0 ? _g : models.LayoutType.Master; + // Adding commands in extensions array to this.commands + var extensionsArray = (_j = (_h = this.config) === null || _h === void 0 ? void 0 : _h.settings) === null || _j === void 0 ? void 0 : _j.extensions; + if (Array.isArray(extensionsArray)) { + this.commands = []; + extensionsArray.map(function (extension) { if (extension === null || extension === void 0 ? void 0 : extension.command) { + _this.commands.push(extension.command); + } }); + } if (isBootstrap) { // save current config in bootstrapConfig to be able to merge it on next call to powerbi.embed this.bootstrapConfig = this.config; @@ -7256,11 +8015,13 @@ var Embed = /** @class */ (function () { * * @hidden */ - Embed.prototype.setIframe = function (isLoad, phasedRender, isBootstrap) { + Embed.prototype.setIframe = function (isLoad, phasedRender, isBootstrap, registerQueryCallback) { var _this = this; if (!this.iframe) { var iframeContent = document.createElement("iframe"); var embedUrl = this.config.uniqueId ? util_1.addParamToUrl(this.config.embedUrl, 'uid', this.config.uniqueId) : this.config.embedUrl; + if (!isBootstrap && registerQueryCallback) + embedUrl = util_1.addParamToUrl(embedUrl, "registerQueryCallback", "true"); iframeContent.style.width = '100%'; iframeContent.style.height = '100%'; iframeContent.setAttribute("src", embedUrl); @@ -7541,13 +8302,14 @@ var Page = /** @class */ (function () { * @param {SectionVisibility} [visibility] * @hidden */ - function Page(report, name, displayName, isActivePage, visibility, defaultSize, defaultDisplayOption) { + function Page(report, name, displayName, isActivePage, visibility, defaultSize, defaultDisplayOption, mobileSize) { this.report = report; this.name = name; this.displayName = displayName; this.isActive = isActivePage; this.visibility = visibility; this.defaultSize = defaultSize; + this.mobileSize = mobileSize; this.defaultDisplayOption = defaultDisplayOption; } /** @@ -7790,6 +8552,180 @@ var Page = /** @class */ (function () { }); }); }; + /** + * Gets a visual by name on the page. + * + * ```javascript + * page.getVisualByName(visualName: string) + * .then(visual => { + * ... + * }); + * ``` + * + * @param {string} visualName + * @returns {Promise} + */ + Page.prototype.getVisualByName = function (visualName) { + return __awaiter(this, void 0, void 0, function () { + var response, visual, response_8; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (util_1.isRDLEmbed(this.report.config.embedUrl)) { + return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; + } + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.report.service.hpm.get("/report/pages/" + this.name + "/visuals", { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow)]; + case 2: + response = _a.sent(); + visual = response.body.find(function (v) { return v.name === visualName; }); + if (!visual) { + return [2 /*return*/, Promise.reject(powerbi_models_1.CommonErrorCodes.NotFound)]; + } + return [2 /*return*/, new visualDescriptor_1.VisualDescriptor(this, visual.name, visual.title, visual.type, visual.layout)]; + case 3: + response_8 = _a.sent(); + throw response_8.body; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Updates the display state of a visual in a page. + * + * ```javascript + * page.setVisualDisplayState(visualName, displayState) + * .catch(error => { ... }); + * ``` + * + * @param {string} visualName + * @param {VisualContainerDisplayMode} displayState + * @returns {Promise>} + */ + Page.prototype.setVisualDisplayState = function (visualName, displayState) { + return __awaiter(this, void 0, void 0, function () { + var pageName, report; + return __generator(this, function (_a) { + pageName = this.name; + report = this.report; + return [2 /*return*/, report.setVisualDisplayState(pageName, visualName, displayState)]; + }); + }); + }; + /** + * Updates the position of a visual in a page. + * + * ```javascript + * page.moveVisual(visualName, x, y, z) + * .catch(error => { ... }); + * ``` + * + * @param {string} visualName + * @param {number} x + * @param {number} y + * @param {number} z + * @returns {Promise>} + */ + Page.prototype.moveVisual = function (visualName, x, y, z) { + return __awaiter(this, void 0, void 0, function () { + var pageName, report; + return __generator(this, function (_a) { + pageName = this.name; + report = this.report; + return [2 /*return*/, report.moveVisual(pageName, visualName, x, y, z)]; + }); + }); + }; + /** + * Resize a visual in a page. + * + * ```javascript + * page.resizeVisual(visualName, width, height) + * .catch(error => { ... }); + * ``` + * + * @param {string} visualName + * @param {number} width + * @param {number} height + * @returns {Promise>} + */ + Page.prototype.resizeVisual = function (visualName, width, height) { + return __awaiter(this, void 0, void 0, function () { + var pageName, report; + return __generator(this, function (_a) { + pageName = this.name; + report = this.report; + return [2 /*return*/, report.resizeVisual(pageName, visualName, width, height)]; + }); + }); + }; + /** + * Updates the size of active page. + * + * ```javascript + * page.resizePage(pageSizeType, width, height) + * .catch(error => { ... }); + * ``` + * + * @param {PageSizeType} pageSizeType + * @param {number} width + * @param {number} height + * @returns {Promise>} + */ + Page.prototype.resizePage = function (pageSizeType, width, height) { + return __awaiter(this, void 0, void 0, function () { + var report; + return __generator(this, function (_a) { + if (!this.isActive) { + return [2 /*return*/, Promise.reject('Cannot resize the page. Only the active page can be resized')]; + } + report = this.report; + return [2 /*return*/, report.resizeActivePage(pageSizeType, width, height)]; + }); + }); + }; + /** + * Gets the list of slicer visuals on the page. + * + * ```javascript + * page.getSlicers() + * .then(slicers => { + * ... + * }); + * ``` + * + * @returns {Promise} + */ + Page.prototype.getSlicers = function () { + return __awaiter(this, void 0, void 0, function () { + var response, response_9; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (util_1.isRDLEmbed(this.report.config.embedUrl)) { + return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; + } + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.report.service.hpm.get("/report/pages/" + this.name + "/visuals", { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow)]; + case 2: + response = _a.sent(); + return [2 /*return*/, response.body + .filter(function (visual) { return visual.type === 'slicer'; }) + .map(function (visual) { return new visualDescriptor_1.VisualDescriptor(_this, visual.name, visual.title, visual.type, visual.layout); })]; + case 3: + response_9 = _a.sent(); + throw response_9.body; + case 4: return [2 /*return*/]; + } + }); + }); + }; /** * Checks if page has layout. * @@ -7802,7 +8738,7 @@ var Page = /** @class */ (function () { */ Page.prototype.hasLayout = function (layoutType) { return __awaiter(this, void 0, void 0, function () { - var layoutTypeEnum, response, response_8; + var layoutTypeEnum, response, response_10; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -7818,8 +8754,8 @@ var Page = /** @class */ (function () { response = _a.sent(); return [2 /*return*/, response.body]; case 3: - response_8 = _a.sent(); - throw response_8.body; + response_10 = _a.sent(); + throw response_10.body; case 4: return [2 /*return*/]; } }); @@ -7842,7 +8778,7 @@ exports.Page = Page; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. Object.defineProperty(exports, "__esModule", { value: true }); -exports.VisualDescriptor = exports.Visual = exports.Qna = exports.Page = exports.Embed = exports.Tile = exports.Dashboard = exports.Report = exports.models = exports.factories = exports.service = void 0; +exports.RelativeTimeFilterBuilder = exports.RelativeDateFilterBuilder = exports.TopNFilterBuilder = exports.AdvancedFilterBuilder = exports.BasicFilterBuilder = exports.VisualDescriptor = exports.Visual = exports.Qna = exports.Page = exports.Embed = exports.Tile = exports.Dashboard = exports.Report = exports.models = exports.factories = exports.service = void 0; /** * @hidden */ @@ -7868,6 +8804,12 @@ var visual_1 = __webpack_require__(/*! ./visual */ "./src/visual.ts"); Object.defineProperty(exports, "Visual", { enumerable: true, get: function () { return visual_1.Visual; } }); var visualDescriptor_1 = __webpack_require__(/*! ./visualDescriptor */ "./src/visualDescriptor.ts"); Object.defineProperty(exports, "VisualDescriptor", { enumerable: true, get: function () { return visualDescriptor_1.VisualDescriptor; } }); +var FilterBuilders_1 = __webpack_require__(/*! ./FilterBuilders */ "./src/FilterBuilders/index.ts"); +Object.defineProperty(exports, "BasicFilterBuilder", { enumerable: true, get: function () { return FilterBuilders_1.BasicFilterBuilder; } }); +Object.defineProperty(exports, "AdvancedFilterBuilder", { enumerable: true, get: function () { return FilterBuilders_1.AdvancedFilterBuilder; } }); +Object.defineProperty(exports, "TopNFilterBuilder", { enumerable: true, get: function () { return FilterBuilders_1.TopNFilterBuilder; } }); +Object.defineProperty(exports, "RelativeDateFilterBuilder", { enumerable: true, get: function () { return FilterBuilders_1.RelativeDateFilterBuilder; } }); +Object.defineProperty(exports, "RelativeTimeFilterBuilder", { enumerable: true, get: function () { return FilterBuilders_1.RelativeTimeFilterBuilder; } }); /** * Makes Power BI available to the global object for use in applications that don't have module loading support. * @@ -8090,6 +9032,11 @@ var __generator = (this && this.__generator) || function (thisArg, body) { if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; +var __spreadArray = (this && this.__spreadArray) || function (to, from) { + for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) + to[j] = from[i]; + return to; +}; Object.defineProperty(exports, "__esModule", { value: true }); exports.Report = void 0; var powerbi_models_1 = __webpack_require__(/*! powerbi-models */ "./node_modules/powerbi-models/dist/models.js"); @@ -8366,30 +9313,116 @@ var Report = /** @class */ (function (_super) { if (util_1.isRDLEmbed(this.config.embedUrl)) { return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; } - return [2 /*return*/, this.updateFilters(powerbi_models_1.FiltersOperations.RemoveAll)]; + return [2 /*return*/, this.updateFilters(powerbi_models_1.FiltersOperations.RemoveAll)]; + }); + }); + }; + /** + * Sets filters at the report level. + * + * ```javascript + * const filters: [ + * ... + * ]; + * + * report.setFilters(filters) + * .catch(errors => { + * ... + * }); + * ``` + * + * @param {(IFilter[])} filters + * @returns {Promise>} + */ + Report.prototype.setFilters = function (filters) { + return __awaiter(this, void 0, void 0, function () { + var response_7; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (util_1.isRDLEmbed(this.config.embedUrl)) { + return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; + } + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.service.hpm.put("/report/filters", filters, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; + case 2: return [2 /*return*/, _a.sent()]; + case 3: + response_7 = _a.sent(); + throw response_7.body; + case 4: return [2 /*return*/]; + } + }); + }); + }; + /** + * Gets the report ID from the first available location: options, attribute, embed url. + * + * @returns {string} + */ + Report.prototype.getId = function () { + var config = this.config; + var reportId = config.id || this.element.getAttribute(Report.reportIdAttribute) || Report.findIdFromEmbedUrl(config.embedUrl); + if (typeof reportId !== 'string' || reportId.length === 0) { + throw new Error("Report id is required, but it was not found. You must provide an id either as part of embed configuration or as attribute '" + Report.reportIdAttribute + "'."); + } + return reportId; + }; + /** + * Gets the list of pages within the report. + * + * ```javascript + * report.getPages() + * .then(pages => { + * ... + * }); + * ``` + * + * @returns {Promise} + */ + Report.prototype.getPages = function () { + return __awaiter(this, void 0, void 0, function () { + var response, response_8; + var _this = this; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (util_1.isRDLEmbed(this.config.embedUrl)) { + return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; + } + _a.label = 1; + case 1: + _a.trys.push([1, 3, , 4]); + return [4 /*yield*/, this.service.hpm.get('/report/pages', { uid: this.config.uniqueId }, this.iframe.contentWindow)]; + case 2: + response = _a.sent(); + return [2 /*return*/, response.body + .map(function (page) { return new page_1.Page(_this, page.name, page.displayName, page.isActive, page.visibility, page.defaultSize, page.defaultDisplayOption, page.mobileSize); })]; + case 3: + response_8 = _a.sent(); + throw response_8.body; + case 4: return [2 /*return*/]; + } }); }); }; /** - * Sets filters at the report level. + * Gets a report page by its name. * * ```javascript - * const filters: [ - * ... - * ]; - * - * report.setFilters(filters) - * .catch(errors => { - * ... + * report.getPageByName(pageName) + * .then(page => { + * ... * }); * ``` * - * @param {(IFilter[])} filters - * @returns {Promise>} + * @param {string} pageName + * @returns {Promise} */ - Report.prototype.setFilters = function (filters) { + Report.prototype.getPageByName = function (pageName) { return __awaiter(this, void 0, void 0, function () { - var response_7; + var response, page, response_9; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -8399,45 +9432,37 @@ var Report = /** @class */ (function (_super) { _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); - return [4 /*yield*/, this.service.hpm.put("/report/filters", filters, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; - case 2: return [2 /*return*/, _a.sent()]; + return [4 /*yield*/, this.service.hpm.get("/report/pages", { uid: this.config.uniqueId }, this.iframe.contentWindow)]; + case 2: + response = _a.sent(); + page = response.body.find(function (p) { return p.name === pageName; }); + if (!page) { + return [2 /*return*/, Promise.reject(powerbi_models_1.CommonErrorCodes.NotFound)]; + } + return [2 /*return*/, new page_1.Page(this, page.name, page.displayName, page.isActive, page.visibility, page.defaultSize, page.defaultDisplayOption, page.mobileSize)]; case 3: - response_7 = _a.sent(); - throw response_7.body; + response_9 = _a.sent(); + throw response_9.body; case 4: return [2 /*return*/]; } }); }); }; /** - * Gets the report ID from the first available location: options, attribute, embed url. - * - * @returns {string} - */ - Report.prototype.getId = function () { - var config = this.config; - var reportId = config.id || this.element.getAttribute(Report.reportIdAttribute) || Report.findIdFromEmbedUrl(config.embedUrl); - if (typeof reportId !== 'string' || reportId.length === 0) { - throw new Error("Report id is required, but it was not found. You must provide an id either as part of embed configuration or as attribute '" + Report.reportIdAttribute + "'."); - } - return reportId; - }; - /** - * Gets the list of pages within the report. + * Gets the active report page. * * ```javascript - * report.getPages() - * .then(pages => { + * report.getActivePage() + * .then(activePage => { * ... * }); * ``` * - * @returns {Promise} + * @returns {Promise} */ - Report.prototype.getPages = function () { + Report.prototype.getActivePage = function () { return __awaiter(this, void 0, void 0, function () { - var response, response_8; - var _this = this; + var response, activePage, response_10; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -8450,11 +9475,11 @@ var Report = /** @class */ (function (_super) { return [4 /*yield*/, this.service.hpm.get('/report/pages', { uid: this.config.uniqueId }, this.iframe.contentWindow)]; case 2: response = _a.sent(); - return [2 /*return*/, response.body - .map(function (page) { return new page_1.Page(_this, page.name, page.displayName, page.isActive, page.visibility, page.defaultSize, page.defaultDisplayOption); })]; + activePage = response.body.find(function (page) { return page.isActive; }); + return [2 /*return*/, new page_1.Page(this, activePage.name, activePage.displayName, activePage.isActive, activePage.visibility, activePage.defaultSize, activePage.defaultDisplayOption, activePage.mobileSize)]; case 3: - response_8 = _a.sent(); - throw response_8.body; + response_10 = _a.sent(); + throw response_10.body; case 4: return [2 /*return*/]; } }); @@ -8483,7 +9508,7 @@ var Report = /** @class */ (function (_super) { */ Report.prototype.print = function () { return __awaiter(this, void 0, void 0, function () { - var response, response_9; + var response, response_11; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -8498,8 +9523,8 @@ var Report = /** @class */ (function (_super) { response = _a.sent(); return [2 /*return*/, response.body]; case 3: - response_9 = _a.sent(); - throw response_9.body; + response_11 = _a.sent(); + throw response_11.body; case 4: return [2 /*return*/]; } }); @@ -8518,7 +9543,7 @@ var Report = /** @class */ (function (_super) { */ Report.prototype.setPage = function (pageName) { return __awaiter(this, void 0, void 0, function () { - var page, response_10; + var page, response_12; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -8536,8 +9561,8 @@ var Report = /** @class */ (function (_super) { return [4 /*yield*/, this.service.hpm.put('/report/pages/active', page, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; case 2: return [2 /*return*/, _a.sent()]; case 3: - response_10 = _a.sent(); - throw response_10.body; + response_12 = _a.sent(); + throw response_12.body; case 4: return [2 /*return*/]; } }); @@ -8563,22 +9588,36 @@ var Report = /** @class */ (function (_super) { * @returns {Promise>} */ Report.prototype.updateSettings = function (settings) { + var _a, _b; return __awaiter(this, void 0, void 0, function () { - var response_11; - return __generator(this, function (_a) { - switch (_a.label) { + var response, extension, extensionsArray, response_13; + var _this = this; + return __generator(this, function (_c) { + switch (_c.label) { case 0: if (util_1.isRDLEmbed(this.config.embedUrl) && settings.customLayout != null) { return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; } - _a.label = 1; + _c.label = 1; case 1: - _a.trys.push([1, 3, , 4]); + _c.trys.push([1, 3, , 4]); return [4 /*yield*/, this.service.hpm.patch('/report/settings', settings, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; - case 2: return [2 /*return*/, _a.sent()]; + case 2: + response = _c.sent(); + extension = settings === null || settings === void 0 ? void 0 : settings.extensions; + this.commands = (_a = extension === null || extension === void 0 ? void 0 : extension.commands) !== null && _a !== void 0 ? _a : this.commands; + this.groups = (_b = extension === null || extension === void 0 ? void 0 : extension.groups) !== null && _b !== void 0 ? _b : this.groups; + extensionsArray = settings === null || settings === void 0 ? void 0 : settings.extensions; + if (Array.isArray(extensionsArray)) { + this.commands = []; + extensionsArray.map(function (extensionElement) { if (extensionElement === null || extensionElement === void 0 ? void 0 : extensionElement.command) { + _this.commands.push(extensionElement.command); + } }); + } + return [2 /*return*/, response]; case 3: - response_11 = _a.sent(); - throw response_11.body; + response_13 = _c.sent(); + throw response_13.body; case 4: return [2 /*return*/]; } }); @@ -8633,7 +9672,7 @@ var Report = /** @class */ (function (_super) { */ Report.prototype.switchMode = function (viewMode) { return __awaiter(this, void 0, void 0, function () { - var newMode, url, response, response_12; + var newMode, url, response, response_14; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -8652,177 +9691,608 @@ var Report = /** @class */ (function (_super) { response = _a.sent(); return [2 /*return*/, response.body]; case 3: - response_12 = _a.sent(); - throw response_12.body; + response_14 = _a.sent(); + throw response_14.body; case 4: return [2 /*return*/]; } }); }); }; /** - * Refreshes data sources for the report. + * Refreshes data sources for the report. + * + * ```javascript + * report.refresh(); + * ``` + */ + Report.prototype.refresh = function () { + return __awaiter(this, void 0, void 0, function () { + var response, response_15; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 2, , 3]); + return [4 /*yield*/, this.service.hpm.post('/report/refresh', null, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; + case 1: + response = _a.sent(); + return [2 /*return*/, response.body]; + case 2: + response_15 = _a.sent(); + throw response_15.body; + case 3: return [2 /*return*/]; + } + }); + }); + }; + /** + * checks if the report is saved. + * + * ```javascript + * report.isSaved() + * ``` + * + * @returns {Promise} + */ + Report.prototype.isSaved = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (util_1.isRDLEmbed(this.config.embedUrl)) { + return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; + } + return [4 /*yield*/, util_1.isSavedInternal(this.service.hpm, this.config.uniqueId, this.iframe.contentWindow)]; + case 1: return [2 /*return*/, _a.sent()]; + } + }); + }); + }; + /** + * Apply a theme to the report + * + * ```javascript + * report.applyTheme(theme); + * ``` + */ + Report.prototype.applyTheme = function (theme) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (util_1.isRDLEmbed(this.config.embedUrl)) { + return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; + } + return [4 /*yield*/, this.applyThemeInternal(theme)]; + case 1: return [2 /*return*/, _a.sent()]; + } + }); + }); + }; + /** + * Reset and apply the default theme of the report + * + * ```javascript + * report.resetTheme(); + * ``` + */ + Report.prototype.resetTheme = function () { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (util_1.isRDLEmbed(this.config.embedUrl)) { + return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; + } + return [4 /*yield*/, this.applyThemeInternal({})]; + case 1: return [2 /*return*/, _a.sent()]; + } + }); + }); + }; + /** + * Reset user's filters, slicers, and other data view changes to the default state of the report + * + * ```javascript + * report.resetPersistentFilters(); + * ``` + */ + Report.prototype.resetPersistentFilters = function () { + return __awaiter(this, void 0, void 0, function () { + var response_16; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 2, , 3]); + return [4 /*yield*/, this.service.hpm.delete("/report/userState", null, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; + case 1: return [2 /*return*/, _a.sent()]; + case 2: + response_16 = _a.sent(); + throw response_16.body; + case 3: return [2 /*return*/]; + } + }); + }); + }; + /** + * Save user's filters, slicers, and other data view changes of the report + * + * ```javascript + * report.savePersistentFilters(); + * ``` + */ + Report.prototype.savePersistentFilters = function () { + return __awaiter(this, void 0, void 0, function () { + var response_17; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 2, , 3]); + return [4 /*yield*/, this.service.hpm.post("/report/userState", null, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; + case 1: return [2 /*return*/, _a.sent()]; + case 2: + response_17 = _a.sent(); + throw response_17.body; + case 3: return [2 /*return*/]; + } + }); + }); + }; + /** + * Returns if there are user's filters, slicers, or other data view changes applied on the report. + * If persistent filters is disable, returns false. + * + * ```javascript + * report.arePersistentFiltersApplied(); + * ``` + * + * @returns {Promise} + */ + Report.prototype.arePersistentFiltersApplied = function () { + return __awaiter(this, void 0, void 0, function () { + var response, response_18; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 2, , 3]); + return [4 /*yield*/, this.service.hpm.get("/report/isUserStateApplied", { uid: this.config.uniqueId }, this.iframe.contentWindow)]; + case 1: + response = _a.sent(); + return [2 /*return*/, response.body]; + case 2: + response_18 = _a.sent(); + throw response_18.body; + case 3: return [2 /*return*/]; + } + }); + }); + }; + /** + * Remove context menu extension command. + * + * ```javascript + * report.removeContextMenuCommand(commandName, contextMenuTitle) + * .catch(error => { + * ... + * }); + * ``` + * + * @param {string} commandName + * @param {string} contextMenuTitle + * @returns {Promise>} + */ + Report.prototype.removeContextMenuCommand = function (commandName, contextMenuTitle) { + return __awaiter(this, void 0, void 0, function () { + var commandCopy, indexOfCommand, newSetting; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + if (util_1.isRDLEmbed(this.config.embedUrl)) { + return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; + } + commandCopy = JSON.parse(JSON.stringify(this.commands)); + indexOfCommand = this.findCommandMenuIndex("visualContextMenu", commandCopy, commandName, contextMenuTitle); + if (indexOfCommand === -1) { + throw powerbi_models_1.CommonErrorCodes.NotFound; + } + // Delete the context menu and not the entire command, since command can have option menu as well. + delete commandCopy[indexOfCommand].extend.visualContextMenu; + newSetting = { + extensions: { + commands: commandCopy, + groups: this.groups + } + }; + return [4 /*yield*/, this.updateSettings(newSetting)]; + case 1: return [2 /*return*/, _a.sent()]; + } + }); + }); + }; + /** + * Add context menu extension command. * * ```javascript - * report.refresh(); + * report.addContextMenuCommand(commandName, commandTitle, contextMenuTitle, menuLocation, visualName, visualType, groupName) + * .catch(error => { + * ... + * }); * ``` + * + * @param {string} commandName + * @param {string} commandTitle + * @param {string} contextMenuTitle + * @param {MenuLocation} menuLocation + * @param {string} visualName + * @param {string} visualType + * @param {string} groupName + * @returns {Promise>} */ - Report.prototype.refresh = function () { + Report.prototype.addContextMenuCommand = function (commandName, commandTitle, contextMenuTitle, menuLocation, visualName, visualType, groupName) { + if (contextMenuTitle === void 0) { contextMenuTitle = commandTitle; } + if (menuLocation === void 0) { menuLocation = powerbi_models_1.MenuLocation.Bottom; } + if (visualName === void 0) { visualName = undefined; } + if (groupName === void 0) { groupName = undefined; } return __awaiter(this, void 0, void 0, function () { - var response, response_13; + var newCommands, newSetting; return __generator(this, function (_a) { switch (_a.label) { case 0: - _a.trys.push([0, 2, , 3]); - return [4 /*yield*/, this.service.hpm.post('/report/refresh', null, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; - case 1: - response = _a.sent(); - return [2 /*return*/, response.body]; - case 2: - response_13 = _a.sent(); - throw response_13.body; - case 3: return [2 /*return*/]; + if (util_1.isRDLEmbed(this.config.embedUrl)) { + return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; + } + newCommands = this.createMenuCommand("visualContextMenu", commandName, commandTitle, contextMenuTitle, menuLocation, visualName, visualType, groupName); + newSetting = { + extensions: { + commands: newCommands, + groups: this.groups + } + }; + return [4 /*yield*/, this.updateSettings(newSetting)]; + case 1: return [2 /*return*/, _a.sent()]; } }); }); }; /** - * checks if the report is saved. + * Remove options menu extension command. * * ```javascript - * report.isSaved() + * report.removeOptionsMenuCommand(commandName, optionsMenuTitle) + * .then({ + * ... + * }); * ``` * - * @returns {Promise} + * @param {string} commandName + * @param {string} optionsMenuTitle + * @returns {Promise>} */ - Report.prototype.isSaved = function () { + Report.prototype.removeOptionsMenuCommand = function (commandName, optionsMenuTitle) { return __awaiter(this, void 0, void 0, function () { + var commandCopy, indexOfCommand, newSetting; return __generator(this, function (_a) { switch (_a.label) { case 0: if (util_1.isRDLEmbed(this.config.embedUrl)) { return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; } - return [4 /*yield*/, util_1.isSavedInternal(this.service.hpm, this.config.uniqueId, this.iframe.contentWindow)]; + commandCopy = JSON.parse(JSON.stringify(this.commands)); + indexOfCommand = this.findCommandMenuIndex("visualOptionsMenu", commandCopy, commandName, optionsMenuTitle); + if (indexOfCommand === -1) { + throw powerbi_models_1.CommonErrorCodes.NotFound; + } + // Delete the context options and not the entire command, since command can have context menu as well. + delete commandCopy[indexOfCommand].extend.visualOptionsMenu; + delete commandCopy[indexOfCommand].icon; + newSetting = { + extensions: { + commands: commandCopy, + groups: this.groups + } + }; + return [4 /*yield*/, this.updateSettings(newSetting)]; case 1: return [2 /*return*/, _a.sent()]; } }); }); }; /** - * Apply a theme to the report + * Add options menu extension command. * * ```javascript - * report.applyTheme(theme); + * report.addOptionsMenuCommand(commandName, commandTitle, optionsMenuTitle, menuLocation, visualName, visualType, groupName, commandIcon) + * .catch(error => { + * ... + * }); * ``` + * + * @param {string} commandName + * @param {string} commandTitle + * @param {string} optionMenuTitle + * @param {MenuLocation} menuLocation + * @param {string} visualName + * @param {string} visualType + * @param {string} groupName + * @param {string} commandIcon + * @returns {Promise>} */ - Report.prototype.applyTheme = function (theme) { + Report.prototype.addOptionsMenuCommand = function (commandName, commandTitle, optionsMenuTitle, menuLocation, visualName, visualType, groupName, commandIcon) { + if (optionsMenuTitle === void 0) { optionsMenuTitle = commandTitle; } + if (menuLocation === void 0) { menuLocation = powerbi_models_1.MenuLocation.Bottom; } + if (visualName === void 0) { visualName = undefined; } + if (visualType === void 0) { visualType = undefined; } + if (groupName === void 0) { groupName = undefined; } + if (commandIcon === void 0) { commandIcon = undefined; } return __awaiter(this, void 0, void 0, function () { + var newCommands, newSetting; return __generator(this, function (_a) { switch (_a.label) { case 0: if (util_1.isRDLEmbed(this.config.embedUrl)) { return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; } - return [4 /*yield*/, this.applyThemeInternal(theme)]; + newCommands = this.createMenuCommand("visualOptionsMenu", commandName, commandTitle, optionsMenuTitle, menuLocation, visualName, visualType, groupName, commandIcon); + newSetting = { + extensions: { + commands: newCommands, + groups: this.groups + } + }; + return [4 /*yield*/, this.updateSettings(newSetting)]; case 1: return [2 /*return*/, _a.sent()]; } }); }); }; /** - * Reset and apply the default theme of the report + * Updates the display state of a visual in a page. * * ```javascript - * report.resetTheme(); + * report.setVisualDisplayState(pageName, visualName, displayState) + * .catch(error => { ... }); * ``` + * + * @param {string} pageName + * @param {string} visualName + * @param {VisualContainerDisplayMode} displayState + * @returns {Promise>} */ - Report.prototype.resetTheme = function () { + Report.prototype.setVisualDisplayState = function (pageName, visualName, displayState) { return __awaiter(this, void 0, void 0, function () { + var visualLayout, newSettings; return __generator(this, function (_a) { switch (_a.label) { - case 0: - if (util_1.isRDLEmbed(this.config.embedUrl)) { - return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)]; - } - return [4 /*yield*/, this.applyThemeInternal({})]; - case 1: return [2 /*return*/, _a.sent()]; + case 0: + // Check if page name and visual name are valid + return [4 /*yield*/, this.validateVisual(pageName, visualName)]; + case 1: + // Check if page name and visual name are valid + _a.sent(); + visualLayout = { + displayState: { + mode: displayState + } + }; + newSettings = this.buildLayoutSettingsObject(pageName, visualName, visualLayout); + return [2 /*return*/, this.updateSettings(newSettings)]; } }); }); }; /** - * Reset user's filters, slicers, and other data view changes to the default state of the report + * Resize a visual in a page. * * ```javascript - * report.resetPersistentFilters(); + * report.resizeVisual(pageName, visualName, width, height) + * .catch(error => { ... }); * ``` + * + * @param {string} pageName + * @param {string} visualName + * @param {number} width + * @param {number} height + * @returns {Promise>} */ - Report.prototype.resetPersistentFilters = function () { + Report.prototype.resizeVisual = function (pageName, visualName, width, height) { return __awaiter(this, void 0, void 0, function () { - var response_14; + var visualLayout, newSettings; return __generator(this, function (_a) { switch (_a.label) { - case 0: - _a.trys.push([0, 2, , 3]); - return [4 /*yield*/, this.service.hpm.delete("/report/userState", null, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; - case 1: return [2 /*return*/, _a.sent()]; - case 2: - response_14 = _a.sent(); - throw response_14.body; - case 3: return [2 /*return*/]; + case 0: + // Check if page name and visual name are valid + return [4 /*yield*/, this.validateVisual(pageName, visualName)]; + case 1: + // Check if page name and visual name are valid + _a.sent(); + visualLayout = { + width: width, + height: height, + }; + newSettings = this.buildLayoutSettingsObject(pageName, visualName, visualLayout); + return [2 /*return*/, this.updateSettings(newSettings)]; } }); }); }; /** - * Save user's filters, slicers, and other data view changes of the report + * Updates the size of active page in report. * * ```javascript - * report.savePersistentFilters(); + * report.resizeActivePage(pageSizeType, width, height) + * .catch(error => { ... }); * ``` + * + * @param {PageSizeType} pageSizeType + * @param {number} width + * @param {number} height + * @returns {Promise>} */ - Report.prototype.savePersistentFilters = function () { + Report.prototype.resizeActivePage = function (pageSizeType, width, height) { + return __awaiter(this, void 0, void 0, function () { + var pageSize, newSettings; + return __generator(this, function (_a) { + pageSize = { + type: pageSizeType, + width: width, + height: height + }; + newSettings = { + layoutType: powerbi_models_1.LayoutType.Custom, + customLayout: { + pageSize: pageSize + } + }; + return [2 /*return*/, this.updateSettings(newSettings)]; + }); + }); + }; + /** + * Updates the position of a visual in a page. + * + * ```javascript + * report.moveVisual(pageName, visualName, x, y, z) + * .catch(error => { ... }); + * ``` + * + * @param {string} pageName + * @param {string} visualName + * @param {number} x + * @param {number} y + * @param {number} z + * @returns {Promise>} + */ + Report.prototype.moveVisual = function (pageName, visualName, x, y, z) { return __awaiter(this, void 0, void 0, function () { - var response_15; + var visualLayout, newSettings; return __generator(this, function (_a) { switch (_a.label) { - case 0: - _a.trys.push([0, 2, , 3]); - return [4 /*yield*/, this.service.hpm.post("/report/userState", null, { uid: this.config.uniqueId }, this.iframe.contentWindow)]; - case 1: return [2 /*return*/, _a.sent()]; - case 2: - response_15 = _a.sent(); - throw response_15.body; - case 3: return [2 /*return*/]; + case 0: + // Check if page name and visual name are valid + return [4 /*yield*/, this.validateVisual(pageName, visualName)]; + case 1: + // Check if page name and visual name are valid + _a.sent(); + visualLayout = { + x: x, + y: y, + z: z + }; + newSettings = this.buildLayoutSettingsObject(pageName, visualName, visualLayout); + return [2 /*return*/, this.updateSettings(newSettings)]; } }); }); }; /** - * Returns if there are user's filters, slicers, or other data view changes applied on the report. - * If persistent filters is disable, returns false. + * Updates the report layout * * ```javascript - * report.arePersistentFiltersApplied(); + * report.switchLayout(layoutType); * ``` * - * @returns {Promise} + * @param {LayoutType} layoutType + * @returns {Promise>} */ - Report.prototype.arePersistentFiltersApplied = function () { + Report.prototype.switchLayout = function (layoutType) { return __awaiter(this, void 0, void 0, function () { - var response, response_16; + var isInitialMobileSettings, isPassedMobileSettings, newSetting, response; return __generator(this, function (_a) { switch (_a.label) { case 0: - _a.trys.push([0, 2, , 3]); - return [4 /*yield*/, this.service.hpm.get("/report/isUserStateApplied", { uid: this.config.uniqueId }, this.iframe.contentWindow)]; + isInitialMobileSettings = this.isMobileSettings({ layoutType: this.initialLayoutType }); + isPassedMobileSettings = this.isMobileSettings({ layoutType: layoutType }); + // Check if both passed layout and initial layout are of same type. + if (isInitialMobileSettings !== isPassedMobileSettings) { + throw "Switching between mobile and desktop layouts is not supported. Please reset the embed container and re-embed with required layout."; + } + newSetting = { + layoutType: layoutType + }; + return [4 /*yield*/, this.updateSettings(newSetting)]; case 1: response = _a.sent(); - return [2 /*return*/, response.body]; - case 2: - response_16 = _a.sent(); - throw response_16.body; - case 3: return [2 /*return*/]; + this.initialLayoutType = layoutType; + return [2 /*return*/, response]; + } + }); + }); + }; + /** + * @hidden + */ + Report.prototype.createMenuCommand = function (type, commandName, commandTitle, menuTitle, menuLocation, visualName, visualType, groupName, icon) { + var newCommandObj = { + name: commandName, + title: commandTitle, + extend: {} + }; + newCommandObj.extend[type] = { + title: menuTitle, + menuLocation: menuLocation, + }; + if (type === "visualOptionsMenu") { + newCommandObj.icon = icon; + } + if (groupName) { + var extend = newCommandObj.extend[type]; + delete extend.menuLocation; + var groupExtend = newCommandObj.extend[type]; + groupExtend.groupName = groupName; + } + if (visualName) { + newCommandObj.selector = { + $schema: "http://powerbi.com/product/schema#visualSelector", + visualName: visualName + }; + } + if (visualType) { + newCommandObj.selector = { + $schema: "http://powerbi.com/product/schema#visualTypeSelector", + visualType: visualType + }; + } + return __spreadArray(__spreadArray([], this.commands), [newCommandObj]); + }; + /** + * @hidden + */ + Report.prototype.findCommandMenuIndex = function (type, commands, commandName, menuTitle) { + var indexOfCommand = -1; + commands.some(function (activeMenuCommand, index) { + return (activeMenuCommand.name === commandName && activeMenuCommand.extend[type] && activeMenuCommand.extend[type].title === menuTitle) ? (indexOfCommand = index, true) : false; + }); + return indexOfCommand; + }; + /** + * @hidden + */ + Report.prototype.buildLayoutSettingsObject = function (pageName, visualName, visualLayout) { + // Create new settings object with custom layout type + var newSettings = { + layoutType: powerbi_models_1.LayoutType.Custom, + customLayout: { + pagesLayout: {} + } + }; + newSettings.customLayout.pagesLayout[pageName] = { + visualsLayout: {} + }; + newSettings.customLayout.pagesLayout[pageName].visualsLayout[visualName] = visualLayout; + return newSettings; + }; + /** + * @hidden + */ + Report.prototype.validateVisual = function (pageName, visualName) { + return __awaiter(this, void 0, void 0, function () { + var page; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, this.getPageByName(pageName)]; + case 1: + page = _a.sent(); + return [4 /*yield*/, page.getVisualByName(visualName)]; + case 2: return [2 /*return*/, _a.sent()]; } }); }); @@ -8832,7 +10302,7 @@ var Report = /** @class */ (function (_super) { */ Report.prototype.applyThemeInternal = function (theme) { return __awaiter(this, void 0, void 0, function () { - var response, response_17; + var response, response_19; return __generator(this, function (_a) { switch (_a.label) { case 0: @@ -8842,8 +10312,8 @@ var Report = /** @class */ (function (_super) { response = _a.sent(); return [2 /*return*/, response.body]; case 2: - response_17 = _a.sent(); - throw response_17.body; + response_19 = _a.sent(); + throw response_19.body; case 3: return [2 /*return*/]; } }); @@ -8871,7 +10341,7 @@ var Report = /** @class */ (function (_super) { return settings && (settings.layoutType === powerbi_models_1.LayoutType.MobileLandscape || settings.layoutType === powerbi_models_1.LayoutType.MobilePortrait); }; /** @hidden */ - Report.allowedEvents = ["filtersApplied", "pageChanged", "commandTriggered", "swipeStart", "swipeEnd", "bookmarkApplied", "dataHyperlinkClicked", "visualRendered", "visualClicked", "selectionChanged"]; + Report.allowedEvents = ["filtersApplied", "pageChanged", "commandTriggered", "swipeStart", "swipeEnd", "bookmarkApplied", "dataHyperlinkClicked", "visualRendered", "visualClicked", "selectionChanged", "renderingStarted"]; /** @hidden */ Report.reportIdAttribute = 'powerbi-report-id'; /** @hidden */ @@ -8898,6 +10368,42 @@ exports.Report = Report; // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; Object.defineProperty(exports, "__esModule", { value: true }); exports.Service = void 0; var embed_1 = __webpack_require__(/*! ./embed */ "./src/embed.ts"); @@ -9053,6 +10559,7 @@ var Service = /** @class */ (function () { */ Service.prototype.embed = function (element, config) { if (config === void 0) { config = {}; } + this.registerApplicationContextHook(config); return this.embedInternal(element, config); }; /** @@ -9067,6 +10574,7 @@ var Service = /** @class */ (function () { */ Service.prototype.load = function (element, config) { if (config === void 0) { config = {}; } + this.registerApplicationContextHook(config); return this.embedInternal(element, config, /* phasedRender */ true, /* isBootstrap */ false); }; /** @@ -9171,6 +10679,40 @@ var Service = /** @class */ (function () { component.load(phasedRender); return component; }; + /** + * @hidden + */ + Service.prototype.registerApplicationContextHook = function (config) { + var _this = this; + var _a; + var applicationContextProvider = (_a = config === null || config === void 0 ? void 0 : config.eventHooks) === null || _a === void 0 ? void 0 : _a.applicationContextProvider; + if (!applicationContextProvider) { + return; + } + if (typeof applicationContextProvider !== 'function') { + throw new Error("applicationContextProvider must be a function"); + } + this.router.post("preQuery", function (req, _res) { return __awaiter(_this, void 0, void 0, function () { + var result, error_1; + return __generator(this, function (_a) { + switch (_a.label) { + case 0: + _a.trys.push([0, 2, , 3]); + return [4 /*yield*/, applicationContextProvider(req.body)]; + case 1: + result = _a.sent(); + _res.send(200, result); + return [3 /*break*/, 3]; + case 2: + error_1 = _a.sent(); + _res.send(400, null); + console.error(error_1); + return [3 /*break*/, 3]; + case 3: return [2 /*return*/]; + } + }); + }); }); + }; /** * Adds an event handler for DOMContentLoaded, which searches the DOM for elements that have the 'powerbi-embed-url' attribute, * and automatically attempts to embed a powerbi component based on information from other powerbi-* attributes. @@ -9691,7 +11233,7 @@ exports.isSavedInternal = isSavedInternal; * @returns {boolean} */ function isRDLEmbed(embedUrl) { - return embedUrl.toLowerCase().indexOf("/rdlembed?") >= 0; + return embedUrl && embedUrl.toLowerCase().indexOf("/rdlembed?") >= 0; } exports.isRDLEmbed = isRDLEmbed; /** @@ -10429,6 +11971,75 @@ var VisualDescriptor = /** @class */ (function () { }); }); }; + /** + * Updates the position of a visual. + * + * ```javascript + * visual.moveVisual(x, y, z) + * .catch(error => { ... }); + * ``` + * + * @param {number} x + * @param {number} y + * @param {number} z + * @returns {Promise>} + */ + VisualDescriptor.prototype.moveVisual = function (x, y, z) { + return __awaiter(this, void 0, void 0, function () { + var pageName, visualName, report; + return __generator(this, function (_a) { + pageName = this.page.name; + visualName = this.name; + report = this.page.report; + return [2 /*return*/, report.moveVisual(pageName, visualName, x, y, z)]; + }); + }); + }; + /** + * Updates the display state of a visual. + * + * ```javascript + * visual.setVisualDisplayState(displayState) + * .catch(error => { ... }); + * ``` + * + * @param {VisualContainerDisplayMode} displayState + * @returns {Promise>} + */ + VisualDescriptor.prototype.setVisualDisplayState = function (displayState) { + return __awaiter(this, void 0, void 0, function () { + var pageName, visualName, report; + return __generator(this, function (_a) { + pageName = this.page.name; + visualName = this.name; + report = this.page.report; + return [2 /*return*/, report.setVisualDisplayState(pageName, visualName, displayState)]; + }); + }); + }; + /** + * Resize a visual. + * + * ```javascript + * visual.resizeVisual(width, height) + * .catch(error => { ... }); + * ``` + * + * @param {number} width + * @param {number} height + * @returns {Promise>} + */ + VisualDescriptor.prototype.resizeVisual = function (width, height) { + return __awaiter(this, void 0, void 0, function () { + var pageName, visualName, report; + return __generator(this, function (_a) { + pageName = this.page.name; + visualName = this.name; + report = this.page.report; + return [2 /*return*/, report.resizeVisual(pageName, visualName, width, height)]; + }); + }); + }; return VisualDescriptor; }()); exports.VisualDescriptor = VisualDescriptor; diff --git a/dist/powerbi.min.js b/dist/powerbi.min.js index edb0d67e..34c6fbb2 100644 --- a/dist/powerbi.min.js +++ b/dist/powerbi.min.js @@ -1,10 +1,10 @@ -// powerbi-client v2.18.1 +// powerbi-client v2.18.4 // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports["powerbi-client"]=e():t["powerbi-client"]=e()}(this,(function(){return function(t){var e={};function r(a){if(e[a])return e[a].exports;var i=e[a]={i:a,l:!1,exports:{}};return t[a].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=t,r.c=e,r.d=function(t,e,a){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:a})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var a=Object.create(null);if(r.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)r.d(a,i,function(e){return t[e]}.bind(null,i));return a},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=12)}([function(t,e,r){var a;a=function(){return function(t){var e={};function r(a){if(e[a])return e[a].exports;var i=e[a]={i:a,l:!1,exports:{}};return t[a].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=t,r.c=e,r.d=function(t,e,a){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:a})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var a=Object.create(null);if(r.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)r.d(a,i,function(e){return t[e]}.bind(null,i));return a},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=0)}([function(t,e,r){var a,i=this&&this.__extends||(a=function(t,e){return(a=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])})(t,e)},function(t,e){function r(){this.constructor=t}a(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)});Object.defineProperty(e,"__esModule",{value:!0}),e.validateCustomTheme=e.validateCommandsSettings=e.validateVisualSettings=e.validateVisualHeader=e.validateExportDataRequest=e.validateQnaInterpretInputData=e.validateLoadQnaConfiguration=e.validateSaveAsParameters=e.validateUpdateFiltersRequest=e.validateFilter=e.validatePage=e.validateTileLoad=e.validateDashboardLoad=e.validateCreateReport=e.validatePaginatedReportLoad=e.validateReportLoad=e.validateMenuGroupExtension=e.validateExtension=e.validateCustomPageSize=e.validateVisualizationsPane=e.validateSyncSlicersPane=e.validateSelectionPane=e.validatePageNavigationPane=e.validateFieldsPane=e.validateFiltersPane=e.validateBookmarksPane=e.validatePanes=e.validateSettings=e.validateCaptureBookmarkRequest=e.validateApplyBookmarkStateRequest=e.validateApplyBookmarkByNameRequest=e.validateAddBookmarkRequest=e.validatePlayBookmarkRequest=e.validateSlicerState=e.validateSlicer=e.validateVisualSelector=e.isIExtensionArray=e.isIExtensions=e.isGroupedMenuExtension=e.isFlatMenuExtension=e.isReportFiltersArray=e.isOnLoadFilters=e.VisualDataRoleKindPreference=e.VisualDataRoleKind=e.CommandDisplayOption=e.SlicerTargetSelector=e.VisualTypeSelector=e.VisualSelector=e.PageSelector=e.Selector=e.SortDirection=e.LegendPosition=e.TextAlignment=e.CommonErrorCodes=e.BookmarksPlayMode=e.ExportDataType=e.QnaMode=e.PageNavigationPosition=e.isColumnAggr=e.isHierarchyLevelAggr=e.isHierarchyLevel=e.isColumn=e.isMeasure=e.getFilterType=e.isBasicFilterWithKeys=e.isFilterKeyColumnsTarget=e.AdvancedFilter=e.TupleFilter=e.BasicFilterWithKeys=e.BasicFilter=e.RelativeTimeFilter=e.RelativeDateFilter=e.TopNFilter=e.IncludeExcludeFilter=e.NotSupportedFilter=e.Filter=e.RelativeDateOperators=e.RelativeDateFilterTimeUnit=e.FilterType=e.FiltersLevel=e.FiltersOperations=e.MenuLocation=e.ContrastMode=e.TokenType=e.ViewMode=e.Permissions=e.SectionVisibility=e.HyperlinkClickBehavior=e.LayoutType=e.VisualContainerDisplayMode=e.BackgroundType=e.DisplayOption=e.PageSizeType=e.TraceType=void 0;var o,n=r(1);!function(t){t[t.Information=0]="Information",t[t.Verbose=1]="Verbose",t[t.Warning=2]="Warning",t[t.Error=3]="Error",t[t.ExpectedError=4]="ExpectedError",t[t.UnexpectedError=5]="UnexpectedError",t[t.Fatal=6]="Fatal"}(e.TraceType||(e.TraceType={})),function(t){t[t.Widescreen=0]="Widescreen",t[t.Standard=1]="Standard",t[t.Cortana=2]="Cortana",t[t.Letter=3]="Letter",t[t.Custom=4]="Custom"}(e.PageSizeType||(e.PageSizeType={})),function(t){t[t.FitToPage=0]="FitToPage",t[t.FitToWidth=1]="FitToWidth",t[t.ActualSize=2]="ActualSize"}(e.DisplayOption||(e.DisplayOption={})),function(t){t[t.Default=0]="Default",t[t.Transparent=1]="Transparent"}(e.BackgroundType||(e.BackgroundType={})),function(t){t[t.Visible=0]="Visible",t[t.Hidden=1]="Hidden"}(e.VisualContainerDisplayMode||(e.VisualContainerDisplayMode={})),function(t){t[t.Master=0]="Master",t[t.Custom=1]="Custom",t[t.MobilePortrait=2]="MobilePortrait",t[t.MobileLandscape=3]="MobileLandscape"}(e.LayoutType||(e.LayoutType={})),function(t){t[t.Navigate=0]="Navigate",t[t.NavigateAndRaiseEvent=1]="NavigateAndRaiseEvent",t[t.RaiseEvent=2]="RaiseEvent"}(e.HyperlinkClickBehavior||(e.HyperlinkClickBehavior={})),function(t){t[t.AlwaysVisible=0]="AlwaysVisible",t[t.HiddenInViewMode=1]="HiddenInViewMode"}(e.SectionVisibility||(e.SectionVisibility={})),function(t){t[t.Read=0]="Read",t[t.ReadWrite=1]="ReadWrite",t[t.Copy=2]="Copy",t[t.Create=4]="Create",t[t.All=7]="All"}(e.Permissions||(e.Permissions={})),function(t){t[t.View=0]="View",t[t.Edit=1]="Edit"}(e.ViewMode||(e.ViewMode={})),function(t){t[t.Aad=0]="Aad",t[t.Embed=1]="Embed"}(e.TokenType||(e.TokenType={})),function(t){t[t.None=0]="None",t[t.HighContrast1=1]="HighContrast1",t[t.HighContrast2=2]="HighContrast2",t[t.HighContrastBlack=3]="HighContrastBlack",t[t.HighContrastWhite=4]="HighContrastWhite"}(e.ContrastMode||(e.ContrastMode={})),function(t){t[t.Bottom=0]="Bottom",t[t.Top=1]="Top"}(e.MenuLocation||(e.MenuLocation={})),function(t){t[t.RemoveAll=0]="RemoveAll",t[t.ReplaceAll=1]="ReplaceAll",t[t.Add=2]="Add",t[t.Replace=3]="Replace"}(e.FiltersOperations||(e.FiltersOperations={})),function(t){t[t.Report=0]="Report",t[t.Page=1]="Page",t[t.Visual=2]="Visual"}(e.FiltersLevel||(e.FiltersLevel={})),function(t){t[t.Advanced=0]="Advanced",t[t.Basic=1]="Basic",t[t.Unknown=2]="Unknown",t[t.IncludeExclude=3]="IncludeExclude",t[t.RelativeDate=4]="RelativeDate",t[t.TopN=5]="TopN",t[t.Tuple=6]="Tuple",t[t.RelativeTime=7]="RelativeTime"}(o=e.FilterType||(e.FilterType={})),function(t){t[t.Days=0]="Days",t[t.Weeks=1]="Weeks",t[t.CalendarWeeks=2]="CalendarWeeks",t[t.Months=3]="Months",t[t.CalendarMonths=4]="CalendarMonths",t[t.Years=5]="Years",t[t.CalendarYears=6]="CalendarYears",t[t.Minutes=7]="Minutes",t[t.Hours=8]="Hours"}(e.RelativeDateFilterTimeUnit||(e.RelativeDateFilterTimeUnit={})),function(t){t[t.InLast=0]="InLast",t[t.InThis=1]="InThis",t[t.InNext=2]="InNext"}(e.RelativeDateOperators||(e.RelativeDateOperators={}));var l=function(){function t(t,e){this.target=t,this.filterType=e}return t.prototype.toJSON=function(){var t={$schema:this.schemaUrl,target:this.target,filterType:this.filterType};return void 0!==this.displaySettings&&(t.displaySettings=this.displaySettings),t},t}();e.Filter=l;var s=function(t){function e(r,a,i){var n=t.call(this,r,o.Unknown)||this;return n.message=a,n.notSupportedTypeName=i,n.schemaUrl=e.schemaUrl,n}return i(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.message=this.message,e.notSupportedTypeName=this.notSupportedTypeName,e},e.schemaUrl="http://powerbi.com/product/schema#notSupported",e}(l);e.NotSupportedFilter=s;var d=function(t){function e(r,a,i){var n=t.call(this,r,o.IncludeExclude)||this;return n.values=i,n.isExclude=a,n.schemaUrl=e.schemaUrl,n}return i(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.isExclude=this.isExclude,e.values=this.values,e},e.schemaUrl="http://powerbi.com/product/schema#includeExclude",e}(l);e.IncludeExcludeFilter=d;var u=function(t){function e(r,a,i,n){var l=t.call(this,r,o.TopN)||this;return l.operator=a,l.itemCount=i,l.schemaUrl=e.schemaUrl,l.orderBy=n,l}return i(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.operator=this.operator,e.itemCount=this.itemCount,e.orderBy=this.orderBy,e},e.schemaUrl="http://powerbi.com/product/schema#topN",e}(l);e.TopNFilter=u;var c=function(t){function e(r,a,i,n,l){var s=t.call(this,r,o.RelativeDate)||this;return s.operator=a,s.timeUnitsCount=i,s.timeUnitType=n,s.includeToday=l,s.schemaUrl=e.schemaUrl,s}return i(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.operator=this.operator,e.timeUnitsCount=this.timeUnitsCount,e.timeUnitType=this.timeUnitType,e.includeToday=this.includeToday,e},e.schemaUrl="http://powerbi.com/product/schema#relativeDate",e}(l);e.RelativeDateFilter=c;var p=function(t){function e(r,a,i,n){var l=t.call(this,r,o.RelativeTime)||this;return l.operator=a,l.timeUnitsCount=i,l.timeUnitType=n,l.schemaUrl=e.schemaUrl,l}return i(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.operator=this.operator,e.timeUnitsCount=this.timeUnitsCount,e.timeUnitType=this.timeUnitType,e},e.schemaUrl="http://powerbi.com/product/schema#relativeTime",e}(l);e.RelativeTimeFilter=p;var f=function(t){function e(r,a){for(var i=[],n=2;n0&&!i)throw new Error("You should pass the values to be filtered for each key. You passed: no values and "+n+" keys");if(0===n&&i&&i.length>0)throw new Error("You passed key values but your target object doesn't contain the keys to be filtered");for(var l=0,s=o.keyValues;l2)throw new Error("AdvancedFilters may not have more than two conditions. You passed: "+i.length);if(1===l.length&&"And"!==a)throw new Error('Logical Operator must be "And" when there is only one condition provided');return s.conditions=l,s}return i(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.logicalOperator=this.logicalOperator,e.conditions=this.conditions,e},e.schemaUrl="http://powerbi.com/product/schema#advanced",e}(l);function V(t){if(t.filterType)return t.filterType;var e=t,r=t;return"string"==typeof e.operator&&Array.isArray(e.values)?o.Basic:"string"==typeof r.logicalOperator&&Array.isArray(r.conditions)?o.Advanced:o.Unknown}function m(t){return!(!t.table||!t.column||t.aggregationFunction)}e.AdvancedFilter=y,e.isFilterKeyColumnsTarget=function(t){return m(t)&&!!t.keys},e.isBasicFilterWithKeys=function(t){return V(t)===o.Basic&&!!t.keyValues},e.getFilterType=V,e.isMeasure=function(t){return void 0!==t.table&&void 0!==t.measure},e.isColumn=m,e.isHierarchyLevel=function(t){return!(!(t.table&&t.hierarchy&&t.hierarchyLevel)||t.aggregationFunction)},e.isHierarchyLevelAggr=function(t){return!!(t.table&&t.hierarchy&&t.hierarchyLevel&&t.aggregationFunction)},e.isColumnAggr=function(t){return!!(t.table&&t.column&&t.aggregationFunction)},function(t){t[t.Bottom=0]="Bottom",t[t.Left=1]="Left"}(e.PageNavigationPosition||(e.PageNavigationPosition={})),function(t){t[t.Interactive=0]="Interactive",t[t.ResultOnly=1]="ResultOnly"}(e.QnaMode||(e.QnaMode={})),function(t){t[t.Summarized=0]="Summarized",t[t.Underlying=1]="Underlying"}(e.ExportDataType||(e.ExportDataType={})),function(t){t[t.Off=0]="Off",t[t.Presentation=1]="Presentation"}(e.BookmarksPlayMode||(e.BookmarksPlayMode={})),e.CommonErrorCodes={TokenExpired:"TokenExpired",NotFound:"PowerBIEntityNotFound",InvalidParameters:"Invalid parameters",LoadReportFailed:"LoadReportFailed",NotAuthorized:"PowerBINotAuthorizedException",FailedToLoadModel:"ExplorationContainer_FailedToLoadModel_DefaultDetails"},e.TextAlignment={Left:"left",Center:"center",Right:"right"},e.LegendPosition={Top:"Top",Bottom:"Bottom",Right:"Right",Left:"Left",TopCenter:"TopCenter",BottomCenter:"BottomCenter",RightCenter:"RightCenter",LeftCenter:"LeftCenter"},function(t){t[t.Ascending=1]="Ascending",t[t.Descending=2]="Descending"}(e.SortDirection||(e.SortDirection={}));var g=function(){function t(t){this.$schema=t}return t.prototype.toJSON=function(){return{$schema:this.$schema}},t}();e.Selector=g;var b=function(t){function e(r){var a=t.call(this,e.schemaUrl)||this;return a.pageName=r,a}return i(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.pageName=this.pageName,e},e.schemaUrl="http://powerbi.com/product/schema#pageSelector",e}(g);e.PageSelector=b;var w=function(t){function e(r){var a=t.call(this,e.schemaUrl)||this;return a.visualName=r,a}return i(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.visualName=this.visualName,e},e.schemaUrl="http://powerbi.com/product/schema#visualSelector",e}(g);e.VisualSelector=w;var P=function(t){function e(e){var r=t.call(this,w.schemaUrl)||this;return r.visualType=e,r}return i(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.visualType=this.visualType,e},e.schemaUrl="http://powerbi.com/product/schema#visualTypeSelector",e}(g);e.VisualTypeSelector=P;var _=function(t){function e(e){var r=t.call(this,w.schemaUrl)||this;return r.target=e,r}return i(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.target=this.target,e},e.schemaUrl="http://powerbi.com/product/schema#slicerTargetSelector",e}(g);function O(t){return Array.isArray(t)}function S(t){return t&&!!t.groupName}function E(t){return Array.isArray(t)}function T(t){var e=t.message;return e||(e=t.path+" is invalid. Not meeting "+t.keyword+" constraint"),{message:e}}e.SlicerTargetSelector=_,function(t){t[t.Enabled=0]="Enabled",t[t.Disabled=1]="Disabled",t[t.Hidden=2]="Hidden"}(e.CommandDisplayOption||(e.CommandDisplayOption={})),function(t){t[t.Grouping=0]="Grouping",t[t.Measure=1]="Measure",t[t.GroupingOrMeasure=2]="GroupingOrMeasure"}(e.VisualDataRoleKind||(e.VisualDataRoleKind={})),function(t){t[t.Measure=0]="Measure",t[t.Grouping=1]="Grouping"}(e.VisualDataRoleKindPreference||(e.VisualDataRoleKindPreference={})),e.isOnLoadFilters=function(t){return t&&!O(t)},e.isReportFiltersArray=O,e.isFlatMenuExtension=function(t){return t&&!S(t)},e.isGroupedMenuExtension=S,e.isIExtensions=function(t){return t&&!E(t)},e.isIExtensionArray=E,e.validateVisualSelector=function(t){var e=n.Validators.visualSelectorValidator.validate(t);return e?e.map(T):void 0},e.validateSlicer=function(t){var e=n.Validators.slicerValidator.validate(t);return e?e.map(T):void 0},e.validateSlicerState=function(t){var e=n.Validators.slicerStateValidator.validate(t);return e?e.map(T):void 0},e.validatePlayBookmarkRequest=function(t){var e=n.Validators.playBookmarkRequestValidator.validate(t);return e?e.map(T):void 0},e.validateAddBookmarkRequest=function(t){var e=n.Validators.addBookmarkRequestValidator.validate(t);return e?e.map(T):void 0},e.validateApplyBookmarkByNameRequest=function(t){var e=n.Validators.applyBookmarkByNameRequestValidator.validate(t);return e?e.map(T):void 0},e.validateApplyBookmarkStateRequest=function(t){var e=n.Validators.applyBookmarkStateRequestValidator.validate(t);return e?e.map(T):void 0},e.validateCaptureBookmarkRequest=function(t){var e=n.Validators.captureBookmarkRequestValidator.validate(t);return e?e.map(T):void 0},e.validateSettings=function(t){var e=n.Validators.settingsValidator.validate(t);return e?e.map(T):void 0},e.validatePanes=function(t){var e=n.Validators.reportPanesValidator.validate(t);return e?e.map(T):void 0},e.validateBookmarksPane=function(t){var e=n.Validators.bookmarksPaneValidator.validate(t);return e?e.map(T):void 0},e.validateFiltersPane=function(t){var e=n.Validators.filtersPaneValidator.validate(t);return e?e.map(T):void 0},e.validateFieldsPane=function(t){var e=n.Validators.fieldsPaneValidator.validate(t);return e?e.map(T):void 0},e.validatePageNavigationPane=function(t){var e=n.Validators.pageNavigationPaneValidator.validate(t);return e?e.map(T):void 0},e.validateSelectionPane=function(t){var e=n.Validators.selectionPaneValidator.validate(t);return e?e.map(T):void 0},e.validateSyncSlicersPane=function(t){var e=n.Validators.syncSlicersPaneValidator.validate(t);return e?e.map(T):void 0},e.validateVisualizationsPane=function(t){var e=n.Validators.visualizationsPaneValidator.validate(t);return e?e.map(T):void 0},e.validateCustomPageSize=function(t){var e=n.Validators.customPageSizeValidator.validate(t);return e?e.map(T):void 0},e.validateExtension=function(t){var e=n.Validators.extensionValidator.validate(t);return e?e.map(T):void 0},e.validateMenuGroupExtension=function(t){var e=n.Validators.menuGroupExtensionValidator.validate(t);return e?e.map(T):void 0},e.validateReportLoad=function(t){var e=n.Validators.reportLoadValidator.validate(t);return e?e.map(T):void 0},e.validatePaginatedReportLoad=function(t){var e=n.Validators.paginatedReportLoadValidator.validate(t);return e?e.map(T):void 0},e.validateCreateReport=function(t){var e=n.Validators.reportCreateValidator.validate(t);return e?e.map(T):void 0},e.validateDashboardLoad=function(t){var e=n.Validators.dashboardLoadValidator.validate(t);return e?e.map(T):void 0},e.validateTileLoad=function(t){var e=n.Validators.tileLoadValidator.validate(t);return e?e.map(T):void 0},e.validatePage=function(t){var e=n.Validators.pageValidator.validate(t);return e?e.map(T):void 0},e.validateFilter=function(t){var e=n.Validators.filterValidator.validate(t);return e?e.map(T):void 0},e.validateUpdateFiltersRequest=function(t){var e=n.Validators.updateFiltersRequestValidator.validate(t);return e?e.map(T):void 0},e.validateSaveAsParameters=function(t){var e=n.Validators.saveAsParametersValidator.validate(t);return e?e.map(T):void 0},e.validateLoadQnaConfiguration=function(t){var e=n.Validators.loadQnaValidator.validate(t);return e?e.map(T):void 0},e.validateQnaInterpretInputData=function(t){var e=n.Validators.qnaInterpretInputDataValidator.validate(t);return e?e.map(T):void 0},e.validateExportDataRequest=function(t){var e=n.Validators.exportDataRequestValidator.validate(t);return e?e.map(T):void 0},e.validateVisualHeader=function(t){var e=n.Validators.visualHeaderValidator.validate(t);return e?e.map(T):void 0},e.validateVisualSettings=function(t){var e=n.Validators.visualSettingsValidator.validate(t);return e?e.map(T):void 0},e.validateCommandsSettings=function(t){var e=n.Validators.commandsSettingsValidator.validate(t);return e?e.map(T):void 0},e.validateCustomTheme=function(t){var e=n.Validators.customThemeValidator.validate(t);return e?e.map(T):void 0}},function(t,e,r){Object.defineProperty(e,"__esModule",{value:!0}),e.Validators=void 0;var a=r(2),i=r(5),o=r(6),n=r(7),l=r(8),s=r(9),d=r(10),u=r(11),c=r(12),p=r(13),f=r(14),h=r(15),v=r(16),y=r(17),V=r(18),m=r(19),g=r(20),b=r(21),w=r(22),P=r(23),_=r(24),O=r(25),S=r(26),E=r(27),T=r(28),F=r(29),R=r(4),k=r(30);e.Validators={addBookmarkRequestValidator:new i.AddBookmarkRequestValidator,advancedFilterTypeValidator:new R.EnumValidator([0]),advancedFilterValidator:new c.AdvancedFilterValidator,anyArrayValidator:new R.ArrayValidator([new S.AnyOfValidator([new R.StringValidator,new R.NumberValidator,new R.BooleanValidator])]),anyFilterValidator:new S.AnyOfValidator([new c.BasicFilterValidator,new c.AdvancedFilterValidator,new c.IncludeExcludeFilterValidator,new c.NotSupportedFilterValidator,new c.RelativeDateFilterValidator,new c.TopNFilterValidator,new c.RelativeTimeFilterValidator]),anyValueValidator:new S.AnyOfValidator([new R.StringValidator,new R.NumberValidator,new R.BooleanValidator]),actionBarValidator:new a.ActionBarValidator,applyBookmarkByNameRequestValidator:new i.ApplyBookmarkByNameRequestValidator,applyBookmarkStateRequestValidator:new i.ApplyBookmarkStateRequestValidator,applyBookmarkValidator:new S.AnyOfValidator([new i.ApplyBookmarkByNameRequestValidator,new i.ApplyBookmarkStateRequestValidator]),backgroundValidator:new R.EnumValidator([0,1]),basicFilterTypeValidator:new R.EnumValidator([1]),basicFilterValidator:new c.BasicFilterValidator,booleanArrayValidator:new R.BooleanArrayValidator,booleanValidator:new R.BooleanValidator,bookmarksPaneValidator:new h.BookmarksPaneValidator,captureBookmarkOptionsValidator:new i.CaptureBookmarkOptionsValidator,captureBookmarkRequestValidator:new i.CaptureBookmarkRequestValidator,commandDisplayOptionValidator:new R.EnumValidator([0,1,2]),commandExtensionSelectorValidator:new S.AnyOfValidator([new b.VisualSelectorValidator,new b.VisualTypeSelectorValidator]),commandExtensionArrayValidator:new R.ArrayValidator([new u.CommandExtensionValidator]),commandExtensionValidator:new u.CommandExtensionValidator,commandsSettingsArrayValidator:new R.ArrayValidator([new o.CommandsSettingsValidator]),commandsSettingsValidator:new o.CommandsSettingsValidator,conditionItemValidator:new c.ConditionItemValidator,contrastModeValidator:new R.EnumValidator([0,1,2,3,4]),customLayoutDisplayOptionValidator:new R.EnumValidator([0,1,2]),customLayoutValidator:new p.CustomLayoutValidator,customPageSizeValidator:new f.CustomPageSizeValidator,customThemeValidator:new n.CustomThemeValidator,dashboardLoadValidator:new l.DashboardLoadValidator,datasetBindingValidator:new s.DatasetBindingValidator,displayStateModeValidator:new R.EnumValidator([0,1]),displayStateValidator:new p.DisplayStateValidator,exportDataRequestValidator:new d.ExportDataRequestValidator,extensionArrayValidator:new R.ArrayValidator([new u.ExtensionValidator]),extensionsValidator:new S.AnyOfValidator([new R.ArrayValidator([new u.ExtensionValidator]),new u.ExtensionsValidator]),extensionPointsValidator:new u.ExtensionPointsValidator,extensionValidator:new u.ExtensionValidator,fieldForbiddenValidator:new E.FieldForbiddenValidator,fieldRequiredValidator:new T.FieldRequiredValidator,fieldsPaneValidator:new h.FieldsPaneValidator,filterColumnTargetValidator:new c.FilterColumnTargetValidator,filterDisplaySettingsValidator:new c.FilterDisplaySettingsValidator,filterConditionsValidator:new R.ArrayValidator([new c.ConditionItemValidator]),filterHierarchyTargetValidator:new c.FilterHierarchyTargetValidator,filterMeasureTargetValidator:new c.FilterMeasureTargetValidator,filterTargetValidator:new S.AnyOfValidator([new c.FilterColumnTargetValidator,new c.FilterHierarchyTargetValidator,new c.FilterMeasureTargetValidator]),filterValidator:new c.FilterValidator,filterTypeValidator:new R.EnumValidator([0,1,2,3,4,5,6,7]),filtersArrayValidator:new R.ArrayValidator([new c.FilterValidator]),filtersOperationsUpdateValidator:new R.EnumValidator([1,2,3]),filtersOperationsRemoveAllValidator:new R.EnumValidator([0]),filtersPaneValidator:new h.FiltersPaneValidator,hyperlinkClickBehaviorValidator:new R.EnumValidator([0,1,2]),includeExcludeFilterValidator:new c.IncludeExcludeFilterValidator,includeExludeFilterTypeValidator:new R.EnumValidator([3]),layoutTypeValidator:new R.EnumValidator([0,1,2,3]),loadQnaValidator:new v.LoadQnaValidator,menuExtensionValidator:new S.AnyOfValidator([new u.FlatMenuExtensionValidator,new u.GroupedMenuExtensionValidator]),menuGroupExtensionArrayValidator:new R.ArrayValidator([new u.MenuGroupExtensionValidator]),menuGroupExtensionValidator:new u.MenuGroupExtensionValidator,menuLocationValidator:new R.EnumValidator([0,1]),notSupportedFilterTypeValidator:new R.EnumValidator([2]),notSupportedFilterValidator:new c.NotSupportedFilterValidator,numberArrayValidator:new R.NumberArrayValidator,numberValidator:new R.NumberValidator,onLoadFiltersBaseValidator:new S.AnyOfValidator([new c.OnLoadFiltersBaseValidator,new c.OnLoadFiltersBaseRemoveOperationValidator]),pageLayoutValidator:new F.MapValidator([new R.StringValidator],[new p.VisualLayoutValidator]),pageNavigationPaneValidator:new h.PageNavigationPaneValidator,pageNavigationPositionValidator:new R.EnumValidator([0,1]),pageSizeTypeValidator:new R.EnumValidator([0,1,2,3,4,5]),pageSizeValidator:new f.PageSizeValidator,pageValidator:new f.PageValidator,pageViewFieldValidator:new f.PageViewFieldValidator,pagesLayoutValidator:new F.MapValidator([new R.StringValidator],[new p.PageLayoutValidator]),paginatedReportCommandsValidator:new o.PaginatedReportCommandsValidator,paginatedReportLoadValidator:new m.PaginatedReportLoadValidator,paginatedReportsettingsValidator:new w.PaginatedReportSettingsValidator,parametersPanelValidator:new k.ParametersPanelValidator,permissionsValidator:new R.EnumValidator([0,1,2,4,7]),playBookmarkRequestValidator:new i.PlayBookmarkRequestValidator,qnaInterpretInputDataValidator:new v.QnaInterpretInputDataValidator,qnaPanesValidator:new h.QnaPanesValidator,qnaSettingValidator:new v.QnaSettingsValidator,relativeDateFilterOperatorValidator:new R.EnumValidator([0,1,2]),relativeDateFilterTimeUnitTypeValidator:new R.EnumValidator([0,1,2,3,4,5,6]),relativeDateFilterTypeValidator:new R.EnumValidator([4]),relativeDateFilterValidator:new c.RelativeDateFilterValidator,relativeDateTimeFilterTypeValidator:new R.EnumValidator([4,7]),relativeDateTimeFilterUnitTypeValidator:new R.EnumValidator([0,1,2,3,4,5,6,7,8]),relativeTimeFilterTimeUnitTypeValidator:new R.EnumValidator([7,8]),relativeTimeFilterTypeValidator:new R.EnumValidator([7]),relativeTimeFilterValidator:new c.RelativeTimeFilterValidator,reportBarsValidator:new a.ReportBarsValidator,reportCreateValidator:new y.ReportCreateValidator,reportLoadFiltersValidator:new S.AnyOfValidator([new R.ArrayValidator([new c.FilterValidator]),new c.OnLoadFiltersValidator]),reportLoadValidator:new V.ReportLoadValidator,reportPanesValidator:new h.ReportPanesValidator,saveAsParametersValidator:new g.SaveAsParametersValidator,selectionPaneValidator:new h.SelectionPaneValidator,settingsValidator:new w.SettingsValidator,singleCommandSettingsValidator:new o.SingleCommandSettingsValidator,slicerSelectorValidator:new S.AnyOfValidator([new b.VisualSelectorValidator,new b.SlicerTargetSelectorValidator]),slicerStateValidator:new P.SlicerStateValidator,slicerTargetValidator:new S.AnyOfValidator([new c.FilterColumnTargetValidator,new c.FilterHierarchyTargetValidator,new c.FilterMeasureTargetValidator,new c.FilterKeyColumnsTargetValidator,new c.FilterKeyHierarchyTargetValidator]),slicerValidator:new P.SlicerValidator,stringArrayValidator:new R.StringArrayValidator,stringValidator:new R.StringValidator,syncSlicersPaneValidator:new h.SyncSlicersPaneValidator,tileLoadValidator:new _.TileLoadValidator,tokenTypeValidator:new R.EnumValidator([0,1]),topNFilterTypeValidator:new R.EnumValidator([5]),topNFilterValidator:new c.TopNFilterValidator,updateFiltersRequestValidator:new S.AnyOfValidator([new c.UpdateFiltersRequestValidator,new c.RemoveFiltersRequestValidator]),viewModeValidator:new R.EnumValidator([0,1]),visualCommandSelectorValidator:new S.AnyOfValidator([new b.VisualSelectorValidator,new b.VisualTypeSelectorValidator]),visualHeaderSelectorValidator:new S.AnyOfValidator([new b.VisualSelectorValidator,new b.VisualTypeSelectorValidator]),visualHeaderSettingsValidator:new O.VisualHeaderSettingsValidator,visualHeaderValidator:new O.VisualHeaderValidator,visualHeadersValidator:new R.ArrayValidator([new O.VisualHeaderValidator]),visualizationsPaneValidator:new h.VisualizationsPaneValidator,visualLayoutValidator:new p.VisualLayoutValidator,visualSelectorValidator:new b.VisualSelectorValidator,visualSettingsValidator:new O.VisualSettingsValidator,visualTypeSelectorValidator:new b.VisualTypeSelectorValidator}},function(t,e,r){var a,i=this&&this.__extends||(a=function(t,e){return(a=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])})(t,e)},function(t,e){function r(){this.constructor=t}a(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)});Object.defineProperty(e,"__esModule",{value:!0}),e.ActionBarValidator=e.ReportBarsValidator=void 0;var o=r(3),n=r(4),l=r(1),s=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i(e,t),e.prototype.validate=function(e,r,a){if(null==e)return null;var i=t.prototype.validate.call(this,e,r,a);if(i)return i;var n=[{field:"actionBar",validators:[l.Validators.actionBarValidator]}];return new o.MultipleFieldsValidator(n).validate(e,r,a)},e}(n.ObjectValidator);e.ReportBarsValidator=s;var d=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return i(e,t),e.prototype.validate=function(e,r,a){if(null==e)return null;var i=t.prototype.validate.call(this,e,r,a);if(i)return i;var n=[{field:"visible",validators:[l.Validators.booleanValidator]}];return new o.MultipleFieldsValidator(n).validate(e,r,a)},e}(n.ObjectValidator);e.ActionBarValidator=d},function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.MultipleFieldsValidator=void 0;var r=function(){function t(t){this.fieldValidatorsPairs=t}return t.prototype.validate=function(t,e,r){if(!this.fieldValidatorsPairs)return null;for(var a=e?e+"."+r:r,i=0,o=this.fieldValidatorsPairs;i0&&i[i.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&i[i.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0?"&":"?";return t+=a+e+"="+r},e.isSavedInternal=function(t,e,i){return r(this,void 0,void 0,(function(){return a(this,(function(r){switch(r.label){case 0:return r.trys.push([0,2,,3]),[4,t.get("/report/hasUnsavedChanges",{uid:e},i)];case 1:return[2,!r.sent().body];case 2:throw r.sent().body;case 3:return[2]}}))}))},e.isRDLEmbed=function(t){return t.toLowerCase().indexOf("/rdlembed?")>=0},e.autoAuthInEmbedUrl=function(t){return t&&decodeURIComponent(t).toLowerCase().indexOf("autoauth=true")>=0},e.getRandomValue=o,e.getTimeDiffInMilliseconds=function(t,e){return Math.abs(t.getTime()-e.getTime())}},function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.EmbedUrlNotSupported=e.APINotSupportedForRDLError=void 0,e.APINotSupportedForRDLError="This API is currently not supported for RDL reports",e.EmbedUrlNotSupported="Embed URL is invalid for this scenario. Please use Power BI REST APIs to get the valid URL"},function(t,e,r){var a,i=this&&this.__extends||(a=function(t,e){return(a=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])})(t,e)},function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function r(){this.constructor=t}a(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}),o=this&&this.__awaiter||function(t,e,r,a){return new(r||(r=Promise))((function(i,o){function n(t){try{s(a.next(t))}catch(t){o(t)}}function l(t){try{s(a.throw(t))}catch(t){o(t)}}function s(t){var e;t.done?i(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(n,l)}s((a=a.apply(t,e||[])).next())}))},n=this&&this.__generator||function(t,e){var r,a,i,o,n={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function l(o){return function(l){return function(o){if(r)throw new TypeError("Generator is already executing.");for(;n;)try{if(r=1,a&&(i=2&o[0]?a.return:o[0]?a.throw||((i=a.return)&&i.call(a),0):a.next)&&!(i=i.call(a,o[1])).done)return i;switch(a=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return n.label++,{value:o[1],done:!1};case 5:n.label++,a=o[1],o=[0];continue;case 7:o=n.ops.pop(),n.trys.pop();continue;default:if(!(i=n.trys,(i=i.length>0&&i[i.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&i[i.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&i[i.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&i[i.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&i[i.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&i[i.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&i[i.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&!a)throw new Error("You should pass the values to be filtered for each key. You passed: no values and "+n+" keys");if(0===n&&a&&a.length>0)throw new Error("You passed key values but your target object doesn't contain the keys to be filtered");for(var l=0,s=o.keyValues;l2)throw new Error("AdvancedFilters may not have more than two conditions. You passed: "+a.length);if(1===l.length&&"And"!==i)throw new Error('Logical Operator must be "And" when there is only one condition provided');return s.conditions=l,s}return a(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.logicalOperator=this.logicalOperator,e.conditions=this.conditions,e},e.schemaUrl="http://powerbi.com/product/schema#advanced",e}(l);function V(t){if(t.filterType)return t.filterType;var e=t,r=t;return"string"==typeof e.operator&&Array.isArray(e.values)?o.Basic:"string"==typeof r.logicalOperator&&Array.isArray(r.conditions)?o.Advanced:o.Unknown}function g(t){return!(!t.table||!t.column||t.aggregationFunction)}e.AdvancedFilter=m,e.isFilterKeyColumnsTarget=function(t){return g(t)&&!!t.keys},e.isBasicFilterWithKeys=function(t){return V(t)===o.Basic&&!!t.keyValues},e.getFilterType=V,e.isMeasure=function(t){return void 0!==t.table&&void 0!==t.measure},e.isColumn=g,e.isHierarchyLevel=function(t){return!(!(t.table&&t.hierarchy&&t.hierarchyLevel)||t.aggregationFunction)},e.isHierarchyLevelAggr=function(t){return!!(t.table&&t.hierarchy&&t.hierarchyLevel&&t.aggregationFunction)},e.isColumnAggr=function(t){return!!(t.table&&t.column&&t.aggregationFunction)},function(t){t[t.Bottom=0]="Bottom",t[t.Left=1]="Left"}(e.PageNavigationPosition||(e.PageNavigationPosition={})),function(t){t[t.Interactive=0]="Interactive",t[t.ResultOnly=1]="ResultOnly"}(e.QnaMode||(e.QnaMode={})),function(t){t[t.Summarized=0]="Summarized",t[t.Underlying=1]="Underlying"}(e.ExportDataType||(e.ExportDataType={})),function(t){t[t.Off=0]="Off",t[t.Presentation=1]="Presentation"}(e.BookmarksPlayMode||(e.BookmarksPlayMode={})),e.CommonErrorCodes={TokenExpired:"TokenExpired",NotFound:"PowerBIEntityNotFound",InvalidParameters:"Invalid parameters",LoadReportFailed:"LoadReportFailed",NotAuthorized:"PowerBINotAuthorizedException",FailedToLoadModel:"ExplorationContainer_FailedToLoadModel_DefaultDetails"},e.TextAlignment={Left:"left",Center:"center",Right:"right"},e.LegendPosition={Top:"Top",Bottom:"Bottom",Right:"Right",Left:"Left",TopCenter:"TopCenter",BottomCenter:"BottomCenter",RightCenter:"RightCenter",LeftCenter:"LeftCenter"},function(t){t[t.Ascending=1]="Ascending",t[t.Descending=2]="Descending"}(e.SortDirection||(e.SortDirection={}));var b=function(){function t(t){this.$schema=t}return t.prototype.toJSON=function(){return{$schema:this.$schema}},t}();e.Selector=b;var w=function(t){function e(r){var i=t.call(this,e.schemaUrl)||this;return i.pageName=r,i}return a(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.pageName=this.pageName,e},e.schemaUrl="http://powerbi.com/product/schema#pageSelector",e}(b);e.PageSelector=w;var P=function(t){function e(r){var i=t.call(this,e.schemaUrl)||this;return i.visualName=r,i}return a(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.visualName=this.visualName,e},e.schemaUrl="http://powerbi.com/product/schema#visualSelector",e}(b);e.VisualSelector=P;var _=function(t){function e(e){var r=t.call(this,P.schemaUrl)||this;return r.visualType=e,r}return a(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.visualType=this.visualType,e},e.schemaUrl="http://powerbi.com/product/schema#visualTypeSelector",e}(b);e.VisualTypeSelector=_;var O=function(t){function e(e){var r=t.call(this,P.schemaUrl)||this;return r.target=e,r}return a(e,t),e.prototype.toJSON=function(){var e=t.prototype.toJSON.call(this);return e.target=this.target,e},e.schemaUrl="http://powerbi.com/product/schema#slicerTargetSelector",e}(b);function S(t){return Array.isArray(t)}function T(t){return t&&!!t.groupName}function E(t){return Array.isArray(t)}function F(t){var e=t.message;return e||(e=t.path+" is invalid. Not meeting "+t.keyword+" constraint"),{message:e}}e.SlicerTargetSelector=O,function(t){t[t.Enabled=0]="Enabled",t[t.Disabled=1]="Disabled",t[t.Hidden=2]="Hidden"}(e.CommandDisplayOption||(e.CommandDisplayOption={})),function(t){t[t.Grouping=0]="Grouping",t[t.Measure=1]="Measure",t[t.GroupingOrMeasure=2]="GroupingOrMeasure"}(e.VisualDataRoleKind||(e.VisualDataRoleKind={})),function(t){t[t.Measure=0]="Measure",t[t.Grouping=1]="Grouping"}(e.VisualDataRoleKindPreference||(e.VisualDataRoleKindPreference={})),e.isOnLoadFilters=function(t){return t&&!S(t)},e.isReportFiltersArray=S,e.isFlatMenuExtension=function(t){return t&&!T(t)},e.isGroupedMenuExtension=T,e.isIExtensions=function(t){return t&&!E(t)},e.isIExtensionArray=E,e.validateVisualSelector=function(t){var e=n.Validators.visualSelectorValidator.validate(t);return e?e.map(F):void 0},e.validateSlicer=function(t){var e=n.Validators.slicerValidator.validate(t);return e?e.map(F):void 0},e.validateSlicerState=function(t){var e=n.Validators.slicerStateValidator.validate(t);return e?e.map(F):void 0},e.validatePlayBookmarkRequest=function(t){var e=n.Validators.playBookmarkRequestValidator.validate(t);return e?e.map(F):void 0},e.validateAddBookmarkRequest=function(t){var e=n.Validators.addBookmarkRequestValidator.validate(t);return e?e.map(F):void 0},e.validateApplyBookmarkByNameRequest=function(t){var e=n.Validators.applyBookmarkByNameRequestValidator.validate(t);return e?e.map(F):void 0},e.validateApplyBookmarkStateRequest=function(t){var e=n.Validators.applyBookmarkStateRequestValidator.validate(t);return e?e.map(F):void 0},e.validateCaptureBookmarkRequest=function(t){var e=n.Validators.captureBookmarkRequestValidator.validate(t);return e?e.map(F):void 0},e.validateSettings=function(t){var e=n.Validators.settingsValidator.validate(t);return e?e.map(F):void 0},e.validatePanes=function(t){var e=n.Validators.reportPanesValidator.validate(t);return e?e.map(F):void 0},e.validateBookmarksPane=function(t){var e=n.Validators.bookmarksPaneValidator.validate(t);return e?e.map(F):void 0},e.validateFiltersPane=function(t){var e=n.Validators.filtersPaneValidator.validate(t);return e?e.map(F):void 0},e.validateFieldsPane=function(t){var e=n.Validators.fieldsPaneValidator.validate(t);return e?e.map(F):void 0},e.validatePageNavigationPane=function(t){var e=n.Validators.pageNavigationPaneValidator.validate(t);return e?e.map(F):void 0},e.validateSelectionPane=function(t){var e=n.Validators.selectionPaneValidator.validate(t);return e?e.map(F):void 0},e.validateSyncSlicersPane=function(t){var e=n.Validators.syncSlicersPaneValidator.validate(t);return e?e.map(F):void 0},e.validateVisualizationsPane=function(t){var e=n.Validators.visualizationsPaneValidator.validate(t);return e?e.map(F):void 0},e.validateCustomPageSize=function(t){var e=n.Validators.customPageSizeValidator.validate(t);return e?e.map(F):void 0},e.validateExtension=function(t){var e=n.Validators.extensionValidator.validate(t);return e?e.map(F):void 0},e.validateMenuGroupExtension=function(t){var e=n.Validators.menuGroupExtensionValidator.validate(t);return e?e.map(F):void 0},e.validateReportLoad=function(t){var e=n.Validators.reportLoadValidator.validate(t);return e?e.map(F):void 0},e.validatePaginatedReportLoad=function(t){var e=n.Validators.paginatedReportLoadValidator.validate(t);return e?e.map(F):void 0},e.validateCreateReport=function(t){var e=n.Validators.reportCreateValidator.validate(t);return e?e.map(F):void 0},e.validateDashboardLoad=function(t){var e=n.Validators.dashboardLoadValidator.validate(t);return e?e.map(F):void 0},e.validateTileLoad=function(t){var e=n.Validators.tileLoadValidator.validate(t);return e?e.map(F):void 0},e.validatePage=function(t){var e=n.Validators.pageValidator.validate(t);return e?e.map(F):void 0},e.validateFilter=function(t){var e=n.Validators.filterValidator.validate(t);return e?e.map(F):void 0},e.validateUpdateFiltersRequest=function(t){var e=n.Validators.updateFiltersRequestValidator.validate(t);return e?e.map(F):void 0},e.validateSaveAsParameters=function(t){var e=n.Validators.saveAsParametersValidator.validate(t);return e?e.map(F):void 0},e.validateLoadQnaConfiguration=function(t){var e=n.Validators.loadQnaValidator.validate(t);return e?e.map(F):void 0},e.validateQnaInterpretInputData=function(t){var e=n.Validators.qnaInterpretInputDataValidator.validate(t);return e?e.map(F):void 0},e.validateExportDataRequest=function(t){var e=n.Validators.exportDataRequestValidator.validate(t);return e?e.map(F):void 0},e.validateVisualHeader=function(t){var e=n.Validators.visualHeaderValidator.validate(t);return e?e.map(F):void 0},e.validateVisualSettings=function(t){var e=n.Validators.visualSettingsValidator.validate(t);return e?e.map(F):void 0},e.validateCommandsSettings=function(t){var e=n.Validators.commandsSettingsValidator.validate(t);return e?e.map(F):void 0},e.validateCustomTheme=function(t){var e=n.Validators.customThemeValidator.validate(t);return e?e.map(F):void 0}},function(t,e,r){Object.defineProperty(e,"__esModule",{value:!0}),e.Validators=void 0;var i=r(2),a=r(5),o=r(6),n=r(7),l=r(8),s=r(9),u=r(10),d=r(11),c=r(12),p=r(13),f=r(14),h=r(15),v=r(16),y=r(17),m=r(18),V=r(19),g=r(20),b=r(21),w=r(22),P=r(23),_=r(24),O=r(25),S=r(26),T=r(27),E=r(28),F=r(29),R=r(4),x=r(30);e.Validators={addBookmarkRequestValidator:new a.AddBookmarkRequestValidator,advancedFilterTypeValidator:new R.EnumValidator([0]),advancedFilterValidator:new c.AdvancedFilterValidator,anyArrayValidator:new R.ArrayValidator([new S.AnyOfValidator([new R.StringValidator,new R.NumberValidator,new R.BooleanValidator])]),anyFilterValidator:new S.AnyOfValidator([new c.BasicFilterValidator,new c.AdvancedFilterValidator,new c.IncludeExcludeFilterValidator,new c.NotSupportedFilterValidator,new c.RelativeDateFilterValidator,new c.TopNFilterValidator,new c.RelativeTimeFilterValidator]),anyValueValidator:new S.AnyOfValidator([new R.StringValidator,new R.NumberValidator,new R.BooleanValidator]),actionBarValidator:new i.ActionBarValidator,applyBookmarkByNameRequestValidator:new a.ApplyBookmarkByNameRequestValidator,applyBookmarkStateRequestValidator:new a.ApplyBookmarkStateRequestValidator,applyBookmarkValidator:new S.AnyOfValidator([new a.ApplyBookmarkByNameRequestValidator,new a.ApplyBookmarkStateRequestValidator]),backgroundValidator:new R.EnumValidator([0,1]),basicFilterTypeValidator:new R.EnumValidator([1]),basicFilterValidator:new c.BasicFilterValidator,booleanArrayValidator:new R.BooleanArrayValidator,booleanValidator:new R.BooleanValidator,bookmarksPaneValidator:new h.BookmarksPaneValidator,captureBookmarkOptionsValidator:new a.CaptureBookmarkOptionsValidator,captureBookmarkRequestValidator:new a.CaptureBookmarkRequestValidator,commandDisplayOptionValidator:new R.EnumValidator([0,1,2]),commandExtensionSelectorValidator:new S.AnyOfValidator([new b.VisualSelectorValidator,new b.VisualTypeSelectorValidator]),commandExtensionArrayValidator:new R.ArrayValidator([new d.CommandExtensionValidator]),commandExtensionValidator:new d.CommandExtensionValidator,commandsSettingsArrayValidator:new R.ArrayValidator([new o.CommandsSettingsValidator]),commandsSettingsValidator:new o.CommandsSettingsValidator,conditionItemValidator:new c.ConditionItemValidator,contrastModeValidator:new R.EnumValidator([0,1,2,3,4]),customLayoutDisplayOptionValidator:new R.EnumValidator([0,1,2]),customLayoutValidator:new p.CustomLayoutValidator,customPageSizeValidator:new f.CustomPageSizeValidator,customThemeValidator:new n.CustomThemeValidator,dashboardLoadValidator:new l.DashboardLoadValidator,datasetBindingValidator:new s.DatasetBindingValidator,displayStateModeValidator:new R.EnumValidator([0,1]),displayStateValidator:new p.DisplayStateValidator,exportDataRequestValidator:new u.ExportDataRequestValidator,extensionArrayValidator:new R.ArrayValidator([new d.ExtensionValidator]),extensionsValidator:new S.AnyOfValidator([new R.ArrayValidator([new d.ExtensionValidator]),new d.ExtensionsValidator]),extensionPointsValidator:new d.ExtensionPointsValidator,extensionValidator:new d.ExtensionValidator,fieldForbiddenValidator:new T.FieldForbiddenValidator,fieldRequiredValidator:new E.FieldRequiredValidator,fieldsPaneValidator:new h.FieldsPaneValidator,filterColumnTargetValidator:new c.FilterColumnTargetValidator,filterDisplaySettingsValidator:new c.FilterDisplaySettingsValidator,filterConditionsValidator:new R.ArrayValidator([new c.ConditionItemValidator]),filterHierarchyTargetValidator:new c.FilterHierarchyTargetValidator,filterMeasureTargetValidator:new c.FilterMeasureTargetValidator,filterTargetValidator:new S.AnyOfValidator([new c.FilterColumnTargetValidator,new c.FilterHierarchyTargetValidator,new c.FilterMeasureTargetValidator]),filterValidator:new c.FilterValidator,filterTypeValidator:new R.EnumValidator([0,1,2,3,4,5,6,7]),filtersArrayValidator:new R.ArrayValidator([new c.FilterValidator]),filtersOperationsUpdateValidator:new R.EnumValidator([1,2,3]),filtersOperationsRemoveAllValidator:new R.EnumValidator([0]),filtersPaneValidator:new h.FiltersPaneValidator,hyperlinkClickBehaviorValidator:new R.EnumValidator([0,1,2]),includeExcludeFilterValidator:new c.IncludeExcludeFilterValidator,includeExludeFilterTypeValidator:new R.EnumValidator([3]),layoutTypeValidator:new R.EnumValidator([0,1,2,3]),loadQnaValidator:new v.LoadQnaValidator,menuExtensionValidator:new S.AnyOfValidator([new d.FlatMenuExtensionValidator,new d.GroupedMenuExtensionValidator]),menuGroupExtensionArrayValidator:new R.ArrayValidator([new d.MenuGroupExtensionValidator]),menuGroupExtensionValidator:new d.MenuGroupExtensionValidator,menuLocationValidator:new R.EnumValidator([0,1]),notSupportedFilterTypeValidator:new R.EnumValidator([2]),notSupportedFilterValidator:new c.NotSupportedFilterValidator,numberArrayValidator:new R.NumberArrayValidator,numberValidator:new R.NumberValidator,onLoadFiltersBaseValidator:new S.AnyOfValidator([new c.OnLoadFiltersBaseValidator,new c.OnLoadFiltersBaseRemoveOperationValidator]),pageLayoutValidator:new F.MapValidator([new R.StringValidator],[new p.VisualLayoutValidator]),pageNavigationPaneValidator:new h.PageNavigationPaneValidator,pageNavigationPositionValidator:new R.EnumValidator([0,1]),pageSizeTypeValidator:new R.EnumValidator([0,1,2,3,4,5]),pageSizeValidator:new f.PageSizeValidator,pageValidator:new f.PageValidator,pageViewFieldValidator:new f.PageViewFieldValidator,pagesLayoutValidator:new F.MapValidator([new R.StringValidator],[new p.PageLayoutValidator]),paginatedReportCommandsValidator:new o.PaginatedReportCommandsValidator,paginatedReportLoadValidator:new V.PaginatedReportLoadValidator,paginatedReportsettingsValidator:new w.PaginatedReportSettingsValidator,parametersPanelValidator:new x.ParametersPanelValidator,permissionsValidator:new R.EnumValidator([0,1,2,4,7]),playBookmarkRequestValidator:new a.PlayBookmarkRequestValidator,qnaInterpretInputDataValidator:new v.QnaInterpretInputDataValidator,qnaPanesValidator:new h.QnaPanesValidator,qnaSettingValidator:new v.QnaSettingsValidator,relativeDateFilterOperatorValidator:new R.EnumValidator([0,1,2]),relativeDateFilterTimeUnitTypeValidator:new R.EnumValidator([0,1,2,3,4,5,6]),relativeDateFilterTypeValidator:new R.EnumValidator([4]),relativeDateFilterValidator:new c.RelativeDateFilterValidator,relativeDateTimeFilterTypeValidator:new R.EnumValidator([4,7]),relativeDateTimeFilterUnitTypeValidator:new R.EnumValidator([0,1,2,3,4,5,6,7,8]),relativeTimeFilterTimeUnitTypeValidator:new R.EnumValidator([7,8]),relativeTimeFilterTypeValidator:new R.EnumValidator([7]),relativeTimeFilterValidator:new c.RelativeTimeFilterValidator,reportBarsValidator:new i.ReportBarsValidator,reportCreateValidator:new y.ReportCreateValidator,reportLoadFiltersValidator:new S.AnyOfValidator([new R.ArrayValidator([new c.FilterValidator]),new c.OnLoadFiltersValidator]),reportLoadValidator:new m.ReportLoadValidator,reportPanesValidator:new h.ReportPanesValidator,saveAsParametersValidator:new g.SaveAsParametersValidator,selectionPaneValidator:new h.SelectionPaneValidator,settingsValidator:new w.SettingsValidator,singleCommandSettingsValidator:new o.SingleCommandSettingsValidator,slicerSelectorValidator:new S.AnyOfValidator([new b.VisualSelectorValidator,new b.SlicerTargetSelectorValidator]),slicerStateValidator:new P.SlicerStateValidator,slicerTargetValidator:new S.AnyOfValidator([new c.FilterColumnTargetValidator,new c.FilterHierarchyTargetValidator,new c.FilterMeasureTargetValidator,new c.FilterKeyColumnsTargetValidator,new c.FilterKeyHierarchyTargetValidator]),slicerValidator:new P.SlicerValidator,stringArrayValidator:new R.StringArrayValidator,stringValidator:new R.StringValidator,syncSlicersPaneValidator:new h.SyncSlicersPaneValidator,tileLoadValidator:new _.TileLoadValidator,tokenTypeValidator:new R.EnumValidator([0,1]),topNFilterTypeValidator:new R.EnumValidator([5]),topNFilterValidator:new c.TopNFilterValidator,updateFiltersRequestValidator:new S.AnyOfValidator([new c.UpdateFiltersRequestValidator,new c.RemoveFiltersRequestValidator]),viewModeValidator:new R.EnumValidator([0,1]),visualCommandSelectorValidator:new S.AnyOfValidator([new b.VisualSelectorValidator,new b.VisualTypeSelectorValidator]),visualHeaderSelectorValidator:new S.AnyOfValidator([new b.VisualSelectorValidator,new b.VisualTypeSelectorValidator]),visualHeaderSettingsValidator:new O.VisualHeaderSettingsValidator,visualHeaderValidator:new O.VisualHeaderValidator,visualHeadersValidator:new R.ArrayValidator([new O.VisualHeaderValidator]),visualizationsPaneValidator:new h.VisualizationsPaneValidator,visualLayoutValidator:new p.VisualLayoutValidator,visualSelectorValidator:new b.VisualSelectorValidator,visualSettingsValidator:new O.VisualSettingsValidator,visualTypeSelectorValidator:new b.VisualTypeSelectorValidator}},function(t,e,r){var i,a=this&&this.__extends||(i=function(t,e){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r])})(t,e)},function(t,e){function r(){this.constructor=t}i(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)});Object.defineProperty(e,"__esModule",{value:!0}),e.ActionBarValidator=e.ReportBarsValidator=void 0;var o=r(3),n=r(4),l=r(1),s=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.validate=function(e,r,i){if(null==e)return null;var a=t.prototype.validate.call(this,e,r,i);if(a)return a;var n=[{field:"actionBar",validators:[l.Validators.actionBarValidator]}];return new o.MultipleFieldsValidator(n).validate(e,r,i)},e}(n.ObjectValidator);e.ReportBarsValidator=s;var u=function(t){function e(){return null!==t&&t.apply(this,arguments)||this}return a(e,t),e.prototype.validate=function(e,r,i){if(null==e)return null;var a=t.prototype.validate.call(this,e,r,i);if(a)return a;var n=[{field:"visible",validators:[l.Validators.booleanValidator]}];return new o.MultipleFieldsValidator(n).validate(e,r,i)},e}(n.ObjectValidator);e.ActionBarValidator=u},function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.MultipleFieldsValidator=void 0;var r=function(){function t(t){this.fieldValidatorsPairs=t}return t.prototype.validate=function(t,e,r){if(!this.fieldValidatorsPairs)return null;for(var i=e?e+"."+r:r,a=0,o=this.fieldValidatorsPairs;a0&&a[a.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!a||o[1]>a[0]&&o[1]0&&a[a.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!a||o[1]>a[0]&&o[1]0?"&":"?";return t+=i+e+"="+r},e.isSavedInternal=function(t,e,a){return r(this,void 0,void 0,(function(){return i(this,(function(r){switch(r.label){case 0:return r.trys.push([0,2,,3]),[4,t.get("/report/hasUnsavedChanges",{uid:e},a)];case 1:return[2,!r.sent().body];case 2:throw r.sent().body;case 3:return[2]}}))}))},e.isRDLEmbed=function(t){return t&&t.toLowerCase().indexOf("/rdlembed?")>=0},e.autoAuthInEmbedUrl=function(t){return t&&decodeURIComponent(t).toLowerCase().indexOf("autoauth=true")>=0},e.getRandomValue=o,e.getTimeDiffInMilliseconds=function(t,e){return Math.abs(t.getTime()-e.getTime())}},function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.FilterBuilder=void 0;var r=function(){function t(){}return t.prototype.withTargetObject=function(t){return this.target=t,this},t.prototype.withColumnTarget=function(t,e){return this.target={table:t,column:e},this},t.prototype.withMeasureTarget=function(t,e){return this.target={table:t,measure:e},this},t.prototype.withHierarchyLevelTarget=function(t,e,r){return this.target={table:t,hierarchy:e,hierarchyLevel:r},this},t.prototype.withColumnAggregation=function(t,e,r){return this.target={table:t,column:e,aggregationFunction:r},this},t.prototype.withHierarchyLevelAggregationTarget=function(t,e,r,i){return this.target={table:t,hierarchy:e,hierarchyLevel:r,aggregationFunction:i},this},t}();e.FilterBuilder=r},function(t,e){Object.defineProperty(e,"__esModule",{value:!0}),e.EmbedUrlNotSupported=e.APINotSupportedForRDLError=void 0,e.APINotSupportedForRDLError="This API is currently not supported for RDL reports",e.EmbedUrlNotSupported="Embed URL is invalid for this scenario. Please use Power BI REST APIs to get the valid URL"},function(t,e,r){var i,a=this&&this.__extends||(i=function(t,e){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])})(t,e)},function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Class extends value "+String(e)+" is not a constructor or null");function r(){this.constructor=t}i(t,e),t.prototype=null===e?Object.create(e):(r.prototype=e.prototype,new r)}),o=this&&this.__awaiter||function(t,e,r,i){return new(r||(r=Promise))((function(a,o){function n(t){try{s(i.next(t))}catch(t){o(t)}}function l(t){try{s(i.throw(t))}catch(t){o(t)}}function s(t){var e;t.done?a(t.value):(e=t.value,e instanceof r?e:new r((function(t){t(e)}))).then(n,l)}s((i=i.apply(t,e||[])).next())}))},n=this&&this.__generator||function(t,e){var r,i,a,o,n={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]};return o={next:l(0),throw:l(1),return:l(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function l(o){return function(l){return function(o){if(r)throw new TypeError("Generator is already executing.");for(;n;)try{if(r=1,i&&(a=2&o[0]?i.return:o[0]?i.throw||((a=i.return)&&a.call(i),0):i.next)&&!(a=a.call(i,o[1])).done)return a;switch(i=0,a&&(o=[2&o[0],a.value]),o[0]){case 0:case 1:a=o;break;case 4:return n.label++,{value:o[1],done:!1};case 5:n.label++,i=o[1],o=[0];continue;case 7:o=n.ops.pop(),n.trys.pop();continue;default:if(!(a=n.trys,(a=a.length>0&&a[a.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!a||o[1]>a[0]&&o[1]0&&a[a.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!a||o[1]>a[0]&&o[1]0&&a[a.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!a||o[1]>a[0]&&o[1]0&&a[a.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!a||o[1]>a[0]&&o[1]0&&a[a.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!a||o[1]>a[0]&&o[1]0&&a[a.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!a||o[1]>a[0]&&o[1]0&&a[a.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!a||o[1]>a[0]&&o[1]0&&a[a.length-1])||6!==o[0]&&2!==o[0])){n=0;continue}if(3===o[0]&&(!a||o[1]>a[0]&&o[1]2&&"[]"===n.slice(l-2)&&(s=!0,r[n=n.slice(0,l-2)]||(r[n]=[])),i=o[1]?m(o[1]):""),s?r[n].push(i):r[n]=i}return r},recognize:function(t){var e,r,a,i=[this.rootState],o={},n=!1;if(-1!==(a=t.indexOf("?"))){var l=t.substr(a+1,t.length);t=t.substr(0,a),o=this.parseQueryString(l)}for("/"!==(t=decodeURI(t)).charAt(0)&&(t="/"+t),(e=t.length)>1&&"/"===t.charAt(e-1)&&(t=t.substr(0,e-1),n=!0),r=0;r2&&"[]"===n.slice(l-2)&&(s=!0,r[n=n.slice(0,l-2)]||(r[n]=[])),a=o[1]?V(o[1]):""),s?r[n].push(a):r[n]=a}return r},recognize:function(t){var e,r,i,a=[this.rootState],o={},n=!1;if(-1!==(i=t.indexOf("?"))){var l=t.substr(i+1,t.length);t=t.substr(0,i),o=this.parseQueryString(l)}for("/"!==(t=decodeURI(t)).charAt(0)&&(t="/"+t),(e=t.length)>1&&"/"===t.charAt(e-1)&&(t=t.substr(0,e-1),n=!0),r=0;r; + private operator: BasicFilterOperators; + private isRequireSingleSelection = false; + + /** + * Sets In as operator for Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().in([values]); + * ``` + * + * @returns {BasicFilterBuilder} + */ + in(values: Array<(string | number | boolean)>): BasicFilterBuilder { + this.operator = "In"; + this.values = values; + return this; + } + + /** + * Sets NotIn as operator for Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().notIn([values]); + * ``` + * + * @returns {BasicFilterBuilder} + */ + notIn(values: Array<(string | number | boolean)>): BasicFilterBuilder { + this.operator = "NotIn"; + this.values = values; + return this; + } + + /** + * Sets All as operator for Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().all(); + * ``` + * + * @returns {BasicFilterBuilder} + */ + all(): BasicFilterBuilder { + this.operator = "All"; + this.values = []; + return this; + } + + /** + * Sets required single selection property for Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().requireSingleSelection(isRequireSingleSelection); + * ``` + * + * @returns {BasicFilterBuilder} + */ + requireSingleSelection(isRequireSingleSelection = false): BasicFilterBuilder { + this.isRequireSingleSelection = isRequireSingleSelection; + return this; + } + + /** + * Creates Basic filter + * + * ```javascript + * + * const basicFilterBuilder = new BasicFilterBuilder().build(); + * ``` + * + * @returns {BasicFilter} + */ + build(): BasicFilter { + const basicFilter = new BasicFilter(this.target, this.operator, this.values); + basicFilter.requireSingleSelection = this.isRequireSingleSelection; + return basicFilter; + } +} diff --git a/src/FilterBuilders/filterBuilder.ts b/src/FilterBuilders/filterBuilder.ts new file mode 100644 index 00000000..660b7821 --- /dev/null +++ b/src/FilterBuilders/filterBuilder.ts @@ -0,0 +1,103 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { IFilterTarget } from "powerbi-models"; + +/** + * Generic filter builder for BasicFilter, AdvancedFilter, RelativeDate, RelativeTime and TopN + * + * @class + */ +export class FilterBuilder { + + public target: IFilterTarget; + + /** + * Sets target property for filter with target object + * + * ```javascript + * const target = { + * table: 'table1', + * column: 'column1' + * }; + * + * const filterBuilder = new FilterBuilder().withTargetObject(target); + * ``` + * + * @returns {FilterBuilder} + */ + withTargetObject(target: IFilterTarget) { + this.target = target; + return this; + } + + /** + * Sets target property for filter with column target object + * + * ``` + * const filterBuilder = new FilterBuilder().withColumnTarget(tableName, columnName); + * ``` + * + * @returns {FilterBuilder} + */ + withColumnTarget(tableName: string, columnName: string) { + this.target = { table: tableName, column: columnName }; + return this; + } + + /** + * Sets target property for filter with measure target object + * + * ``` + * const filterBuilder = new FilterBuilder().withMeasureTarget(tableName, measure); + * ``` + * + * @returns {FilterBuilder} + */ + withMeasureTarget(tableName: string, measure: string) { + this.target = { table: tableName, measure: measure }; + return this; + } + + /** + * Sets target property for filter with hierarchy level target object + * + * ``` + * const filterBuilder = new FilterBuilder().withHierarchyLevelTarget(tableName, hierarchy, hierarchyLevel); + * ``` + * + * @returns {FilterBuilder} + */ + withHierarchyLevelTarget(tableName: string, hierarchy: string, hierarchyLevel: string) { + this.target = { table: tableName, hierarchy: hierarchy, hierarchyLevel: hierarchyLevel }; + return this; + } + + /** + * Sets target property for filter with column aggregation target object + * + * ``` + * const filterBuilder = new FilterBuilder().withColumnAggregation(tableName, columnName, aggregationFunction); + * ``` + * + * @returns {FilterBuilder} + */ + withColumnAggregation(tableName: string, columnName: string, aggregationFunction: string) { + this.target = { table: tableName, column: columnName, aggregationFunction: aggregationFunction }; + return this; + } + + /** + * Sets target property for filter with hierarchy level aggregation target object + * + * ``` + * const filterBuilder = new FilterBuilder().withHierarchyLevelAggregationTarget(tableName, hierarchy, hierarchyLevel, aggregationFunction); + * ``` + * + * @returns {FilterBuilder} + */ + withHierarchyLevelAggregationTarget(tableName: string, hierarchy: string, hierarchyLevel: string, aggregationFunction: string) { + this.target = { table: tableName, hierarchy: hierarchy, hierarchyLevel: hierarchyLevel, aggregationFunction: aggregationFunction }; + return this; + } +} diff --git a/src/FilterBuilders/index.ts b/src/FilterBuilders/index.ts new file mode 100644 index 00000000..d57029c4 --- /dev/null +++ b/src/FilterBuilders/index.ts @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +export { + BasicFilterBuilder +} from "./basicFilterBuilder"; +export { + AdvancedFilterBuilder +} from "./advancedFilterBuilder"; +export { + TopNFilterBuilder +} from "./topNFilterBuilder"; +export { + RelativeDateFilterBuilder +} from "./relativeDateFilterBuilder"; +export { + RelativeTimeFilterBuilder +} from "./relativeTimeFilterBuilder"; diff --git a/src/FilterBuilders/relativeDateFilterBuilder.ts b/src/FilterBuilders/relativeDateFilterBuilder.ts new file mode 100644 index 00000000..5f522e60 --- /dev/null +++ b/src/FilterBuilders/relativeDateFilterBuilder.ts @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { + RelativeDateFilter, + RelativeDateOperators, + RelativeDateFilterTimeUnit +} from "powerbi-models"; + +import { FilterBuilder } from './filterBuilder'; + +/** + * Power BI Relative Date filter builder component + * + * @export + * @class RelativeDateFilterBuilder + * @extends {FilterBuilder} + */ +export class RelativeDateFilterBuilder extends FilterBuilder { + + private operator: RelativeDateOperators; + private timeUnitsCount: number; + private timeUnitType: RelativeDateFilterTimeUnit; + private isTodayIncluded = true; + + /** + * Sets inLast as operator for Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().inLast(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeDateFilterBuilder} + */ + inLast(timeUnitsCount: number, timeUnitType: RelativeDateFilterTimeUnit): RelativeDateFilterBuilder { + this.operator = RelativeDateOperators.InLast; + this.timeUnitsCount = timeUnitsCount; + this.timeUnitType = timeUnitType; + return this; + } + + /** + * Sets inThis as operator for Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().inThis(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeDateFilterBuilder} + */ + inThis(timeUnitsCount: number, timeUnitType: RelativeDateFilterTimeUnit): RelativeDateFilterBuilder { + this.operator = RelativeDateOperators.InThis; + this.timeUnitsCount = timeUnitsCount; + this.timeUnitType = timeUnitType; + return this; + } + + /** + * Sets inNext as operator for Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().inNext(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeDateFilterBuilder} + */ + inNext(timeUnitsCount: number, timeUnitType: RelativeDateFilterTimeUnit): RelativeDateFilterBuilder { + this.operator = RelativeDateOperators.InNext; + this.timeUnitsCount = timeUnitsCount; + this.timeUnitType = timeUnitType; + return this; + } + + /** + * Sets includeToday for Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().includeToday(includeToday); + * ``` + * + * @param {boolean} includeToday - Denotes if today is included or not + * @returns {RelativeDateFilterBuilder} + */ + includeToday(includeToday: boolean): RelativeDateFilterBuilder { + this.isTodayIncluded = includeToday; + return this; + } + + /** + * Creates Relative Date filter + * + * ```javascript + * + * const relativeDateFilterBuilder = new RelativeDateFilterBuilder().build(); + * ``` + * + * @returns {RelativeDateFilter} + */ + build(): RelativeDateFilter { + const relativeDateFilter = new RelativeDateFilter(this.target, this.operator, this.timeUnitsCount, this.timeUnitType, this.isTodayIncluded); + return relativeDateFilter; + } +} diff --git a/src/FilterBuilders/relativeTimeFilterBuilder.ts b/src/FilterBuilders/relativeTimeFilterBuilder.ts new file mode 100644 index 00000000..ac3b6084 --- /dev/null +++ b/src/FilterBuilders/relativeTimeFilterBuilder.ts @@ -0,0 +1,96 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { + RelativeTimeFilter, + RelativeDateOperators, + RelativeDateFilterTimeUnit +} from "powerbi-models"; + +import { FilterBuilder } from './filterBuilder'; + +/** + * Power BI Relative Time filter builder component + * + * @export + * @class RelativeTimeFilterBuilder + * @extends {FilterBuilder} + */ +export class RelativeTimeFilterBuilder extends FilterBuilder { + + private operator: RelativeDateOperators; + private timeUnitsCount: number; + private timeUnitType: RelativeDateFilterTimeUnit; + + /** + * Sets inLast as operator for Relative Time filter + * + * ```javascript + * + * const relativeTimeFilterBuilder = new RelativeTimeFilterBuilder().inLast(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeTimeFilterBuilder} + */ + inLast(timeUnitsCount: number, timeUnitType: RelativeDateFilterTimeUnit): RelativeTimeFilterBuilder { + this.operator = RelativeDateOperators.InLast; + this.timeUnitsCount = timeUnitsCount; + this.timeUnitType = timeUnitType; + return this; + } + + /** + * Sets inThis as operator for Relative Time filter + * + * ```javascript + * + * const relativeTimeFilterBuilder = new RelativeTimeFilterBuilder().inThis(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeTimeFilterBuilder} + */ + inThis(timeUnitsCount: number, timeUnitType: RelativeDateFilterTimeUnit): RelativeTimeFilterBuilder { + this.operator = RelativeDateOperators.InThis; + this.timeUnitsCount = timeUnitsCount; + this.timeUnitType = timeUnitType; + return this; + } + + /** + * Sets inNext as operator for Relative Time filter + * + * ```javascript + * + * const relativeTimeFilterBuilder = new RelativeTimeFilterBuilder().inNext(timeUnitsCount, timeUnitType); + * ``` + * + * @param {number} timeUnitsCount - The amount of time units + * @param {RelativeDateFilterTimeUnit} timeUnitType - Defines the unit of time the filter is using + * @returns {RelativeTimeFilterBuilder} + */ + inNext(timeUnitsCount: number, timeUnitType: RelativeDateFilterTimeUnit): RelativeTimeFilterBuilder { + this.operator = RelativeDateOperators.InNext; + this.timeUnitsCount = timeUnitsCount; + this.timeUnitType = timeUnitType; + return this; + } + + /** + * Creates Relative Time filter + * + * ```javascript + * + * const relativeTimeFilterBuilder = new RelativeTimeFilterBuilder().build(); + * ``` + * + * @returns {RelativeTimeFilter} + */ + build(): RelativeTimeFilter { + const relativeTimeFilter = new RelativeTimeFilter(this.target, this.operator, this.timeUnitsCount, this.timeUnitType); + return relativeTimeFilter; + } +} diff --git a/src/FilterBuilders/topNFilterBuilder.ts b/src/FilterBuilders/topNFilterBuilder.ts new file mode 100644 index 00000000..7dae49be --- /dev/null +++ b/src/FilterBuilders/topNFilterBuilder.ts @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { + ITarget, + TopNFilter, + TopNFilterOperators +} from "powerbi-models"; + +import { FilterBuilder } from './filterBuilder'; + +/** + * Power BI Top N filter builder component + * + * @export + * @class TopNFilterBuilder + * @extends {FilterBuilder} + */ +export class TopNFilterBuilder extends FilterBuilder { + + private itemCount: number; + private operator: TopNFilterOperators; + private orderByTargetValue: ITarget; + + /** + * Sets Top as operator for Top N filter + * + * ```javascript + * + * const topNFilterBuilder = new TopNFilterBuilder().top(itemCount); + * ``` + * + * @returns {TopNFilterBuilder} + */ + top(itemCount: number): TopNFilterBuilder { + this.operator = "Top"; + this.itemCount = itemCount; + return this; + } + + /** + * Sets Bottom as operator for Top N filter + * + * ```javascript + * + * const topNFilterBuilder = new TopNFilterBuilder().bottom(itemCount); + * ``` + * + * @returns {TopNFilterBuilder} + */ + bottom(itemCount: number): TopNFilterBuilder { + this.operator = "Bottom"; + this.itemCount = itemCount; + return this; + } + + /** + * Sets order by for Top N filter + * + * ```javascript + * + * const topNFilterBuilder = new TopNFilterBuilder().orderByTarget(target); + * ``` + * + * @returns {TopNFilterBuilder} + */ + orderByTarget(target: ITarget): TopNFilterBuilder { + this.orderByTargetValue = target; + return this; + } + + /** + * Creates Top N filter + * + * ```javascript + * + * const topNFilterBuilder = new TopNFilterBuilder().build(); + * ``` + * + * @returns {TopNFilter} + */ + build(): TopNFilter { + const topNFilter = new TopNFilter(this.target, this.operator, this.itemCount, this.orderByTargetValue); + return topNFilter; + } +} diff --git a/src/config.ts b/src/config.ts index 587dbe38..eb5cbed4 100644 --- a/src/config.ts +++ b/src/config.ts @@ -3,7 +3,7 @@ /** @ignore *//** */ const config = { - version: '2.18.1', + version: '2.18.4', type: 'js' }; diff --git a/src/embed.ts b/src/embed.ts index 465c2596..ef1d822f 100644 --- a/src/embed.ts +++ b/src/embed.ts @@ -2,10 +2,10 @@ // Licensed under the MIT License. import * as models from 'powerbi-models'; -import { addParamToUrl, assign, autoAuthInEmbedUrl, createRandomString, getTimeDiffInMilliseconds, remove } from './util'; -import { Service, IEventHandler, IEvent, ICustomEvent } from './service'; import * as sdkConfig from './config'; import { EmbedUrlNotSupported } from './errors'; +import { ICustomEvent, IEvent, IEventHandler, Service } from './service'; +import { addParamToUrl, assign, autoAuthInEmbedUrl, createRandomString, getTimeDiffInMilliseconds, remove } from './util'; declare global { interface Document { @@ -91,6 +91,15 @@ export abstract class Embed { /** @hidden */ allowedEvents: string[] = []; + /** @hidden */ + protected commands: models.ICommandExtension[]; + + /** @hidden */ + protected initialLayoutType: models.LayoutType; + + /** @hidden */ + groups: models.IMenuGroupExtension[]; + /** * Gets or sets the event handler registered for this embed component. * @@ -215,13 +224,18 @@ export abstract class Embed { this.iframe = iframe; this.iframeLoaded = false; this.embedtype = config.type.toLowerCase(); + this.commands = []; + this.groups = []; + + const registerQueryCallback = !!(config).eventHooks?.applicationContextProvider; + delete (config).eventHooks; this.populateConfig(config, isBootstrap); if (this.embedtype === 'create') { - this.setIframe(false /* set EventListener to call create() on 'load' event*/, phasedRender, isBootstrap); + this.setIframe(false /* set EventListener to call create() on 'load' event*/, phasedRender, isBootstrap, registerQueryCallback); } else { - this.setIframe(true /* set EventListener to call load() on 'load' event*/, phasedRender, isBootstrap); + this.setIframe(true /* set EventListener to call load() on 'load' event*/, phasedRender, isBootstrap, registerQueryCallback); } } @@ -505,6 +519,17 @@ export abstract class Embed { this.config.groupId = this.getGroupId(); this.addLocaleToEmbedUrl(config); this.config.uniqueId = this.getUniqueId(); + const extensions = this.config?.settings?.extensions as models.IExtensions; + this.commands = extensions?.commands ?? []; + this.groups = extensions?.groups ?? []; + this.initialLayoutType = this.config?.settings?.layoutType ?? models.LayoutType.Master; + + // Adding commands in extensions array to this.commands + const extensionsArray = this.config?.settings?.extensions as models.IExtension[]; + if (Array.isArray(extensionsArray)) { + this.commands = []; + extensionsArray.map((extension: models.IExtension) => { if (extension?.command) { this.commands.push(extension.command) } }); + } if (isBootstrap) { // save current config in bootstrapConfig to be able to merge it on next call to powerbi.embed @@ -680,10 +705,14 @@ export abstract class Embed { * * @hidden */ - private setIframe(isLoad: boolean, phasedRender?: boolean, isBootstrap?: boolean): void { + private setIframe(isLoad: boolean, phasedRender?: boolean, isBootstrap?: boolean, registerQueryCallback?: boolean): void { if (!this.iframe) { const iframeContent = document.createElement("iframe"); - const embedUrl = this.config.uniqueId ? addParamToUrl(this.config.embedUrl, 'uid', this.config.uniqueId) : this.config.embedUrl; + let embedUrl = this.config.uniqueId ? addParamToUrl(this.config.embedUrl, 'uid', this.config.uniqueId) : this.config.embedUrl; + + if (!isBootstrap && registerQueryCallback) + embedUrl = addParamToUrl(embedUrl, "registerQueryCallback", "true"); + iframeContent.style.width = '100%'; iframeContent.style.height = '100%'; iframeContent.setAttribute("src", embedUrl); diff --git a/src/page.ts b/src/page.ts index 8eaf7ada..b4f48a10 100644 --- a/src/page.ts +++ b/src/page.ts @@ -3,6 +3,7 @@ import { IHttpPostMessageResponse } from 'http-post-message'; import { + CommonErrorCodes, DisplayOption, FiltersOperations, ICustomPageSize, @@ -12,10 +13,12 @@ import { IVisual, LayoutType, PageLevelFilters, - SectionVisibility + PageSizeType, + SectionVisibility, + VisualContainerDisplayMode } from 'powerbi-models'; import { IFilterable } from './ifilterable'; -import { IReportNode } from './report'; +import { IReportNode, Report } from './report'; import { VisualDescriptor } from './visualDescriptor'; import { isRDLEmbed } from './util'; import { APINotSupportedForRDLError } from './errors'; @@ -83,6 +86,13 @@ export class Page implements IPageNode, IFilterable { */ defaultSize: ICustomPageSize; + /** + * Mobile view page size (if defined) as saved in the report. + * + * @type {ICustomPageSize} + */ + mobileSize: ICustomPageSize; + /** * Page display options as saved in the report. * @@ -100,13 +110,14 @@ export class Page implements IPageNode, IFilterable { * @param {SectionVisibility} [visibility] * @hidden */ - constructor(report: IReportNode, name: string, displayName?: string, isActivePage?: boolean, visibility?: SectionVisibility, defaultSize?: ICustomPageSize, defaultDisplayOption?: DisplayOption) { + constructor(report: IReportNode, name: string, displayName?: string, isActivePage?: boolean, visibility?: SectionVisibility, defaultSize?: ICustomPageSize, defaultDisplayOption?: DisplayOption, mobileSize?: ICustomPageSize) { this.report = report; this.name = name; this.displayName = displayName; this.isActive = isActivePage; this.visibility = visibility; this.defaultSize = defaultSize; + this.mobileSize = mobileSize; this.defaultDisplayOption = defaultDisplayOption; } @@ -273,6 +284,142 @@ export class Page implements IPageNode, IFilterable { } } + /** + * Gets a visual by name on the page. + * + * ```javascript + * page.getVisualByName(visualName: string) + * .then(visual => { + * ... + * }); + * ``` + * + * @param {string} visualName + * @returns {Promise} + */ + async getVisualByName(visualName: string): Promise { + if (isRDLEmbed(this.report.config.embedUrl)) { + return Promise.reject(APINotSupportedForRDLError); + } + + try { + const response = await this.report.service.hpm.get(`/report/pages/${this.name}/visuals`, { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow); + const visual = response.body.find((v: IVisual) => v.name === visualName); + if (!visual) { + return Promise.reject(CommonErrorCodes.NotFound); + } + + return new VisualDescriptor(this, visual.name, visual.title, visual.type, visual.layout); + } catch (response) { + throw response.body; + } + } + + /** + * Updates the display state of a visual in a page. + * + * ```javascript + * page.setVisualDisplayState(visualName, displayState) + * .catch(error => { ... }); + * ``` + * + * @param {string} visualName + * @param {VisualContainerDisplayMode} displayState + * @returns {Promise>} + */ + async setVisualDisplayState(visualName: string, displayState: VisualContainerDisplayMode): Promise> { + const pageName = this.name; + const report = this.report as Report; + return report.setVisualDisplayState(pageName, visualName, displayState); + } + + /** + * Updates the position of a visual in a page. + * + * ```javascript + * page.moveVisual(visualName, x, y, z) + * .catch(error => { ... }); + * ``` + * + * @param {string} visualName + * @param {number} x + * @param {number} y + * @param {number} z + * @returns {Promise>} + */ + async moveVisual(visualName: string, x: number, y: number, z?: number): Promise> { + const pageName = this.name; + const report = this.report as Report; + return report.moveVisual(pageName, visualName, x, y, z); + } + + /** + * Resize a visual in a page. + * + * ```javascript + * page.resizeVisual(visualName, width, height) + * .catch(error => { ... }); + * ``` + * + * @param {string} visualName + * @param {number} width + * @param {number} height + * @returns {Promise>} + */ + async resizeVisual(visualName: string, width: number, height: number): Promise> { + const pageName = this.name; + const report = this.report as Report; + return report.resizeVisual(pageName, visualName, width, height); + } + + /** + * Updates the size of active page. + * + * ```javascript + * page.resizePage(pageSizeType, width, height) + * .catch(error => { ... }); + * ``` + * + * @param {PageSizeType} pageSizeType + * @param {number} width + * @param {number} height + * @returns {Promise>} + */ + async resizePage(pageSizeType: PageSizeType, width?: number, height?: number): Promise> { + if (!this.isActive) { + return Promise.reject('Cannot resize the page. Only the active page can be resized'); + } + const report = this.report as Report; + return report.resizeActivePage(pageSizeType, width, height); + } + + /** + * Gets the list of slicer visuals on the page. + * + * ```javascript + * page.getSlicers() + * .then(slicers => { + * ... + * }); + * ``` + * + * @returns {Promise} + */ + async getSlicers(): Promise { + if (isRDLEmbed(this.report.config.embedUrl)) { + return Promise.reject(APINotSupportedForRDLError); + } + + try { + const response = await this.report.service.hpm.get(`/report/pages/${this.name}/visuals`, { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow); + return response.body + .filter((visual: IVisual) => visual.type === 'slicer') + .map((visual: IVisual) => new VisualDescriptor(this, visual.name, visual.title, visual.type, visual.layout)); + } catch (response) { + throw response.body; + } + } + /** * Checks if page has layout. * diff --git a/src/powerbi-client.ts b/src/powerbi-client.ts index a2c1e662..bcaf2f21 100644 --- a/src/powerbi-client.ts +++ b/src/powerbi-client.ts @@ -48,6 +48,13 @@ export { export { VisualDescriptor } from './visualDescriptor'; +export { + BasicFilterBuilder, + AdvancedFilterBuilder, + TopNFilterBuilder, + RelativeDateFilterBuilder, + RelativeTimeFilterBuilder +} from './FilterBuilders'; declare var powerbi: service.Service; declare global { diff --git a/src/report.ts b/src/report.ts index 076d4ebc..93a67b7c 100644 --- a/src/report.ts +++ b/src/report.ts @@ -18,7 +18,18 @@ import { ViewMode, IEmbedConfiguration, IEmbedConfigurationBase, - ReportLevelFilters + CommonErrorCodes, + ReportLevelFilters, + MenuLocation, + ICommandExtension, + IExtensions, + IFlatMenuExtension, + IGroupedMenuExtension, + IExtension, + IVisualLayout, + ICustomPageSize, + PageSizeType, + VisualContainerDisplayMode } from 'powerbi-models'; import { IHttpPostMessageResponse } from 'http-post-message'; import { IService, Service } from './service'; @@ -28,6 +39,7 @@ import { APINotSupportedForRDLError } from './errors'; import { IFilterable } from './ifilterable'; import { Page } from './page'; import { BookmarksManager } from './bookmarksManager'; +import { VisualDescriptor } from './visualDescriptor'; /** * A Report node within a report hierarchy @@ -52,7 +64,7 @@ export interface IReportNode { */ export class Report extends Embed implements IReportNode, IFilterable { /** @hidden */ - static allowedEvents = ["filtersApplied", "pageChanged", "commandTriggered", "swipeStart", "swipeEnd", "bookmarkApplied", "dataHyperlinkClicked", "visualRendered", "visualClicked", "selectionChanged"]; + static allowedEvents = ["filtersApplied", "pageChanged", "commandTriggered", "swipeStart", "swipeEnd", "bookmarkApplied", "dataHyperlinkClicked", "visualRendered", "visualClicked", "selectionChanged", "renderingStarted"]; /** @hidden */ static reportIdAttribute = 'powerbi-report-id'; /** @hidden */ @@ -331,7 +343,83 @@ export class Report extends Embed implements IReportNode, IFilterable { try { const response = await this.service.hpm.get('/report/pages', { uid: this.config.uniqueId }, this.iframe.contentWindow); return response.body - .map((page) => new Page(this, page.name, page.displayName, page.isActive, page.visibility, page.defaultSize, page.defaultDisplayOption)); + .map((page) => new Page(this, page.name, page.displayName, page.isActive, page.visibility, page.defaultSize, page.defaultDisplayOption, page.mobileSize)); + } catch (response) { + throw response.body; + } + } + + /** + * Gets a report page by its name. + * + * ```javascript + * report.getPageByName(pageName) + * .then(page => { + * ... + * }); + * ``` + * + * @param {string} pageName + * @returns {Promise} + */ + async getPageByName(pageName: string): Promise { + if (isRDLEmbed(this.config.embedUrl)) { + return Promise.reject(APINotSupportedForRDLError); + } + + try { + const response = await this.service.hpm.get(`/report/pages`, { uid: this.config.uniqueId }, this.iframe.contentWindow); + const page = response.body.find((p: IPage) => p.name === pageName); + + if (!page) { + return Promise.reject(CommonErrorCodes.NotFound); + } + + return new Page( + this, + page.name, + page.displayName, + page.isActive, + page.visibility, + page.defaultSize, + page.defaultDisplayOption, + page.mobileSize + ); + } catch (response) { + throw response.body; + } + } + + /** + * Gets the active report page. + * + * ```javascript + * report.getActivePage() + * .then(activePage => { + * ... + * }); + * ``` + * + * @returns {Promise} + */ + async getActivePage(): Promise { + if (isRDLEmbed(this.config.embedUrl)) { + return Promise.reject(APINotSupportedForRDLError); + } + try { + const response = await this.service.hpm.get('/report/pages', { uid: this.config.uniqueId }, this.iframe.contentWindow); + const activePage = response.body.find((page: IPage) => page.isActive); + + return new Page( + this, + activePage.name, + activePage.displayName, + activePage.isActive, + activePage.visibility, + activePage.defaultSize, + activePage.defaultDisplayOption, + activePage.mobileSize + ); } catch (response) { throw response.body; } @@ -426,7 +514,21 @@ export class Report extends Embed implements IReportNode, IFilterable { } try { - return await this.service.hpm.patch('/report/settings', settings, { uid: this.config.uniqueId }, this.iframe.contentWindow); + const response = await this.service.hpm.patch('/report/settings', settings, { uid: this.config.uniqueId }, this.iframe.contentWindow); + + // Update commands if provided + const extension = settings?.extensions as IExtensions; + this.commands = extension?.commands ?? this.commands; + this.groups = extension?.groups ?? this.groups; + + // Adding commands in extensions array to this.commands + const extensionsArray = settings?.extensions as IExtension[]; + if (Array.isArray(extensionsArray)) { + this.commands = []; + extensionsArray.map((extensionElement: IExtension) => { if (extensionElement?.command) { this.commands.push(extensionElement.command); } }); + } + + return response; } catch (response) { throw response.body; } @@ -617,6 +719,364 @@ export class Report extends Embed implements IReportNode, IFilterable { } } + /** + * Remove context menu extension command. + * + * ```javascript + * report.removeContextMenuCommand(commandName, contextMenuTitle) + * .catch(error => { + * ... + * }); + * ``` + * + * @param {string} commandName + * @param {string} contextMenuTitle + * @returns {Promise>} + */ + async removeContextMenuCommand(commandName: string, contextMenuTitle: string): Promise> { + if (isRDLEmbed(this.config.embedUrl)) { + return Promise.reject(APINotSupportedForRDLError); + } + + const commandCopy: ICommandExtension[] = JSON.parse(JSON.stringify(this.commands)); + const indexOfCommand: number = this.findCommandMenuIndex("visualContextMenu", commandCopy, commandName, contextMenuTitle); + if (indexOfCommand === -1) { + throw CommonErrorCodes.NotFound; + } + + // Delete the context menu and not the entire command, since command can have option menu as well. + delete commandCopy[indexOfCommand].extend.visualContextMenu; + const newSetting: ISettings = { + extensions: { + commands: commandCopy, + groups: this.groups + } + }; + return await this.updateSettings(newSetting); + } + + /** + * Add context menu extension command. + * + * ```javascript + * report.addContextMenuCommand(commandName, commandTitle, contextMenuTitle, menuLocation, visualName, visualType, groupName) + * .catch(error => { + * ... + * }); + * ``` + * + * @param {string} commandName + * @param {string} commandTitle + * @param {string} contextMenuTitle + * @param {MenuLocation} menuLocation + * @param {string} visualName + * @param {string} visualType + * @param {string} groupName + * @returns {Promise>} + */ + async addContextMenuCommand(commandName: string, commandTitle: string, contextMenuTitle: string = commandTitle, menuLocation: MenuLocation = MenuLocation.Bottom, visualName: string = undefined, visualType: string, groupName: string = undefined): Promise> { + if (isRDLEmbed(this.config.embedUrl)) { + return Promise.reject(APINotSupportedForRDLError); + } + + const newCommands: ICommandExtension[] = this.createMenuCommand("visualContextMenu", commandName, commandTitle, contextMenuTitle, menuLocation, visualName, visualType, groupName); + const newSetting: ISettings = { + extensions: { + commands: newCommands, + groups: this.groups + } + }; + return await this.updateSettings(newSetting); + } + + /** + * Remove options menu extension command. + * + * ```javascript + * report.removeOptionsMenuCommand(commandName, optionsMenuTitle) + * .then({ + * ... + * }); + * ``` + * + * @param {string} commandName + * @param {string} optionsMenuTitle + * @returns {Promise>} + */ + async removeOptionsMenuCommand(commandName: string, optionsMenuTitle: string): Promise> { + if (isRDLEmbed(this.config.embedUrl)) { + return Promise.reject(APINotSupportedForRDLError); + } + + const commandCopy: ICommandExtension[] = JSON.parse(JSON.stringify(this.commands)); + const indexOfCommand: number = this.findCommandMenuIndex("visualOptionsMenu", commandCopy, commandName, optionsMenuTitle); + + if (indexOfCommand === -1) { + throw CommonErrorCodes.NotFound; + } + + // Delete the context options and not the entire command, since command can have context menu as well. + delete commandCopy[indexOfCommand].extend.visualOptionsMenu; + delete commandCopy[indexOfCommand].icon; + const newSetting: ISettings = { + extensions: { + commands: commandCopy, + groups: this.groups + } + }; + return await this.updateSettings(newSetting); + } + + /** + * Add options menu extension command. + * + * ```javascript + * report.addOptionsMenuCommand(commandName, commandTitle, optionsMenuTitle, menuLocation, visualName, visualType, groupName, commandIcon) + * .catch(error => { + * ... + * }); + * ``` + * + * @param {string} commandName + * @param {string} commandTitle + * @param {string} optionMenuTitle + * @param {MenuLocation} menuLocation + * @param {string} visualName + * @param {string} visualType + * @param {string} groupName + * @param {string} commandIcon + * @returns {Promise>} + */ + async addOptionsMenuCommand(commandName: string, commandTitle: string, optionsMenuTitle: string = commandTitle, menuLocation: MenuLocation = MenuLocation.Bottom, visualName: string = undefined, visualType: string = undefined, groupName: string = undefined, commandIcon: string = undefined): Promise> { + if (isRDLEmbed(this.config.embedUrl)) { + return Promise.reject(APINotSupportedForRDLError); + } + + const newCommands: ICommandExtension[] = this.createMenuCommand("visualOptionsMenu", commandName, commandTitle, optionsMenuTitle, menuLocation, visualName, visualType, groupName, commandIcon); + const newSetting: ISettings = { + extensions: { + commands: newCommands, + groups: this.groups + } + }; + return await this.updateSettings(newSetting); + } + + /** + * Updates the display state of a visual in a page. + * + * ```javascript + * report.setVisualDisplayState(pageName, visualName, displayState) + * .catch(error => { ... }); + * ``` + * + * @param {string} pageName + * @param {string} visualName + * @param {VisualContainerDisplayMode} displayState + * @returns {Promise>} + */ + async setVisualDisplayState(pageName: string, visualName: string, displayState: VisualContainerDisplayMode): Promise> { + // Check if page name and visual name are valid + await this.validateVisual(pageName, visualName); + const visualLayout: IVisualLayout = { + displayState: { + mode: displayState + } + }; + + // Get new Settings object with updated visual layout + const newSettings = this.buildLayoutSettingsObject(pageName, visualName, visualLayout); + return this.updateSettings(newSettings); + } + + /** + * Resize a visual in a page. + * + * ```javascript + * report.resizeVisual(pageName, visualName, width, height) + * .catch(error => { ... }); + * ``` + * + * @param {string} pageName + * @param {string} visualName + * @param {number} width + * @param {number} height + * @returns {Promise>} + */ + async resizeVisual(pageName: string, visualName: string, width: number, height: number): Promise> { + // Check if page name and visual name are valid + await this.validateVisual(pageName, visualName); + const visualLayout: IVisualLayout = { + width: width, + height: height, + }; + + // Get new Settings object with updated visual layout + const newSettings = this.buildLayoutSettingsObject(pageName, visualName, visualLayout); + return this.updateSettings(newSettings); + } + + /** + * Updates the size of active page in report. + * + * ```javascript + * report.resizeActivePage(pageSizeType, width, height) + * .catch(error => { ... }); + * ``` + * + * @param {PageSizeType} pageSizeType + * @param {number} width + * @param {number} height + * @returns {Promise>} + */ + async resizeActivePage(pageSizeType: PageSizeType, width?: number, height?: number): Promise> { + const pageSize: ICustomPageSize = { + type: pageSizeType, + width: width, + height: height + }; + + // Create new settings object with custom layout type + const newSettings: ISettings = { + layoutType: LayoutType.Custom, + customLayout: { + pageSize: pageSize + } + }; + return this.updateSettings(newSettings); + } + + /** + * Updates the position of a visual in a page. + * + * ```javascript + * report.moveVisual(pageName, visualName, x, y, z) + * .catch(error => { ... }); + * ``` + * + * @param {string} pageName + * @param {string} visualName + * @param {number} x + * @param {number} y + * @param {number} z + * @returns {Promise>} + */ + async moveVisual(pageName: string, visualName: string, x: number, y: number, z?: number): Promise> { + // Check if page name and visual name are valid + await this.validateVisual(pageName, visualName); + const visualLayout: IVisualLayout = { + x: x, + y: y, + z: z + }; + + // Get new Settings object with updated visual layout + const newSettings = this.buildLayoutSettingsObject(pageName, visualName, visualLayout); + return this.updateSettings(newSettings); + } + + /** + * Updates the report layout + * + * ```javascript + * report.switchLayout(layoutType); + * ``` + * + * @param {LayoutType} layoutType + * @returns {Promise>} + */ + async switchLayout(layoutType: LayoutType): Promise> { + const isInitialMobileSettings = this.isMobileSettings({ layoutType: this.initialLayoutType }); + const isPassedMobileSettings = this.isMobileSettings({ layoutType: layoutType }); + + // Check if both passed layout and initial layout are of same type. + if (isInitialMobileSettings !== isPassedMobileSettings) { + throw "Switching between mobile and desktop layouts is not supported. Please reset the embed container and re-embed with required layout."; + } + + const newSetting: ISettings = { + layoutType: layoutType + }; + const response = await this.updateSettings(newSetting); + this.initialLayoutType = layoutType; + return response; + } + + /** + * @hidden + */ + private createMenuCommand(type: string, commandName: string, commandTitle: string, menuTitle: string, menuLocation: MenuLocation, visualName: string, visualType: string, groupName: string, icon?: string): ICommandExtension[] { + const newCommandObj: ICommandExtension = { + name: commandName, + title: commandTitle, + extend: { + } + }; + + newCommandObj.extend[type] = { + title: menuTitle, + menuLocation: menuLocation, + }; + if (type === "visualOptionsMenu") { + newCommandObj.icon = icon; + } + if (groupName) { + const extend = newCommandObj.extend[type] as IFlatMenuExtension; + delete extend.menuLocation; + const groupExtend = newCommandObj.extend[type] as IGroupedMenuExtension; + groupExtend.groupName = groupName; + } + if (visualName) { + newCommandObj.selector = { + $schema: "http://powerbi.com/product/schema#visualSelector", + visualName: visualName + }; + } + if (visualType) { + newCommandObj.selector = { + $schema: "http://powerbi.com/product/schema#visualTypeSelector", + visualType: visualType + }; + } + return [...this.commands, newCommandObj]; + } + + /** + * @hidden + */ + private findCommandMenuIndex(type: string, commands: ICommandExtension[], commandName: string, menuTitle: string): number { + let indexOfCommand = -1; + commands.some((activeMenuCommand, index) => + (activeMenuCommand.name === commandName && activeMenuCommand.extend[type] && activeMenuCommand.extend[type].title === menuTitle) ? (indexOfCommand = index, true) : false); + return indexOfCommand; + } + + /** + * @hidden + */ + private buildLayoutSettingsObject(pageName: string, visualName: string, visualLayout: IVisualLayout): ISettings { + // Create new settings object with custom layout type + const newSettings: ISettings = { + layoutType: LayoutType.Custom, + customLayout: { + pagesLayout: {} + } + }; + newSettings.customLayout.pagesLayout[pageName] = { + visualsLayout: {} + }; + newSettings.customLayout.pagesLayout[pageName].visualsLayout[visualName] = visualLayout; + return newSettings; + } + + /** + * @hidden + */ + private async validateVisual(pageName: string, visualName: string): Promise { + const page = await this.getPageByName(pageName); + return await page.getVisualByName(visualName); + } + /** * @hidden */ diff --git a/src/service.ts b/src/service.ts index 234c4fdf..563cc17d 100644 --- a/src/service.ts +++ b/src/service.ts @@ -300,6 +300,7 @@ export class Service implements IService { * @returns {Embed} */ embed(element: HTMLElement, config: IComponentEmbedConfiguration | IEmbedConfigurationBase = {}): Embed { + this.registerApplicationContextHook(config as IEmbedConfiguration); return this.embedInternal(element, config); } @@ -314,6 +315,7 @@ export class Service implements IService { * @returns {Embed} */ load(element: HTMLElement, config: IComponentEmbedConfiguration | IEmbedConfigurationBase = {}): Embed { + this.registerApplicationContextHook(config as IEmbedConfiguration); return this.embedInternal(element, config, /* phasedRender */ true, /* isBootstrap */ false); } @@ -440,6 +442,30 @@ export class Service implements IService { return component; } + /** + * @hidden + */ + private registerApplicationContextHook(config: IEmbedConfiguration): void { + const applicationContextProvider = config?.eventHooks?.applicationContextProvider; + if (!applicationContextProvider) { + return; + } + + if (typeof applicationContextProvider !== 'function') { + throw new Error("applicationContextProvider must be a function"); + } + + this.router.post(`preQuery`, async (req, _res) => { + try { + let result = await applicationContextProvider(req.body); + _res.send(200, result); + } catch (error) { + _res.send(400, null); + console.error(error); + } + }); + } + /** * Adds an event handler for DOMContentLoaded, which searches the DOM for elements that have the 'powerbi-embed-url' attribute, * and automatically attempts to embed a powerbi component based on information from other powerbi-* attributes. diff --git a/src/visualDescriptor.ts b/src/visualDescriptor.ts index ed1315e3..27f3c1e3 100644 --- a/src/visualDescriptor.ts +++ b/src/visualDescriptor.ts @@ -13,11 +13,13 @@ import { ISortByVisualRequest, IUpdateFiltersRequest, IVisualLayout, + VisualContainerDisplayMode, VisualLevelFilters } from 'powerbi-models'; import { IHttpPostMessageResponse } from 'http-post-message'; import { IFilterable } from './ifilterable'; import { IPageNode } from './page'; +import { Report } from './report'; /** * A Visual node within a report hierarchy @@ -258,4 +260,63 @@ export class VisualDescriptor implements IVisualNode, IFilterable { throw response.body; } } + + /** + * Updates the position of a visual. + * + * ```javascript + * visual.moveVisual(x, y, z) + * .catch(error => { ... }); + * ``` + * + * @param {number} x + * @param {number} y + * @param {number} z + * @returns {Promise>} + */ + async moveVisual(x: number, y: number, z?: number): Promise> { + const pageName = this.page.name; + const visualName = this.name; + const report = this.page.report as Report; + return report.moveVisual(pageName, visualName, x, y, z); + } + + /** + * Updates the display state of a visual. + * + * ```javascript + * visual.setVisualDisplayState(displayState) + * .catch(error => { ... }); + * ``` + * + * @param {VisualContainerDisplayMode} displayState + * @returns {Promise>} + */ + async setVisualDisplayState(displayState: VisualContainerDisplayMode): Promise> { + const pageName = this.page.name; + const visualName = this.name; + const report = this.page.report as Report; + + return report.setVisualDisplayState(pageName, visualName, displayState); + } + + /** + * Resize a visual. + * + * ```javascript + * visual.resizeVisual(width, height) + * .catch(error => { ... }); + * ``` + * + * @param {number} width + * @param {number} height + * @returns {Promise>} + */ + async resizeVisual(width: number, height: number): Promise> { + const pageName = this.page.name; + const visualName = this.name; + const report = this.page.report as Report; + + return report.resizeVisual(pageName, visualName, width, height); + } } diff --git a/test/filterBuilders.spec.ts b/test/filterBuilders.spec.ts new file mode 100644 index 00000000..fbc88798 --- /dev/null +++ b/test/filterBuilders.spec.ts @@ -0,0 +1,677 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { BasicFilterBuilder, AdvancedFilterBuilder, TopNFilterBuilder, RelativeDateFilterBuilder, RelativeTimeFilterBuilder } from '../src/FilterBuilders'; +import * as models from 'powerbi-models'; + +describe('filter builders', function () { + const target: models.IFilterTarget = { + table: 'table1', + column: 'column1' + }; + const measureTarget: models.IMeasureTarget = { + table: 'table', + measure: 'measure' + }; + const columnTarget: models.IColumnTarget = { + table: 'table', + column: 'column' + }; + const hierarchyLevelTarget: models.IHierarchyLevelTarget = { + table: 'table', + hierarchy: 'hierarchy', + hierarchyLevel: 'hierarchy level name', + }; + const columnAggregationTarget: models.IColumnAggrTarget = { + table: 'table', + column: 'column', + aggregationFunction: 'Avg' + }; + const hierarchyLevelAggregationTarget: models.IHierarchyLevelAggrTarget = { + table: 'table', + hierarchy: 'hierarchy', + hierarchyLevel: 'hierarchy level name', + aggregationFunction: 'Avg' + }; + + describe('Basic filter builder', function () { + it('validates Basic filter with target object', function () { + // Arrange + const values = [1, 2, 3]; + const operator: models.BasicFilterOperators = 'In'; + const basicFilter: models.BasicFilter = new models.BasicFilter(target, operator, values); + basicFilter.requireSingleSelection = false; + + // Act + const basicFilterWithBuilder: models.BasicFilter = new BasicFilterBuilder() + .withTargetObject(target) + .in(values) + .build(); + + // Assert + expect(basicFilterWithBuilder).toBeDefined(); + expect(basicFilterWithBuilder).toEqual(basicFilter); + }); + + it('validates Basic filter with column target object', function () { + // Arrange + const values = [1, 2, 3]; + const operator: models.BasicFilterOperators = 'In'; + const basicFilter: models.BasicFilter = new models.BasicFilter(columnTarget, operator, values); + basicFilter.requireSingleSelection = false; + + // Act + const basicFilterWithBuilder: models.BasicFilter = new BasicFilterBuilder() + .withColumnTarget('table', 'column') + .in(values) + .build(); + + // Assert + expect(basicFilterWithBuilder).toBeDefined(); + expect(basicFilterWithBuilder).toEqual(basicFilter); + }); + + it('validates Basic filter with measure target object', function () { + // Arrange + const values = [1, 2, 3]; + const operator: models.BasicFilterOperators = 'In'; + const basicFilter: models.BasicFilter = new models.BasicFilter(measureTarget, operator, values); + basicFilter.requireSingleSelection = false; + + // Act + const basicFilterWithBuilder: models.BasicFilter = new BasicFilterBuilder() + .withMeasureTarget('table', 'measure') + .in(values) + .build(); + + // Assert + expect(basicFilterWithBuilder).toBeDefined(); + expect(basicFilterWithBuilder).toEqual(basicFilter); + }); + + it('validates Basic filter with hierarchy level target object', function () { + // Arrange + const values = [1, 2, 3]; + const operator: models.BasicFilterOperators = 'In'; + const basicFilter: models.BasicFilter = new models.BasicFilter(hierarchyLevelTarget, operator, values); + basicFilter.requireSingleSelection = false; + + // Act + const basicFilterWithBuilder: models.BasicFilter = new BasicFilterBuilder() + .withHierarchyLevelTarget('table', 'hierarchy', 'hierarchy level name') + .in(values) + .build(); + + // Assert + expect(basicFilterWithBuilder).toBeDefined(); + expect(basicFilterWithBuilder).toEqual(basicFilter); + }); + + it('validates Basic filter with column aggregation target object', function () { + // Arrange + const values = [1, 2, 3]; + const operator: models.BasicFilterOperators = 'In'; + const basicFilter: models.BasicFilter = new models.BasicFilter(columnAggregationTarget, operator, values); + basicFilter.requireSingleSelection = false; + + // Act + const basicFilterWithBuilder: models.BasicFilter = new BasicFilterBuilder() + .withColumnAggregation('table', 'column', 'Avg') + .in(values) + .build(); + + // Assert + expect(basicFilterWithBuilder).toBeDefined(); + expect(basicFilterWithBuilder).toEqual(basicFilter); + }); + + it('validates Basic filter with hierarchy level aggregation target object', function () { + // Arrange + const values = [1, 2, 3]; + const operator: models.BasicFilterOperators = 'In'; + const basicFilter: models.BasicFilter = new models.BasicFilter(hierarchyLevelAggregationTarget, operator, values); + basicFilter.requireSingleSelection = false; + + // Act + const basicFilterWithBuilder: models.BasicFilter = new BasicFilterBuilder() + .withHierarchyLevelAggregationTarget('table', 'hierarchy', 'hierarchy level name', 'Avg') + .in(values) + .build(); + + // Assert + expect(basicFilterWithBuilder).toBeDefined(); + expect(basicFilterWithBuilder).toEqual(basicFilter); + }); + }); + + describe('Advanced filter builder', function () { + it('validates Advanced filter with target object', function () { + // Arrange + const logicalOperator: models.AdvancedFilterLogicalOperators = 'And'; + const conditions: models.IAdvancedFilterCondition[] = [ + { + operator: 'Contains', + value: 'value1' + }, + { + operator: 'Contains', + value: 'value2' + } + ]; + const advancedFilter: models.AdvancedFilter = new models.AdvancedFilter(target, logicalOperator, conditions); + + // Act + const advancedFilterWithBuilder: models.AdvancedFilter = new AdvancedFilterBuilder() + .withTargetObject(target) + .addCondition(conditions[0].operator, conditions[0].value) + .and() + .addCondition(conditions[1].operator, conditions[1].value) + .build(); + + // Assert + expect(advancedFilterWithBuilder).toBeDefined(); + expect(advancedFilterWithBuilder).toEqual(advancedFilter); + }); + + it('validates Advanced filter with column target object', function () { + // Arrange + const logicalOperator: models.AdvancedFilterLogicalOperators = 'And'; + const conditions: models.IAdvancedFilterCondition[] = [ + { + operator: 'Contains', + value: 'value1' + }, + { + operator: 'Contains', + value: 'value2' + } + ]; + const advancedFilter: models.AdvancedFilter = new models.AdvancedFilter(columnTarget, logicalOperator, conditions); + + // Act + const advancedFilterWithBuilder: models.AdvancedFilter = new AdvancedFilterBuilder() + .withColumnTarget('table', 'column') + .addCondition(conditions[0].operator, conditions[0].value) + .and() + .addCondition(conditions[1].operator, conditions[1].value) + .build(); + + // Assert + expect(advancedFilterWithBuilder).toBeDefined(); + expect(advancedFilterWithBuilder).toEqual(advancedFilter); + }); + + it('validates Advanced filter with measure target object', function () { + // Arrange + const logicalOperator: models.AdvancedFilterLogicalOperators = 'And'; + const conditions: models.IAdvancedFilterCondition[] = [ + { + operator: 'Contains', + value: 'value1' + }, + { + operator: 'Contains', + value: 'value2' + } + ]; + const advancedFilter: models.AdvancedFilter = new models.AdvancedFilter(measureTarget, logicalOperator, conditions); + + // Act + const advancedFilterWithBuilder: models.AdvancedFilter = new AdvancedFilterBuilder() + .withMeasureTarget('table', 'measure') + .addCondition(conditions[0].operator, conditions[0].value) + .and() + .addCondition(conditions[1].operator, conditions[1].value) + .build(); + + // Assert + expect(advancedFilterWithBuilder).toBeDefined(); + expect(advancedFilterWithBuilder).toEqual(advancedFilter); + }); + + it('validates Advanced filter with hierarchy level target object', function () { + // Arrange + const logicalOperator: models.AdvancedFilterLogicalOperators = 'And'; + const conditions: models.IAdvancedFilterCondition[] = [ + { + operator: 'Contains', + value: 'value1' + }, + { + operator: 'Contains', + value: 'value2' + } + ]; + const advancedFilter: models.AdvancedFilter = new models.AdvancedFilter(hierarchyLevelTarget, logicalOperator, conditions); + + // Act + const advancedFilterWithBuilder: models.AdvancedFilter = new AdvancedFilterBuilder() + .withHierarchyLevelTarget('table', 'hierarchy', 'hierarchy level name') + .addCondition(conditions[0].operator, conditions[0].value) + .and() + .addCondition(conditions[1].operator, conditions[1].value) + .build(); + + // Assert + expect(advancedFilterWithBuilder).toBeDefined(); + expect(advancedFilterWithBuilder).toEqual(advancedFilter); + }); + + it('validates Advanced filter with column aggregation target object', function () { + // Arrange + const logicalOperator: models.AdvancedFilterLogicalOperators = 'And'; + const conditions: models.IAdvancedFilterCondition[] = [ + { + operator: 'Contains', + value: 'value1' + }, + { + operator: 'Contains', + value: 'value2' + } + ]; + const advancedFilter: models.AdvancedFilter = new models.AdvancedFilter(columnAggregationTarget, logicalOperator, conditions); + + // Act + const advancedFilterWithBuilder: models.AdvancedFilter = new AdvancedFilterBuilder() + .withColumnAggregation('table', 'column', 'Avg') + .addCondition(conditions[0].operator, conditions[0].value) + .and() + .addCondition(conditions[1].operator, conditions[1].value) + .build(); + + // Assert + expect(advancedFilterWithBuilder).toBeDefined(); + expect(advancedFilterWithBuilder).toEqual(advancedFilter); + }); + + it('validates Advanced filter with hierarchy level aggregation target object', function () { + // Arrange + const logicalOperator: models.AdvancedFilterLogicalOperators = 'And'; + const conditions: models.IAdvancedFilterCondition[] = [ + { + operator: 'Contains', + value: 'value1' + }, + { + operator: 'Contains', + value: 'value2' + } + ]; + const advancedFilter: models.AdvancedFilter = new models.AdvancedFilter(hierarchyLevelAggregationTarget, logicalOperator, conditions); + + // Act + const advancedFilterWithBuilder: models.AdvancedFilter = new AdvancedFilterBuilder() + .withHierarchyLevelAggregationTarget('table', 'hierarchy', 'hierarchy level name', 'Avg') + .addCondition(conditions[0].operator, conditions[0].value) + .and() + .addCondition(conditions[1].operator, conditions[1].value) + .build(); + + // Assert + expect(advancedFilterWithBuilder).toBeDefined(); + expect(advancedFilterWithBuilder).toEqual(advancedFilter); + }); + }); + + describe('TopN filter builder', function () { + const orderByTarget: models.ITarget = { + table: 'table1', + measure: 'measure1' + }; + + it('validates TopN filter with target object', function () { + // Arrange + const operator: models.TopNFilterOperators = 'Top'; + const itemCount = 10; + const topNFilter: models.TopNFilter = new models.TopNFilter(target, operator, itemCount, orderByTarget); + + // Act + const topNFilterWithBuilder: models.TopNFilter = new TopNFilterBuilder() + .withTargetObject(target) + .top(itemCount) + .orderByTarget({ table: orderByTarget.table, measure: orderByTarget.measure }) + .build(); + + // Assert + expect(topNFilterWithBuilder).toBeDefined(); + expect(topNFilterWithBuilder).toEqual(topNFilter); + }); + + it('validates TopN filter with column target object', function () { + // Arrange + const operator: models.TopNFilterOperators = 'Top'; + const itemCount = 10; + const topNFilter: models.TopNFilter = new models.TopNFilter(columnTarget, operator, itemCount, orderByTarget); + + // Act + const topNFilterWithBuilder: models.TopNFilter = new TopNFilterBuilder() + .withColumnTarget('table', 'column') + .top(itemCount) + .orderByTarget({ table: orderByTarget.table, measure: orderByTarget.measure }) + .build(); + + // Assert + expect(topNFilterWithBuilder).toBeDefined(); + expect(topNFilterWithBuilder).toEqual(topNFilter); + }); + + it('validates TopN filter with measure target object', function () { + // Arrange + const operator: models.TopNFilterOperators = 'Top'; + const itemCount = 10; + const topNFilter: models.TopNFilter = new models.TopNFilter(measureTarget, operator, itemCount, orderByTarget); + + // Act + const topNFilterWithBuilder: models.TopNFilter = new TopNFilterBuilder() + .withMeasureTarget('table', 'measure') + .top(itemCount) + .orderByTarget({ table: orderByTarget.table, measure: orderByTarget.measure }) + .build(); + + // Assert + expect(topNFilterWithBuilder).toBeDefined(); + expect(topNFilterWithBuilder).toEqual(topNFilter); + }); + + it('validates TopN filter with hierarchy level target object', function () { + // Arrange + const operator: models.TopNFilterOperators = 'Top'; + const itemCount = 10; + const topNFilter: models.TopNFilter = new models.TopNFilter(hierarchyLevelTarget, operator, itemCount, orderByTarget); + + // Act + const topNFilterWithBuilder: models.TopNFilter = new TopNFilterBuilder() + .withHierarchyLevelTarget('table', 'hierarchy', 'hierarchy level name') + .top(itemCount) + .orderByTarget({ table: orderByTarget.table, measure: orderByTarget.measure }) + .build(); + + // Assert + expect(topNFilterWithBuilder).toBeDefined(); + expect(topNFilterWithBuilder).toEqual(topNFilter); + }); + + it('validates TopN filter with column aggregation target object', function () { + // Arrange + const operator: models.TopNFilterOperators = 'Top'; + const itemCount = 10; + const topNFilter: models.TopNFilter = new models.TopNFilter(columnAggregationTarget, operator, itemCount, orderByTarget); + + // Act + const topNFilterWithBuilder: models.TopNFilter = new TopNFilterBuilder() + .withColumnAggregation('table', 'column', 'Avg') + .top(itemCount) + .orderByTarget({ table: orderByTarget.table, measure: orderByTarget.measure }) + .build(); + + // Assert + expect(topNFilterWithBuilder).toBeDefined(); + expect(topNFilterWithBuilder).toEqual(topNFilter); + }); + + it('validates TopN filter with hierarchy level aggregation target object', function () { + // Arrange + const operator: models.TopNFilterOperators = 'Top'; + const itemCount = 10; + const topNFilter: models.TopNFilter = new models.TopNFilter(hierarchyLevelAggregationTarget, operator, itemCount, orderByTarget); + + // Act + const topNFilterWithBuilder: models.TopNFilter = new TopNFilterBuilder() + .withHierarchyLevelAggregationTarget('table', 'hierarchy', 'hierarchy level name', 'Avg') + .top(itemCount) + .orderByTarget({ table: orderByTarget.table, measure: orderByTarget.measure }) + .build(); + + // Assert + expect(topNFilterWithBuilder).toBeDefined(); + expect(topNFilterWithBuilder).toEqual(topNFilter); + }); + }); + + describe("Realtive date filter builder", function () { + + it('validates relative date with target object', function () { + // Arrange + const operator: models.RelativeDateOperators = models.RelativeDateOperators.InLast; + const timeUnitsCount = 10; + const timeUnitType = models.RelativeDateFilterTimeUnit.Days; + const includeToday = true; + const relativeDateFilter: models.RelativeDateFilter = new models.RelativeDateFilter(target, operator, timeUnitsCount, timeUnitType, includeToday); + + + // Act + const relativeDateFilterWithBuilder: models.RelativeDateFilter = new RelativeDateFilterBuilder() + .withTargetObject(target) + .inLast(timeUnitsCount, timeUnitType) + .includeToday(true) + .build(); + + // Assert + expect(relativeDateFilterWithBuilder).toBeDefined(); + expect(relativeDateFilterWithBuilder).toEqual(relativeDateFilter); + }); + + it('validates relative date with column target object', function () { + // Arrange + const operator: models.RelativeDateOperators = models.RelativeDateOperators.InLast; + const timeUnitsCount = 10; + const timeUnitType = models.RelativeDateFilterTimeUnit.Days; + const includeToday = true; + const relativeDateFilter: models.RelativeDateFilter = new models.RelativeDateFilter(columnTarget, operator, timeUnitsCount, timeUnitType, includeToday); + + + // Act + const relativeDateFilterWithBuilder: models.RelativeDateFilter = new RelativeDateFilterBuilder() + .withColumnTarget('table', 'column') + .inLast(timeUnitsCount, timeUnitType) + .includeToday(true) + .build(); + + // Assert + expect(relativeDateFilterWithBuilder).toBeDefined(); + expect(relativeDateFilterWithBuilder).toEqual(relativeDateFilter); + }); + + it('validates relative date with measure target object', function () { + // Arrange + const operator: models.RelativeDateOperators = models.RelativeDateOperators.InLast; + const timeUnitsCount = 10; + const timeUnitType = models.RelativeDateFilterTimeUnit.Days; + const includeToday = true; + const relativeDateFilter: models.RelativeDateFilter = new models.RelativeDateFilter(measureTarget, operator, timeUnitsCount, timeUnitType, includeToday); + + + // Act + const relativeDateFilterWithBuilder: models.RelativeDateFilter = new RelativeDateFilterBuilder() + .withMeasureTarget('table', 'measure') + .inLast(timeUnitsCount, timeUnitType) + .includeToday(true) + .build(); + + // Assert + expect(relativeDateFilterWithBuilder).toBeDefined(); + expect(relativeDateFilterWithBuilder).toEqual(relativeDateFilter); + }); + + it('validates relative date with hierarchy level target object', function () { + // Arrange + const operator: models.RelativeDateOperators = models.RelativeDateOperators.InLast; + const timeUnitsCount = 10; + const timeUnitType = models.RelativeDateFilterTimeUnit.Days; + const includeToday = true; + const relativeDateFilter: models.RelativeDateFilter = new models.RelativeDateFilter(hierarchyLevelTarget, operator, timeUnitsCount, timeUnitType, includeToday); + + + // Act + const relativeDateFilterWithBuilder: models.RelativeDateFilter = new RelativeDateFilterBuilder() + .withHierarchyLevelTarget('table', 'hierarchy', 'hierarchy level name') + .inLast(timeUnitsCount, timeUnitType) + .includeToday(true) + .build(); + + // Assert + expect(relativeDateFilterWithBuilder).toBeDefined(); + expect(relativeDateFilterWithBuilder).toEqual(relativeDateFilter); + }); + + it('validates relative date with column aggregation target object', function () { + // Arrange + const operator: models.RelativeDateOperators = models.RelativeDateOperators.InLast; + const timeUnitsCount = 10; + const timeUnitType = models.RelativeDateFilterTimeUnit.Days; + const includeToday = true; + const relativeDateFilter: models.RelativeDateFilter = new models.RelativeDateFilter(columnAggregationTarget, operator, timeUnitsCount, timeUnitType, includeToday); + + + // Act + const relativeDateFilterWithBuilder: models.RelativeDateFilter = new RelativeDateFilterBuilder() + .withColumnAggregation('table', 'column', 'Avg') + .inLast(timeUnitsCount, timeUnitType) + .includeToday(true) + .build(); + + // Assert + expect(relativeDateFilterWithBuilder).toBeDefined(); + expect(relativeDateFilterWithBuilder).toEqual(relativeDateFilter); + }); + + it('validates relative date with hierarchy level aggregation target object', function () { + // Arrange + const operator: models.RelativeDateOperators = models.RelativeDateOperators.InLast; + const timeUnitsCount = 10; + const timeUnitType = models.RelativeDateFilterTimeUnit.Days; + const includeToday = true; + const relativeDateFilter: models.RelativeDateFilter = new models.RelativeDateFilter(hierarchyLevelAggregationTarget, operator, timeUnitsCount, timeUnitType, includeToday); + + + // Act + const relativeDateFilterWithBuilder: models.RelativeDateFilter = new RelativeDateFilterBuilder() + .withHierarchyLevelAggregationTarget('table', 'hierarchy', 'hierarchy level name', 'Avg') + .inLast(timeUnitsCount, timeUnitType) + .includeToday(true) + .build(); + + // Assert + expect(relativeDateFilterWithBuilder).toBeDefined(); + expect(relativeDateFilterWithBuilder).toEqual(relativeDateFilter); + }); + }); + + describe("Realtive time filter builder", function () { + + it('validates time with target object', function () { + // Arrange + const operator: models.RelativeDateOperators = models.RelativeDateOperators.InLast; + const timeUnitsCount = 10; + const timeUnitType = models.RelativeDateFilterTimeUnit.Hours; + const relativeTimeFilter: models.RelativeTimeFilter = new models.RelativeTimeFilter(target, operator, timeUnitsCount, timeUnitType); + + + // Act + const relativeTimeFilterWithBuilder: models.RelativeTimeFilter = new RelativeTimeFilterBuilder() + .withTargetObject(target) + .inLast(timeUnitsCount, timeUnitType) + .build(); + + // Assert + expect(relativeTimeFilterWithBuilder).toBeDefined(); + expect(relativeTimeFilterWithBuilder).toEqual(relativeTimeFilter); + }); + + it('validates time with column target object', function () { + // Arrange + const operator: models.RelativeDateOperators = models.RelativeDateOperators.InLast; + const timeUnitsCount = 10; + const timeUnitType = models.RelativeDateFilterTimeUnit.Hours; + const relativeTimeFilter: models.RelativeTimeFilter = new models.RelativeTimeFilter(columnTarget, operator, timeUnitsCount, timeUnitType); + + + // Act + const relativeTimeFilterWithBuilder: models.RelativeTimeFilter = new RelativeTimeFilterBuilder() + .withColumnTarget('table', 'column') + .inLast(timeUnitsCount, timeUnitType) + .build(); + + // Assert + expect(relativeTimeFilterWithBuilder).toBeDefined(); + expect(relativeTimeFilterWithBuilder).toEqual(relativeTimeFilter); + }); + + it('validates time with measure target object', function () { + // Arrange + const operator: models.RelativeDateOperators = models.RelativeDateOperators.InLast; + const timeUnitsCount = 10; + const timeUnitType = models.RelativeDateFilterTimeUnit.Hours; + const relativeTimeFilter: models.RelativeTimeFilter = new models.RelativeTimeFilter(measureTarget, operator, timeUnitsCount, timeUnitType); + + + // Act + const relativeTimeFilterWithBuilder: models.RelativeTimeFilter = new RelativeTimeFilterBuilder() + .withMeasureTarget('table', 'measure') + .inLast(timeUnitsCount, timeUnitType) + .build(); + + // Assert + expect(relativeTimeFilterWithBuilder).toBeDefined(); + expect(relativeTimeFilterWithBuilder).toEqual(relativeTimeFilter); + }); + + it('validates time with hierarchy level target object', function () { + // Arrange + const operator: models.RelativeDateOperators = models.RelativeDateOperators.InLast; + const timeUnitsCount = 10; + const timeUnitType = models.RelativeDateFilterTimeUnit.Hours; + const relativeTimeFilter: models.RelativeTimeFilter = new models.RelativeTimeFilter(hierarchyLevelTarget, operator, timeUnitsCount, timeUnitType); + + + // Act + const relativeTimeFilterWithBuilder: models.RelativeTimeFilter = new RelativeTimeFilterBuilder() + .withHierarchyLevelTarget('table', 'hierarchy', 'hierarchy level name') + .inLast(timeUnitsCount, timeUnitType) + .build(); + + // Assert + expect(relativeTimeFilterWithBuilder).toBeDefined(); + expect(relativeTimeFilterWithBuilder).toEqual(relativeTimeFilter); + }); + + it('validates time with column aggregation target object', function () { + // Arrange + const operator: models.RelativeDateOperators = models.RelativeDateOperators.InLast; + const timeUnitsCount = 10; + const timeUnitType = models.RelativeDateFilterTimeUnit.Hours; + const relativeTimeFilter: models.RelativeTimeFilter = new models.RelativeTimeFilter(columnAggregationTarget, operator, timeUnitsCount, timeUnitType); + + + // Act + const relativeTimeFilterWithBuilder: models.RelativeTimeFilter = new RelativeTimeFilterBuilder() + .withColumnAggregation('table', 'column', 'Avg') + .inLast(timeUnitsCount, timeUnitType) + .build(); + + // Assert + expect(relativeTimeFilterWithBuilder).toBeDefined(); + expect(relativeTimeFilterWithBuilder).toEqual(relativeTimeFilter); + }); + + it('validates time with hierarchy level aggregation target object', function () { + // Arrange + const operator: models.RelativeDateOperators = models.RelativeDateOperators.InLast; + const timeUnitsCount = 10; + const timeUnitType = models.RelativeDateFilterTimeUnit.Hours; + const relativeTimeFilter: models.RelativeTimeFilter = new models.RelativeTimeFilter(hierarchyLevelAggregationTarget, operator, timeUnitsCount, timeUnitType); + + + // Act + const relativeTimeFilterWithBuilder: models.RelativeTimeFilter = new RelativeTimeFilterBuilder() + .withHierarchyLevelAggregationTarget('table', 'hierarchy', 'hierarchy level name', 'Avg') + .inLast(timeUnitsCount, timeUnitType) + .build(); + + // Assert + expect(relativeTimeFilterWithBuilder).toBeDefined(); + expect(relativeTimeFilterWithBuilder).toEqual(relativeTimeFilter); + }); + }); +}); \ No newline at end of file diff --git a/test/test.spec.ts b/test/test.spec.ts index cfe285d5..30efaa66 100644 --- a/test/test.spec.ts +++ b/test/test.spec.ts @@ -21,7 +21,7 @@ import { spyWpmp } from './utility/mockWpmp'; import { spyHpm } from './utility/mockHpm'; import { spyRouter } from './utility/mockRouter'; import * as util from '../src/util'; -import { EmbedUrlNotSupported } from '../src/errors' +import { APINotSupportedForRDLError, EmbedUrlNotSupported } from '../src/errors' // Avoid adding new tests to this file, create another spec file instead. @@ -3270,6 +3270,145 @@ describe('SDK-to-HPM', function () { }); }); + it('report.getPageByName() returns promise that rejects if report page with given page name not found', function (done) { + // Arrange + const pageName = 'page1'; + const testData = { + expectedError: { + body: { + message: 'page not found' + } + } + }; + + spyHpm.get.and.returnValue(Promise.reject(testData.expectedError)); + + // Act + report.getPageByName(pageName) + .catch(error => { + // Assert + expect(spyHpm.get).toHaveBeenCalledWith('/report/pages', { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.body); + done(); + }); + }); + + it('report.getPageByName(pageName) returns promise that resolves with page if request is successful', function (done) { + // Arrange + const pageName = "page1"; + const testData = { + expectedResponse: + { + report: report, + name: "page1", + displayName: "Page 1", + isActive: true + } + }; + + spyApp.getPageByName.and.returnValue(Promise.resolve(testData.expectedResponse)); + + // Act + spyApp.getPageByName(pageName) + .then(page => { + // Assert + expect(spyApp.getPageByName).toHaveBeenCalled(); + expect(page.name).toEqual(testData.expectedResponse.name); + expect(page.isActive).toEqual(testData.expectedResponse.isActive); + done(); + }); + }); + + it('report.getActivePage() sends GET /report/pages', function () { + // Arrange + const testData = { + response: { + body: [ + { + name: 'page1' + } + ] + } + }; + + spyHpm.get.and.returnValue(Promise.resolve(testData.response)); + + // Act + report.getActivePage(); + + // Assert + expect(spyHpm.get).toHaveBeenCalledWith('/report/pages', { uid: uniqueId }, iframe.contentWindow); + }); + + it('report.getActivePage() return promise that rejects with server error if there was error getting active page', function (done) { + // Arrange + const testData = { + expectedError: { + body: { + message: 'internal server error' + } + } + }; + + spyHpm.get.and.returnValue(Promise.reject(testData.expectedError)); + + // Act + report.getActivePage() + .catch(error => { + // Assert + expect(spyHpm.get).toHaveBeenCalledWith('/report/pages', { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.body); + done(); + }); + }); + + it('report.getActivePage() return promise that rejects if embedded report is an RDL report', function (done) { + // Arrange + const testData = { + expectedError: { + body: { + message: APINotSupportedForRDLError + } + } + }; + + spyHpm.get.and.returnValue(Promise.reject(testData.expectedError)); + + // Act + report.getActivePage() + .catch(error => { + // Assert + expect(spyHpm.get).toHaveBeenCalledWith('/report/pages', { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.body); + done(); + }); + }); + + it('report.getActivePage() returns promise that resolves with a page if request is successful', function (done) { + // Arrange + const testData = { + expectedResponse: + { + report: report, + name: "page1", + displayName: "Page 1", + isActive: true + } + }; + + spyApp.getActivePage.and.returnValue(Promise.resolve(testData.expectedResponse)); + + // Act + spyApp.getActivePage() + .then(page => { + // Assert + expect(spyApp.getActivePage).toHaveBeenCalled(); + expect(page.name).toEqual(testData.expectedResponse.name); + expect(page.isActive).toEqual(testData.expectedResponse.isActive); + done(); + }); + }); + it('report.addPage() sends POST /report/addPage with displayName', function () { // Arrange const displayName = "testName"; @@ -3539,6 +3678,54 @@ describe('SDK-to-HPM', function () { }); }); + describe('switchLayout', function () { + it('report.switchLayout(layout) returns promise that rejects with errors if there was error if initial layout and current layout type do not match', function (done) { + // Arrange + // Set initial layout to desktop layout + report.config.settings.layoutType = models.LayoutType.Master; + + const layoutType = models.LayoutType.MobileLandscape; + const testData = { + expectedError: { + message: 'Switching between mobile and desktop layouts is not supported. Please reset the embed container and re-embed with required layout.' + }, + settings: { + layoutType: layoutType + } + }; + + spyHpm.patch.and.returnValues(Promise.reject(testData.expectedError)); + + // Act + report.switchLayout(layoutType) + .catch(error => { + // Assert + expect(spyHpm.patch).not.toHaveBeenCalledWith('/report/settings', testData.settings, { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.message); + done(); + }); + }); + + it('report.switchLayout(layout) returns promise that resolves with null if requst is valid and accepted', function (done) { + // Arrange + // Set initial layout to mobile layout + report.config.settings.layoutType = models.LayoutType.MobilePortrait; + + const layoutType = models.LayoutType.MobileLandscape; + + spyApp.switchLayout.and.returnValue(Promise.resolve(null)); + + // Act + spyApp.switchLayout(layoutType) + .then(response => { + // Assert + expect(spyApp.switchLayout).toHaveBeenCalled(); + expect(response).toEqual(null); + done(); + }); + }); + }); + describe('saveAs', function () { let saveAsParameters: models.ISaveAsParameters = { name: "reportName" }; @@ -3753,156 +3940,558 @@ describe('SDK-to-HPM', function () { done() }); }); - }); - }); - - describe('create', function () { - describe('createReport', function () { - it('create.createReport() sends POST /report/create with configuration in body', function () { - // Arrange - const testData = { - createConfiguration: { - datasetId: 'fakeId', - accessToken: 'fakeToken' - }, - response: { - body: null - } - }; - - spyHpm.post.and.returnValue(Promise.resolve(testData.response)); - - // Act - create.createReport(testData.createConfiguration); - - // Assert - expect(spyHpm.post).toHaveBeenCalledWith('/report/create', testData.createConfiguration, { uid: createUniqueId, sdkSessionId: sdkSessionId }, createIframe.contentWindow); - }); - it('create.createReport() returns promise that rejects with validation error if the create configuration is invalid', function (done) { + it('report.addContextMenuCommand(commandName, commandTitle, contextMenuTitle) returns promise that rejects with validation errors if extensions property is invalid', function (done) { // Arrange + const commandName = "name1"; + const commandTitle = "title1"; + const contextMenuTitle = "menu1"; const testData = { - createConfiguration: { - datasetId: 'fakeId', - accessToken: 'fakeToken' + expectedError: { + body: [ + { + message: 'extensions property is invalid' + } + ] }, - errorResponse: { - body: { - message: "invalid configuration object" + settings: { + extensions: { + commands: [{ + name: "name1", + title: "title1", + extend: { + visualContextMenu: { + title: contextMenuTitle, + menuLocation: 0 + } + } + }], + groups: [] } } }; - spyHpm.post.and.returnValue(Promise.reject(testData.errorResponse)); + spyHpm.patch.and.returnValues(Promise.reject(testData.expectedError)); // Act - create.createReport(testData.createConfiguration) + report.addContextMenuCommand(commandName, commandTitle, contextMenuTitle, 0, "", "", "") .catch(error => { - expect(spyHpm.post).toHaveBeenCalledWith('/report/create', testData.createConfiguration, { uid: createUniqueId, sdkSessionId: sdkSessionId }, createIframe.contentWindow); - expect(error).toEqual(testData.errorResponse.body); // Assert + expect(spyHpm.patch).toHaveBeenCalledWith('/report/settings', testData.settings, { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(jasmine.objectContaining(testData.expectedError.body)); done(); }); }); - it('create.createReport() returns promise that resolves with null if create report was successful', function (done) { + it('report.addContextMenuCommand(commandName, commandTitle, contextMenuTitle) returns promise that resolves with null if requst is valid and accepted', function (done) { // Arrange - const testData = { - createConfiguration: { - datasetId: 'fakeId', - accessToken: 'fakeToken' - }, - response: { - body: null - } - }; + const commandName = "name2"; + const commandTitle = "title2"; + const contextMenuTitle = "menu2"; - spyHpm.post.and.returnValue(Promise.resolve(testData.response)); + spyApp.addContextMenuCommand.and.returnValue(Promise.resolve(null)); // Act - create.createReport(testData.createConfiguration) + spyApp.addContextMenuCommand(commandName, commandTitle, contextMenuTitle) .then(response => { - expect(spyHpm.post).toHaveBeenCalledWith('/report/create', testData.createConfiguration, { uid: createUniqueId, sdkSessionId: sdkSessionId }, createIframe.contentWindow); - expect(response).toEqual(null); // Assert + expect(spyApp.addContextMenuCommand).toHaveBeenCalled(); + expect(response).toEqual(null); done(); }); }); - }); - }); - describe('dashboard', function () { - describe('load', function () { - it('dashboard.load() sends POST /dashboard/load with configuration in body', function () { + it('report.addOptionsMenuCommand(commandName, commandTitle, optionsMenuTitle) returns promise that rejects with validation errors if extensions property is invalid', function (done) { // Arrange + const commandName = "name1"; + const commandTitle = "title1"; + const optionsMenuTitle = "menu1"; const testData = { - loadConfiguration: { - id: 'fakeId', - accessToken: 'fakeToken', - type: 'dashboard' + expectedError: { + body: [ + { + message: 'extensions property is invalid' + } + ] }, - response: { - body: null + settings: { + extensions: { + commands: [{ + name: "name1", + title: "title1", + extend: { + visualOptionsMenu: { + title: "menu1", + menuLocation: 0, + } + }, + icon: undefined + }], + groups: [] + } } }; - spyHpm.post.and.returnValue(Promise.resolve(testData.response)); + spyHpm.patch.and.returnValues(Promise.reject(testData.expectedError)); // Act - let expectedConfiguration = utils.assign({}, dashboard.config, testData.loadConfiguration); - dashboard.config = expectedConfiguration; - dashboard.load(); - - const expectedHeaders = { - bootstrapped: undefined, - sdkVersion: sdkConfig.default.version, - uid: dashboardUniqueId, - sdkSessionId: sdkSessionId - }; - - // Assert - expect(spyHpm.post).toHaveBeenCalledWith('/dashboard/load', expectedConfiguration, expectedHeaders, dashboardIframe.contentWindow); + report.addOptionsMenuCommand(commandName, commandTitle, optionsMenuTitle) + .catch(error => { + // Assert + expect(spyHpm.patch).toHaveBeenCalledWith('/report/settings', testData.settings, { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(jasmine.objectContaining(testData.expectedError.body)); + done(); + }); }); - }); - }); - describe('page', function () { - describe('filters', function () { - it('page.getFilters() sends GET /report/pages/xyz/filters', function () { + it('report.addOptionsMenuCommand(commandName, commandTitle, optionsMenuTitle) returns promise that resolves with null if requst is valid and accepted', function (done) { // Arrange + const commandName = "name2"; + const commandTitle = "title2"; + const optionsMenuTitle = "menu2"; - // Act - page1.getFilters(); + spyApp.addOptionsMenuCommand.and.returnValue(Promise.resolve(null)); - // Assert - expect(spyHpm.get).toHaveBeenCalledWith(`/report/pages/${page1.name}/filters`, { uid: uniqueId }, iframe.contentWindow); + // Act + spyApp.addOptionsMenuCommand(commandName, commandTitle, optionsMenuTitle) + .then(response => { + // Assert + expect(spyApp.addOptionsMenuCommand).toHaveBeenCalled(); + expect(response).toEqual(null); + done(); + }); }); - it('page.getFilters() return promise that rejects with server error if there was error getting filters', function (done) { + it('report.removeContextMenuCommand(commandName) returns promise that rejects with validation errors if command name is invalid', function (done) { // Arrange + const commandName = "name1"; const testData = { expectedError: { - body: { - message: 'internal server error' + message: 'PowerBIEntityNotFound' + }, + settings: { + extensions: { + commands: [{ + name: "name1", + title: "title1", + extend: { + } + }] } } }; - spyHpm.get.and.returnValue(Promise.reject(testData.expectedError)); + spyApp.removeContextMenuCommand.and.returnValues(Promise.reject(testData.expectedError)); // Act - page1.getFilters() + spyApp.removeContextMenuCommand(commandName) .catch(error => { // Assert - expect(spyHpm.get).toHaveBeenCalledWith(`/report/pages/${page1.name}/filters`, { uid: uniqueId }, iframe.contentWindow); - expect(error).toEqual(testData.expectedError.body); + expect(spyHpm.patch).not.toHaveBeenCalledWith('/report/settings', testData.settings, { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(jasmine.objectContaining(testData.expectedError)); done(); }); }); - it('page.getFilters() returns promise that resolves with list of filters', function (done) { + it('report.removeContextMenuCommand(commandName) returns promise that resolves with null if requst is valid and accepted', function (done) { // Arrange - const testData = { + const commandName = "name2"; + + spyApp.removeContextMenuCommand.and.returnValue(Promise.resolve(null)); + + // Act + spyApp.removeContextMenuCommand(commandName) + .then(response => { + // Assert + expect(spyApp.removeContextMenuCommand).toHaveBeenCalled(); + expect(response).toEqual(null); + done(); + }); + }); + + it('report.removeOptionsMenuCommand(commandName) returns promise that rejects with validation errors if command name is invalid', function (done) { + // Arrange + const commandName = "name1"; + const testData = { + expectedError: { + message: 'PowerBIEntityNotFound' + }, + settings: { + extensions: { + commands: [{ + name: "name1", + title: "title1", + icon: "", + extend: { + } + }] + } + } + }; + + spyApp.removeOptionsMenuCommand.and.returnValues(Promise.reject(testData.expectedError)); + + // Act + spyApp.removeOptionsMenuCommand(commandName) + .catch(error => { + // Assert + expect(spyHpm.patch).not.toHaveBeenCalledWith('/report/settings', testData.settings, { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(jasmine.objectContaining(testData.expectedError)); + done(); + }); + }); + + it('report.removeOptionsMenuCommand(commandName) returns promise that resolves with null if requst is valid and accepted', function (done) { + // Arrange + const commandName = "name2"; + + spyApp.removeOptionsMenuCommand.and.returnValue(Promise.resolve(null)); + + // Act + spyApp.removeOptionsMenuCommand(commandName) + .then(response => { + // Assert + expect(spyApp.removeOptionsMenuCommand).toHaveBeenCalled(); + expect(response).toEqual(null); + done(); + }); + }); + + it('report.setVisualDisplayState(pageName, visualName, displayState) returns promise that rejects with validation error if display state is invalid', function (done) { + // Arrange + const pageName = 'page1'; + const visualName = 'visual'; + const displayState = 2; + const testData = { + expectedError: { + body: { + message: 'display state is invalid' + } + } + }; + + spyHpm.get.and.returnValue(Promise.reject(testData.expectedError)); + + // Act + report.setVisualDisplayState(pageName, visualName, displayState) + .catch(error => { + // Assert + expect(spyHpm.get).toHaveBeenCalledWith('/report/pages', { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.body); + done(); + }); + }); + + it('report.setVisualDisplayState(pageName, visualName, displayState) returns promise that resolves with null if requst is valid and accepted', function (done) { + // Arrange + const pageName = 'page1'; + const visualName = 'visual'; + const displayState = models.VisualContainerDisplayMode.Visible; + + spyApp.setVisualDisplayState.and.returnValue(Promise.resolve(null)); + + // Act + spyApp.setVisualDisplayState(pageName, visualName, displayState) + .then(response => { + // Assert + expect(spyApp.setVisualDisplayState).toHaveBeenCalled(); + expect(response).toEqual(null); + done(); + }); + }); + + it('report.resizeVisual returns promise that rejects with validation error if page name is invalid', function (done) { + // Arrange + const pageName = 'invalid page'; + const visualName = 'visual'; + const width = 200; + const height = 100; + const testData = { + expectedError: { + body: { + message: 'page name is invalid' + } + } + }; + + spyHpm.get.and.returnValue(Promise.reject(testData.expectedError)); + + // Act + report.resizeVisual(pageName, visualName, width, height) + .catch(error => { + // Assert + expect(spyHpm.get).toHaveBeenCalledWith('/report/pages', { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.body); + done(); + }); + }); + + it('report.resizeVisual returns promise that resolves with null if request is valid and accepted', function (done) { + // Arrange + const pageName = 'page1'; + const visualName = 'visual'; + const width = 200; + const height = 100; + + spyApp.resizeVisual.and.returnValue(Promise.resolve(null)); + + // Act + spyApp.resizeVisual(pageName, visualName, width, height) + .then(response => { + // Assert + expect(spyApp.resizeVisual).toHaveBeenCalled(); + expect(response).toEqual(null); + done(); + }); + }); + + it('report.resizeActivePage returns promise that rejects with validation error if page size type is invalid', function (done) { + // Arrange + const pageSizeType = 5; + const width = 200; + const height = 100; + const testData = { + expectedError: { + body: { + message: 'page size type is invalid' + } + }, + settings: { + layoutType: models.LayoutType.Custom, + customLayout: { + pageSize: { + type: pageSizeType, + width: width, + height: height + } + } + } + }; + + spyHpm.patch.and.returnValue(Promise.reject(testData.expectedError)); + + // Act + report.resizeActivePage(pageSizeType, width, height) + .catch(error => { + // Assert + expect(spyHpm.patch).toHaveBeenCalledWith('/report/settings', testData.settings, { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.body); + done(); + }); + }); + + it('report.resizeActivePage returns promise that resolves with null if request is valid and accepted', function (done) { + // Arrange + const pageSizeType = models.PageSizeType.Custom; + const width = 200; + const height = 100; + + spyApp.resizeActivePage.and.returnValue(Promise.resolve(null)); + + // Act + spyApp.resizeActivePage(pageSizeType, width, height) + .then(response => { + // Assert + expect(spyApp.resizeActivePage).toHaveBeenCalled(); + expect(response).toEqual(null); + done(); + }); + }); + + it('moveVisual returns promise that rejects with validation error if visual name is invalid', function (done) { + // Arrange + const pageName = 'page1'; + const visualName = 'invalid visual'; + const x = 0; + const y = 0; + const testData = { + expectedError: { + body: { + message: 'visual name is invalid' + } + } + }; + + spyHpm.get.and.returnValue(Promise.reject(testData.expectedError)); + + // Act + report.moveVisual(pageName, visualName, x, y) + .catch(error => { + // Assert + expect(spyHpm.get).toHaveBeenCalledWith('/report/pages', { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.body); + done(); + }); + }); + + it('moveVisual returns promise that resolves with null if requst is valid and accepted', function (done) { + // Arrange + const pageName = 'page1'; + const visualName = 'visual'; + const x = 0; + const y = 0; + + spyApp.moveVisual.and.returnValue(Promise.resolve(null)); + + // Act + spyApp.moveVisual(pageName, visualName, x, y) + .then(response => { + // Assert + expect(spyApp.moveVisual).toHaveBeenCalled(); + expect(response).toEqual(null); + done(); + }); + }); + }); + }); + + describe('create', function () { + describe('createReport', function () { + it('create.createReport() sends POST /report/create with configuration in body', function () { + // Arrange + const testData = { + createConfiguration: { + datasetId: 'fakeId', + accessToken: 'fakeToken' + }, + response: { + body: null + } + }; + + spyHpm.post.and.returnValue(Promise.resolve(testData.response)); + + // Act + create.createReport(testData.createConfiguration); + + // Assert + expect(spyHpm.post).toHaveBeenCalledWith('/report/create', testData.createConfiguration, { uid: createUniqueId, sdkSessionId: sdkSessionId }, createIframe.contentWindow); + }); + + it('create.createReport() returns promise that rejects with validation error if the create configuration is invalid', function (done) { + // Arrange + const testData = { + createConfiguration: { + datasetId: 'fakeId', + accessToken: 'fakeToken' + }, + errorResponse: { + body: { + message: "invalid configuration object" + } + } + }; + + spyHpm.post.and.returnValue(Promise.reject(testData.errorResponse)); + + // Act + create.createReport(testData.createConfiguration) + .catch(error => { + expect(spyHpm.post).toHaveBeenCalledWith('/report/create', testData.createConfiguration, { uid: createUniqueId, sdkSessionId: sdkSessionId }, createIframe.contentWindow); + expect(error).toEqual(testData.errorResponse.body); + // Assert + done(); + }); + }); + + it('create.createReport() returns promise that resolves with null if create report was successful', function (done) { + // Arrange + const testData = { + createConfiguration: { + datasetId: 'fakeId', + accessToken: 'fakeToken' + }, + response: { + body: null + } + }; + + spyHpm.post.and.returnValue(Promise.resolve(testData.response)); + + // Act + create.createReport(testData.createConfiguration) + .then(response => { + expect(spyHpm.post).toHaveBeenCalledWith('/report/create', testData.createConfiguration, { uid: createUniqueId, sdkSessionId: sdkSessionId }, createIframe.contentWindow); + expect(response).toEqual(null); + // Assert + done(); + }); + }); + }); + }); + + describe('dashboard', function () { + describe('load', function () { + it('dashboard.load() sends POST /dashboard/load with configuration in body', function () { + // Arrange + const testData = { + loadConfiguration: { + id: 'fakeId', + accessToken: 'fakeToken', + type: 'dashboard' + }, + response: { + body: null + } + }; + + spyHpm.post.and.returnValue(Promise.resolve(testData.response)); + + // Act + let expectedConfiguration = utils.assign({}, dashboard.config, testData.loadConfiguration); + dashboard.config = expectedConfiguration; + dashboard.load(); + + const expectedHeaders = { + bootstrapped: undefined, + sdkVersion: sdkConfig.default.version, + uid: dashboardUniqueId, + sdkSessionId: sdkSessionId + }; + + // Assert + expect(spyHpm.post).toHaveBeenCalledWith('/dashboard/load', expectedConfiguration, expectedHeaders, dashboardIframe.contentWindow); + }); + }); + }); + + describe('page', function () { + describe('filters', function () { + it('page.getFilters() sends GET /report/pages/xyz/filters', function () { + // Arrange + + // Act + page1.getFilters(); + + // Assert + expect(spyHpm.get).toHaveBeenCalledWith(`/report/pages/${page1.name}/filters`, { uid: uniqueId }, iframe.contentWindow); + }); + + it('page.getFilters() return promise that rejects with server error if there was error getting filters', function (done) { + // Arrange + const testData = { + expectedError: { + body: { + message: 'internal server error' + } + } + }; + + spyHpm.get.and.returnValue(Promise.reject(testData.expectedError)); + + // Act + page1.getFilters() + .catch(error => { + // Assert + expect(spyHpm.get).toHaveBeenCalledWith(`/report/pages/${page1.name}/filters`, { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.body); + done(); + }); + }); + + it('page.getFilters() returns promise that resolves with list of filters', function (done) { + // Arrange + const testData = { expectedResponse: { body: [ { x: 'fakeFilter1' }, @@ -4090,6 +4679,173 @@ describe('SDK-to-HPM', function () { }); }); }); + describe('custom layout', function () { + it('page.setVisualDisplayState returns promise that rejects with validation error if display state is invalid', function (done) { + // Arrange + const visualName = 'visual'; + const displayState = 2; + const testData = { + expectedError: { + body: { + message: 'display state is invalid' + } + } + }; + + spyHpm.get.and.returnValue(Promise.reject(testData.expectedError)); + + // Act + page1.setVisualDisplayState(visualName, displayState) + .catch(error => { + // Assert + expect(spyHpm.get).toHaveBeenCalledWith('/report/pages', { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.body); + done(); + }); + }); + + it('page.setVisualDisplayState returns promise that resolves with null if requst is valid and accepted', function (done) { + // Arrange + const visualName = 'visual'; + const displayState = models.VisualContainerDisplayMode.Visible; + + spyApp.setVisualDisplayState.and.returnValue(Promise.resolve(null)); + + // Act + spyApp.setVisualDisplayState(visualName, displayState) + .then(response => { + // Assert + expect(spyApp.setVisualDisplayState).toHaveBeenCalled(); + expect(response).toEqual(null); + done(); + }); + }); + + it('page.moveVisual returns promise that rejects with validation error if visual name is invalid', function (done) { + // Arrange + const visualName = 'invalid visual'; + const x = 0; + const y = 0; + const testData = { + expectedError: { + body: { + message: 'visual name is invalid' + } + } + }; + + spyHpm.get.and.returnValue(Promise.reject(testData.expectedError)); + + // Act + page1.moveVisual(visualName, x, y) + .catch(error => { + // Assert + expect(spyHpm.get).toHaveBeenCalledWith('/report/pages', { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.body); + done(); + }); + }); + + it('page.moveVisual returns promise that resolves with null if requst is valid and accepted', function (done) { + // Arrange + const visualName = 'visual'; + const x = 0; + const y = 0; + + spyApp.moveVisual.and.returnValue(Promise.resolve(null)); + + // Act + spyApp.moveVisual(visualName, x, y) + .then(response => { + // Assert + expect(spyApp.moveVisual).toHaveBeenCalled(); + expect(response).toEqual(null); + done(); + }); + }); + + it('page.resizePage returns promise that rejects with validation error if page is not active page', function (done) { + // Arrange + const pageSizeType = 1; + const width = 200; + const height = 100; + const testData = { + expectedError: { + message: 'Cannot resize the page. Only the active page can be resized' + }, + settings: { + layoutType: models.LayoutType.Custom, + customLayout: { + pageSize: { + type: pageSizeType, + width: width, + height: height + } + } + } + }; + + spyHpm.patch.and.returnValue(Promise.reject(testData.expectedError.message)); + + // Act + page1.resizePage(pageSizeType, width, height) + .catch(error => { + // Assert + expect(spyHpm.patch).not.toHaveBeenCalledWith('/report/settings', testData.settings, { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.message); + done(); + }); + }); + + it('page.resizePage returns promise that resolves with null if page is active page', function (done) { + // Arrange + const pageSizeType = 1; + const width = 200; + const height = 100; + const testData = { + settings: { + layoutType: models.LayoutType.Custom, + customLayout: { + pageSize: { + type: pageSizeType, + width: width, + height: height + } + } + } + }; + + page1.isActive = true; + spyHpm.patch.and.returnValue(Promise.resolve(null)); + + // Act + page1.resizePage(pageSizeType, width, height) + .then(response => { + // Assert + expect(spyHpm.patch).toHaveBeenCalledWith('/report/settings', testData.settings, { uid: uniqueId }, iframe.contentWindow); + expect(response).toEqual(null); + done(); + }); + }); + + it('page.resizePage returns promise that resolves with null if request is valid and accepted', function (done) { + // Arrange + const pageSizeType = models.PageSizeType.Custom; + const width = 200; + const height = 100; + + spyApp.resizeActivePage.and.returnValue(Promise.resolve(null)); + + // Act + spyApp.resizeActivePage(pageSizeType, width, height) + .then(response => { + // Assert + expect(spyApp.resizeActivePage).toHaveBeenCalled(); + expect(response).toEqual(null); + done(); + }); + }); + }); }); describe('setDisplayName', function () { @@ -4113,6 +4869,59 @@ describe('SDK-to-HPM', function () { }); }); + describe('getVisualByName', function () { + it('page.getVisualByName(visualName) returns promise that rejects if visual with given name not found', function (done) { + // Arrange + const pageName = page1.name; + const visualName = "visual1"; + const testData = { + expectedError: { + body: { + message: 'visual not found' + } + } + }; + + spyHpm.get.and.returnValue(Promise.reject(testData.expectedError)); + // Act + page1.getVisualByName(visualName) + .catch(error => { + // Assert + expect(spyHpm.get).toHaveBeenCalledWith(`/report/pages/${pageName}/visuals`, { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.body); + done(); + }); + }); + + it('page.getVisualByName(visualName) returns promise that resolves with visual if request is successful', function (done) { + // Arrange + const pageName = page1.name; + const visualName = "visual1"; + const testData = { + expectedResponse: + { + name: "visual1", + title: "Visual 1", + type: "type1", + layout: {}, + page: {} + } + }; + + spyApp.getVisualByName.and.returnValue(Promise.resolve(testData.expectedResponse)); + + // Act + spyApp.getVisualByName(visualName) + .then(visual => { + // Assert + expect(spyApp.getVisualByName).toHaveBeenCalled(); + expect(visual.name).toEqual(testData.expectedResponse.name); + expect(visual.title).toEqual(testData.expectedResponse.title); + done(); + }); + }); + }); + describe('visual', function () { describe('filters', function () { it('visual.getFilters() sends GET /report/pages/xyz/visuals/uvw/filters', function () { @@ -4266,6 +5075,128 @@ describe('SDK-to-HPM', function () { }); }); + describe('custom layout', function () { + it('visual.moveVisual() returns promise that rejects with server error if error in updating setting', function (done) { + // Arrange + const x = 0; + const y = 0; + const testData = { + expectedError: { + body: { + message: 'internal server error' + } + } + }; + + spyHpm.get.and.returnValue(Promise.reject(testData.expectedError)); + + // Act + visual1.moveVisual(x, y) + .catch(error => { + // Assert + expect(spyHpm.get).toHaveBeenCalledWith('/report/pages', { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.body); + done(); + }); + }); + + it('visual.moveVisual() returns promise that resolves with null if request is valid and accepted', function (done) { + // Arrange + const x = 0; + const y = 0; + + spyApp.moveVisual.and.returnValue(Promise.resolve(null)); + + // Act + spyApp.moveVisual(x, y) + .then(response => { + // Assert + expect(spyApp.moveVisual).toHaveBeenCalled(); + expect(response).toEqual(null); + done(); + }); + }); + + it('visual.setVisualDisplayState(displayState) returns promise that rejects with validation error if display state is invalid', function (done) { + // Arrange + const displayState = 2; + const testData = { + expectedError: { + body: { + message: 'mode property is invalid' + } + }, + }; + + spyApp.setVisualDisplayState.and.returnValue(Promise.reject(testData.expectedError)); + + // Act + spyApp.setVisualDisplayState(displayState) + .catch(error => { + // Assert + expect(error).toEqual(testData.expectedError); + done(); + }); + }); + + it('visual.setVisualDisplayState(displayState) returns promise that resolves with null if requst is valid and accepted', function (done) { + // Arrange + const displayState = models.VisualContainerDisplayMode.Visible; + + spyApp.setVisualDisplayState.and.returnValue(Promise.resolve(null)); + + // Act + spyApp.setVisualDisplayState(displayState) + .then(response => { + // Assert + expect(spyApp.setVisualDisplayState).toHaveBeenCalled(); + expect(response).toEqual(null); + done(); + }); + }); + + it('visual.resizeVisual returns promise that rejects with server error if error in updating setting', function (done) { + // Arrange + const width = 200; + const height = 100; + const testData = { + expectedError: { + body: { + message: 'internal server error' + } + } + }; + + spyHpm.get.and.returnValue(Promise.reject(testData.expectedError)); + + // Act + visual1.resizeVisual(width, height) + .catch(error => { + // Assert + expect(spyHpm.get).toHaveBeenCalledWith('/report/pages', { uid: uniqueId }, iframe.contentWindow); + expect(error).toEqual(testData.expectedError.body); + done(); + }); + }); + + it('visual.resizeVisual returns promise that resolves with null if request is valid and accepted', function (done) { + // Arrange + const width = 200; + const height = 100; + + spyApp.resizeVisual.and.returnValue(Promise.resolve(null)); + + // Act + spyApp.resizeVisual(width, height) + .then(response => { + // Assert + expect(spyApp.resizeVisual).toHaveBeenCalled(); + expect(response).toEqual(null); + done(); + }); + }); + }); + describe('theme', function () { it('report.applyTheme(theme) sends PUT /report/theme with theme in body', function () { // Arrange diff --git a/test/utility/mockApp.ts b/test/utility/mockApp.ts index 823982ba..e91a634a 100644 --- a/test/utility/mockApp.ts +++ b/test/utility/mockApp.ts @@ -13,12 +13,23 @@ export interface IApp { // Settings updateSettings(settings: models.ISettings): Promise; validateSettings(settigns: models.ISettings): Promise; + addContextMenuCommand(commandName: string, commandTitle: string, contextMenuTitle: string, menuLocation?: string, visualName?: string, visualType?: string, groupName?: string): Promise; + addOptionsMenuCommand(commandName: string, commandTitle: string, optionsMenuTitle: string, menuLocation?: string, visualName?: string, visualType?: string, groupName?: string, commandIcon?: string): Promise; + removeContextMenuCommand(commandName: string): Promise; + removeOptionsMenuCommand(commandName: string): Promise; + setVisualDisplayState(pageName: string, visualName: string, displayState: models.VisualContainerDisplayMode): Promise; + resizeVisual(pageName: string, visualName: string, width: number, height: number): Promise; + resizeActivePage(pageSizeType: models.PageSizeType, width: number, height: number): Promise; + moveVisual(pageName: string, visualName: string, x: number, y: number, z?: number): Promise; // Pages getPages(): Promise; + getPageByName(pageName: string): Promise; + getActivePage(): Promise; setPage(pageName: string): Promise; validatePage(page: models.IPage): Promise; // Visuals validateVisual(page: models.IPage, visual: models.IVisual): Promise; + getVisualByName(visualName: string): Promise; // Filters getFilters(): Promise; updateFilters(operation: models.FiltersOperations, filters: models.IFilter[]): Promise; @@ -33,6 +44,7 @@ export interface IApp { save(): Promise; saveAs(saveAsParameters: models.ISaveAsParameters): Promise; setAccessToken(accessToken: string): Promise; + switchLayout(layoutType: models.LayoutType): Promise; } export const mockAppSpyObj = { @@ -45,12 +57,23 @@ export const mockAppSpyObj = { // Settings updateSettings: jasmine.createSpy("updateSettings").and.returnValue(Promise.resolve(null)), validateSettings: jasmine.createSpy("validateSettings").and.callFake(models.validateSettings), + addContextMenuCommand: jasmine.createSpy("addContextMenuCommand").and.returnValue(Promise.resolve(null)), + addOptionsMenuCommand: jasmine.createSpy("addOptionsMenuCommand").and.returnValue(Promise.resolve(null)), + removeContextMenuCommand: jasmine.createSpy("removeContextMenuCommand").and.returnValue(Promise.resolve(null)), + removeOptionsMenuCommand: jasmine.createSpy("removeOptionsMenuCommand").and.returnValue(Promise.resolve(null)), + setVisualDisplayState: jasmine.createSpy("setVisualDisplayState").and.returnValue(Promise.resolve(null)), + resizeVisual: jasmine.createSpy("resizeVisual").and.returnValue(Promise.resolve(null)), + resizeActivePage: jasmine.createSpy("resizeActivePage").and.returnValue(Promise.resolve(null)), + moveVisual: jasmine.createSpy("moveVisual").and.returnValue(Promise.resolve(null)), // Pages getPages: jasmine.createSpy("getPages").and.returnValue(Promise.resolve(null)), + getPageByName: jasmine.createSpy("getPageByName").and.returnValue(Promise.resolve(null)), + getActivePage: jasmine.createSpy("getActivePage").and.returnValue(Promise.resolve(null)), setPage: jasmine.createSpy("setPage").and.returnValue(Promise.resolve(null)), validatePage: jasmine.createSpy("validatePage").and.returnValue(Promise.resolve(null)), // Visuals validateVisual: jasmine.createSpy("validateVisual").and.returnValue(Promise.resolve(null)), + getVisualByName: jasmine.createSpy("getVisualByName").and.returnValue(Promise.resolve(null)), // Filters getFilters: jasmine.createSpy("getFilters").and.returnValue(Promise.resolve(null)), updateFilters: jasmine.createSpy("updateFilters").and.returnValue(Promise.resolve(null)), @@ -65,6 +88,7 @@ export const mockAppSpyObj = { save: jasmine.createSpy("save").and.returnValue(Promise.resolve(null)), saveAs: jasmine.createSpy("saveAs").and.returnValue(Promise.resolve(null)), setAccessToken: jasmine.createSpy("setAccessToken").and.returnValue(Promise.resolve(null)), + switchLayout: jasmine.createSpy("switchLayout").and.returnValue(Promise.resolve(null)), reset() { mockAppSpyObj.dashboardLoad.calls.reset(); @@ -74,14 +98,25 @@ export const mockAppSpyObj = { mockAppSpyObj.validateReportLoad.calls.reset(); mockAppSpyObj.updateSettings.calls.reset(); mockAppSpyObj.validateSettings.calls.reset(); + mockAppSpyObj.setVisualDisplayState.calls.reset(); + mockAppSpyObj.resizeVisual.calls.reset(); + mockAppSpyObj.resizeActivePage.calls.reset(); + mockAppSpyObj.moveVisual.calls.reset(); mockAppSpyObj.getPages.calls.reset(); + mockAppSpyObj.getPageByName.calls.reset(); + mockAppSpyObj.getActivePage.calls.reset(); mockAppSpyObj.setPage.calls.reset(); mockAppSpyObj.validatePage.calls.reset(); mockAppSpyObj.validateVisual.calls.reset(); + mockAppSpyObj.getVisualByName.calls.reset(); mockAppSpyObj.getFilters.calls.reset(); mockAppSpyObj.updateFilters.calls.reset(); mockAppSpyObj.setFilters.calls.reset(); mockAppSpyObj.validateFilter.calls.reset(); + mockAppSpyObj.addContextMenuCommand.calls.reset(); + mockAppSpyObj.addOptionsMenuCommand.calls.reset(); + mockAppSpyObj.removeContextMenuCommand.calls.reset(); + mockAppSpyObj.removeOptionsMenuCommand.calls.reset(); mockAppSpyObj.print.calls.reset(); mockAppSpyObj.refreshData.calls.reset(); mockAppSpyObj.exportData.calls.reset(); @@ -90,6 +125,7 @@ export const mockAppSpyObj = { mockAppSpyObj.save.calls.reset(); mockAppSpyObj.saveAs.calls.reset(); mockAppSpyObj.setAccessToken.calls.reset(); + mockAppSpyObj.switchLayout.calls.reset(); } }; diff --git a/webpack.test.config.js b/webpack.test.config.js index e0ebe539..04c1f1ff 100644 --- a/webpack.test.config.js +++ b/webpack.test.config.js @@ -1,8 +1,9 @@ const webpack = require('webpack'); // To access built-in plugins +const glob = require("glob"); module.exports = { mode: 'development', - entry: './test/test.spec.ts', + entry: glob.sync('./test/*.spec.ts'), output: { path: __dirname + "/tmp", filename: 'test.spec.js'