Skip to content

Commit ce34d4c

Browse files
committed
Merged PR 136967: Add update filters API
Added new `updateFilters` to `IFilterable` interfaces and to the classes that implements it. API usage examples: ```typescript await report.updateFilters(FiltersOperations.RemoveAll); await page.updateFilters(FiltersOperations.ReplaceAll, filters); await visual.updateFilters(FiltersOperations.Add, filters); await report.updateFilters(FiltersOperations.Replace, filters); ```
1 parent e4b6f1e commit ce34d4c

14 files changed

+1593
-1017
lines changed

.eslintrc.js

+252-251
Large diffs are not rendered by default.

dist/powerbi-client.d.ts

+210-147
Large diffs are not rendered by default.

dist/powerbi.js

+562-314
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/powerbi.min.js

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "powerbi-client",
3-
"version": "2.16.5",
3+
"version": "2.17.0",
44
"description": "JavaScript library for embedding Power BI into your apps. Provides service which makes it easy to embed different types of components and an object model which allows easy interaction with these components such as changing pages, applying filters, and responding to data selection.",
55
"main": "dist/powerbi.js",
66
"types": "dist/powerbi-client.d.ts",
@@ -78,7 +78,7 @@
7878
},
7979
"dependencies": {
8080
"http-post-message": "^0.2",
81-
"powerbi-models": "^1.7.1",
81+
"powerbi-models": "^1.8",
8282
"powerbi-router": "^0.1",
8383
"window-post-message-proxy": "^0.2"
8484
},

src/config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/** @ignore *//** */
22
const config = {
3-
version: '2.16.5',
3+
version: '2.17.0',
44
type: 'js'
55
};
66

src/ifilterable.ts

+19-11
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,39 @@
1-
import * as models from 'powerbi-models';
1+
import { FiltersOperations, IFilter } from 'powerbi-models';
22
import { IHttpPostMessageResponse } from 'http-post-message';
33

44
/**
55
* Decorates embed components that support filters
66
* Examples include reports and pages
7-
*
7+
*
88
* @export
99
* @interface IFilterable
1010
*/
1111
export interface IFilterable {
1212
/**
1313
* Gets the filters currently applied to the object.
14-
*
15-
* @returns {(Promise<models.IFilter[]>)}
14+
*
15+
* @returns {(Promise<IFilter[]>)}
1616
*/
17-
getFilters(): Promise<models.IFilter[]>;
17+
getFilters(): Promise<IFilter[]>;
1818
/**
19-
* Replaces all filters on the current object with the specified filter values.
20-
*
21-
* @param {(models.IFilter[])} filters
19+
* Update the filters for the current instance according to the operation: Add, replace all, replace by target or remove.
20+
*
21+
* @param {(FiltersOperations)} operation
22+
* @param {(IFilter[])} filters
2223
* @returns {Promise<IHttpPostMessageResponse<void>>}
2324
*/
24-
setFilters(filters: models.IFilter[]): Promise<IHttpPostMessageResponse<void>>;
25+
updateFilters(operation: FiltersOperations, filters?: IFilter[]): Promise<IHttpPostMessageResponse<void>>;
2526
/**
2627
* Removes all filters from the current object.
27-
*
28+
*
2829
* @returns {Promise<IHttpPostMessageResponse<void>>}
2930
*/
3031
removeFilters(): Promise<IHttpPostMessageResponse<void>>;
31-
}
32+
/**
33+
* Replaces all filters on the current object with the specified filter values.
34+
*
35+
* @param {(IFilter[])} filters
36+
* @returns {Promise<IHttpPostMessageResponse<void>>}
37+
*/
38+
setFilters(filters: IFilter[]): Promise<IHttpPostMessageResponse<void>>;
39+
}

src/page.ts

+87-52
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
import { IHttpPostMessageResponse } from 'http-post-message';
2+
import {
3+
DisplayOption,
4+
FiltersOperations,
5+
ICustomPageSize,
6+
IFilter,
7+
IPage,
8+
IUpdateFiltersRequest,
9+
IVisual,
10+
LayoutType,
11+
PageLevelFilters,
12+
SectionVisibility
13+
} from 'powerbi-models';
214
import { IFilterable } from './ifilterable';
315
import { IReportNode } from './report';
416
import { VisualDescriptor } from './visualDescriptor';
5-
import * as models from 'powerbi-models';
6-
import * as utils from './util';
7-
import * as errors from './errors';
17+
import { isRDLEmbed } from './util';
18+
import { APINotSupportedForRDLError } from './errors';
819

920
/**
1021
* A Page node within a report hierarchy
@@ -58,21 +69,23 @@ export class Page implements IPageNode, IFilterable {
5869
* 0 - Always Visible
5970
* 1 - Hidden in View Mode
6071
*
61-
* @type {models.SectionVisibility}
72+
* @type {SectionVisibility}
6273
*/
63-
visibility: models.SectionVisibility;
74+
visibility: SectionVisibility;
6475

6576
/**
6677
* Page size as saved in the report.
67-
* @type {models.ICustomPageSize}
78+
*
79+
* @type {ICustomPageSize}
6880
*/
69-
defaultSize: models.ICustomPageSize;
81+
defaultSize: ICustomPageSize;
7082

7183
/**
7284
* Page display options as saved in the report.
73-
* @type {models.ICustomPageSize}
85+
*
86+
* @type {ICustomPageSize}
7487
*/
75-
defaultDisplayOption: models.DisplayOption;
88+
defaultDisplayOption: DisplayOption;
7689

7790
/**
7891
* Creates an instance of a Power BI report page.
@@ -81,10 +94,10 @@ export class Page implements IPageNode, IFilterable {
8194
* @param {string} name
8295
* @param {string} [displayName]
8396
* @param {boolean} [isActivePage]
84-
* @param {models.SectionVisibility} [visibility]
97+
* @param {SectionVisibility} [visibility]
8598
* @hidden
8699
*/
87-
constructor(report: IReportNode, name: string, displayName?: string, isActivePage?: boolean, visibility?: models.SectionVisibility, defaultSize?: models.ICustomPageSize, defaultDisplayOption?: models.DisplayOption) {
100+
constructor(report: IReportNode, name: string, displayName?: string, isActivePage?: boolean, visibility?: SectionVisibility, defaultSize?: ICustomPageSize, defaultDisplayOption?: DisplayOption) {
88101
this.report = report;
89102
this.name = name;
90103
this.displayName = displayName;
@@ -102,31 +115,36 @@ export class Page implements IPageNode, IFilterable {
102115
* .then(filters => { ... });
103116
* ```
104117
*
105-
* @returns {(Promise<models.IFilter[]>)}
118+
* @returns {(Promise<IFilter[]>)}
106119
*/
107-
async getFilters(): Promise<models.IFilter[]> {
120+
async getFilters(): Promise<IFilter[]> {
108121
try {
109-
const response = await this.report.service.hpm.get<models.IFilter[]>(`/report/pages/${this.name}/filters`, { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow);
122+
const response = await this.report.service.hpm.get<IFilter[]>(`/report/pages/${this.name}/filters`, { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow);
110123
return response.body;
111124
} catch (response) {
112125
throw response.body;
113126
}
114127
}
115128

116129
/**
117-
* Delete the page from the report
130+
* Update the filters for the current page according to the operation: Add, replace all, replace by target or remove.
118131
*
119132
* ```javascript
120-
* // Delete the page from the report
121-
* page.delete();
133+
* page.updateFilters(FiltersOperations.Add, filters)
134+
* .catch(errors => { ... });
122135
* ```
123136
*
124-
* @returns {Promise<void>}
137+
* @param {(IFilter[])} filters
138+
* @returns {Promise<IHttpPostMessageResponse<void>>}
125139
*/
126-
async delete(): Promise<void> {
140+
async updateFilters(operation: FiltersOperations, filters?: IFilter[]): Promise<IHttpPostMessageResponse<void>> {
141+
const updateFiltersRequest: IUpdateFiltersRequest = {
142+
filtersOperation: operation,
143+
filters: filters as PageLevelFilters[]
144+
};
145+
127146
try {
128-
const response = await this.report.service.hpm.delete<void>(`/report/pages/${this.name}`, { }, { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow);
129-
return response.body;
147+
return await this.report.service.hpm.post<void>(`/report/pages/${this.name}/filters`, updateFiltersRequest, { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow);
130148
} catch (response) {
131149
throw response.body;
132150
}
@@ -142,46 +160,65 @@ export class Page implements IPageNode, IFilterable {
142160
* @returns {Promise<IHttpPostMessageResponse<void>>}
143161
*/
144162
async removeFilters(): Promise<IHttpPostMessageResponse<void>> {
145-
return await this.setFilters([]);
163+
return await this.updateFilters(FiltersOperations.RemoveAll);
146164
}
147165

148166
/**
149-
* Makes the current page the active page of the report.
167+
* Sets all filters on the current page.
150168
*
151169
* ```javascript
152-
* page.setActive();
170+
* page.setFilters(filters)
171+
* .catch(errors => { ... });
153172
* ```
154173
*
174+
* @param {(IFilter[])} filters
155175
* @returns {Promise<IHttpPostMessageResponse<void>>}
156176
*/
157-
async setActive(): Promise<IHttpPostMessageResponse<void>> {
158-
const page: models.IPage = {
159-
name: this.name,
160-
displayName: null,
161-
isActive: true
162-
};
177+
async setFilters(filters: IFilter[]): Promise<IHttpPostMessageResponse<void>> {
178+
try {
179+
return await this.report.service.hpm.put<void>(`/report/pages/${this.name}/filters`, filters, { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow);
180+
} catch (response) {
181+
throw response.body;
182+
}
183+
}
163184

185+
/**
186+
* Delete the page from the report
187+
*
188+
* ```javascript
189+
* // Delete the page from the report
190+
* page.delete();
191+
* ```
192+
*
193+
* @returns {Promise<void>}
194+
*/
195+
async delete(): Promise<void> {
164196
try {
165-
return await this.report.service.hpm.put<void>('/report/pages/active', page, { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow);
197+
const response = await this.report.service.hpm.delete<void>(`/report/pages/${this.name}`, {}, { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow);
198+
return response.body;
166199
} catch (response) {
167200
throw response.body;
168201
}
169202
}
170203

171204
/**
172-
* Sets all filters on the current page.
205+
* Makes the current page the active page of the report.
173206
*
174207
* ```javascript
175-
* page.setFilters(filters);
176-
* .catch(errors => { ... });
208+
* page.setActive();
177209
* ```
178210
*
179-
* @param {(models.IFilter[])} filters
180211
* @returns {Promise<IHttpPostMessageResponse<void>>}
181212
*/
182-
async setFilters(filters: models.IFilter[]): Promise<IHttpPostMessageResponse<void>> {
213+
async setActive(): Promise<IHttpPostMessageResponse<void>> {
214+
const page: IPage = {
215+
name: this.name,
216+
displayName: null,
217+
isActive: true
218+
};
219+
183220
try {
184-
return await this.report.service.hpm.put<void>(`/report/pages/${this.name}/filters`, filters, { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow);
221+
return await this.report.service.hpm.put<void>('/report/pages/active', page, { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow);
185222
} catch (response) {
186223
throw response.body;
187224
}
@@ -197,9 +234,9 @@ export class Page implements IPageNode, IFilterable {
197234
* @returns {Promise<IHttpPostMessageResponse<void>>}
198235
*/
199236
async setDisplayName(displayName: string): Promise<IHttpPostMessageResponse<void>> {
200-
const page: models.IPage = {
237+
const page: IPage = {
201238
name: this.name,
202-
displayName,
239+
displayName: displayName,
203240
};
204241

205242
try {
@@ -220,19 +257,17 @@ export class Page implements IPageNode, IFilterable {
220257
* @returns {Promise<VisualDescriptor[]>}
221258
*/
222259
async getVisuals(): Promise<VisualDescriptor[]> {
223-
if (utils.isRDLEmbed(this.report.config.embedUrl)) {
224-
return Promise.reject(errors.APINotSupportedForRDLError);
260+
if (isRDLEmbed(this.report.config.embedUrl)) {
261+
return Promise.reject(APINotSupportedForRDLError);
225262
}
226263

227264
try {
228-
const response = await this.report.service.hpm.get<models.IVisual[]>(`/report/pages/${this.name}/visuals`, { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow);
265+
const response = await this.report.service.hpm.get<IVisual[]>(`/report/pages/${this.name}/visuals`, { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow);
229266
return response.body
230-
.map(visual => {
231-
return new VisualDescriptor(this, visual.name, visual.title, visual.type, visual.layout);
232-
});
233-
} catch (response) {
234-
throw response.body;
235-
}
267+
.map(visual => new VisualDescriptor(this, visual.name, visual.title, visual.type, visual.layout));
268+
} catch (response) {
269+
throw response.body;
270+
}
236271
}
237272

238273
/**
@@ -246,16 +281,16 @@ export class Page implements IPageNode, IFilterable {
246281
* @returns {(Promise<boolean>)}
247282
*/
248283
async hasLayout(layoutType): Promise<boolean> {
249-
if (utils.isRDLEmbed(this.report.config.embedUrl)) {
250-
return Promise.reject(errors.APINotSupportedForRDLError);
284+
if (isRDLEmbed(this.report.config.embedUrl)) {
285+
return Promise.reject(APINotSupportedForRDLError);
251286
}
252287

253-
let layoutTypeEnum = models.LayoutType[layoutType];
288+
const layoutTypeEnum = LayoutType[layoutType];
254289
try {
255290
const response = await this.report.service.hpm.get<boolean>(`/report/pages/${this.name}/layoutTypes/${layoutTypeEnum}`, { uid: this.report.config.uniqueId }, this.report.iframe.contentWindow);
256291
return response.body;
257292
} catch (response) {
258293
throw response.body;
259294
}
260295
}
261-
}
296+
}

0 commit comments

Comments
 (0)