Merge pull request #28 from Microsoft/add_support_for_basic_filter_with_values_as_array_of_tuples

Add support for basic filter with values as array of tuples
This commit is contained in:
Noa 2016-12-22 01:22:14 -08:00 коммит произвёл GitHub
Родитель 76e5181919 7ba436ec17
Коммит 0de0170131
3 изменённых файлов: 110 добавлений и 3 удалений

Просмотреть файл

@ -1,6 +1,6 @@
{ {
"name": "powerbi-models", "name": "powerbi-models",
"version": "0.10.2", "version": "0.10.3",
"description": "Contains JavaScript & TypeScript object models for Microsoft Power BI JavaScript SDK. For each model there is a TypeScript interface, a json schema definitions, and a validation function to ensure and object is valid.", "description": "Contains JavaScript & TypeScript object models for Microsoft Power BI JavaScript SDK. For each model there is a TypeScript interface, a json schema definitions, and a validation function to ensure and object is valid.",
"main": "dist/models.js", "main": "dist/models.js",
"typings": "dist/models.d.ts", "typings": "dist/models.d.ts",

Просмотреть файл

@ -126,6 +126,10 @@ export interface IFilterColumnTarget extends IBaseFilterTarget {
column: string; column: string;
} }
export interface IFilterKeyColumnsTarget extends IFilterColumnTarget {
keys: string[];
}
export interface IFilterHierarchyTarget extends IBaseFilterTarget { export interface IFilterHierarchyTarget extends IBaseFilterTarget {
hierarchy: string; hierarchy: string;
hierarchyLevel: string; hierarchyLevel: string;
@ -147,6 +151,11 @@ export interface IBasicFilter extends IFilter {
values: (string | number | boolean)[]; values: (string | number | boolean)[];
} }
export interface IBasicFilterWithKeys extends IBasicFilter {
target: IFilterKeyColumnsTarget;
keyValues: (string | number | boolean)[][];
}
export type BasicFilterOperators = "In" | "NotIn" | "All"; export type BasicFilterOperators = "In" | "NotIn" | "All";
export type AdvancedFilterLogicalOperators = "And" | "Or"; export type AdvancedFilterLogicalOperators = "And" | "Or";
export type AdvancedFilterConditionOperators = "None" | "LessThan" | "LessThanOrEqual" | "GreaterThan" | "GreaterThanOrEqual" | "Contains" | "DoesNotContain" | "StartsWith" | "DoesNotStartWith" | "Is" | "IsNot" | "IsBlank" | "IsNotBlank"; export type AdvancedFilterConditionOperators = "None" | "LessThan" | "LessThanOrEqual" | "GreaterThan" | "GreaterThanOrEqual" | "Contains" | "DoesNotContain" | "StartsWith" | "DoesNotStartWith" | "Is" | "IsNot" | "IsBlank" | "IsNotBlank";
@ -167,6 +176,14 @@ export enum FilterType {
Unknown Unknown
} }
export function isFilterKeyColumnsTarget(target: IFilterTarget): boolean {
return isColumn(target) && !!(<IFilterKeyColumnsTarget>target).keys;
}
export function isBasicFilterWithKeys(filter: IFilter): boolean {
return getFilterType(filter) === FilterType.Basic && !!(<IBasicFilterWithKeys>filter).keyValues;
}
export function getFilterType(filter: IFilter): FilterType { export function getFilterType(filter: IFilter): FilterType {
const basicFilter = filter as IBasicFilter; const basicFilter = filter as IBasicFilter;
const advancedFilter = filter as IAdvancedFilter; const advancedFilter = filter as IAdvancedFilter;
@ -222,6 +239,7 @@ export class BasicFilter extends Filter {
static schemaUrl: string = "http://powerbi.com/product/schema#basic"; static schemaUrl: string = "http://powerbi.com/product/schema#basic";
operator: BasicFilterOperators; operator: BasicFilterOperators;
values: (string | number | boolean)[]; values: (string | number | boolean)[];
keyValues: (string | number | boolean)[][];
constructor( constructor(
target: IFilterTarget, target: IFilterTarget,
@ -233,7 +251,7 @@ export class BasicFilter extends Filter {
this.schemaUrl = BasicFilter.schemaUrl; this.schemaUrl = BasicFilter.schemaUrl;
if (values.length === 0 && operator !== "All") { if (values.length === 0 && operator !== "All") {
throw new Error(`values must be a non-empty array unless your operator is "All". You passed: ${values}`); throw new Error(`values must be a non-empty array unless your operator is "All".`);
} }
/** /**
@ -259,6 +277,47 @@ export class BasicFilter extends Filter {
} }
} }
export class BasicFilterWithKeys extends BasicFilter {
keyValues: (string | number | boolean)[][];
target: IFilterKeyColumnsTarget;
constructor(
target: IFilterKeyColumnsTarget,
operator: BasicFilterOperators,
values: ((string | number | boolean) | (string | number | boolean)[]),
keyValues: (string | number | boolean)[][]
) {
super(target, operator, values);
this.keyValues = keyValues;
this.target = target;
let numberOfKeys = target.keys ? target.keys.length : 0;
if (numberOfKeys > 0 && !keyValues) {
throw new Error(`You shold pass the values to be filtered for each key. You passed: no values and ${numberOfKeys} keys`);
}
if (numberOfKeys === 0 && keyValues && keyValues.length > 0) {
throw new Error(`You passed key values but your target object doesn't contain the keys to be filtered`);
}
for (let i = 0 ; i < this.keyValues.length ; i++) {
if (this.keyValues[i] ) {
let lengthOfArray = this.keyValues[i].length;
if (lengthOfArray !== numberOfKeys) {
throw new Error(`Each tuple of key values should contain a value for each of the keys. You passed: ${lengthOfArray} values and ${numberOfKeys} keys`);
}
}
}
}
toJSON(): IBasicFilter {
const filter = <IBasicFilterWithKeys>super.toJSON();
filter.keyValues = this.keyValues;
return filter;
}
}
export class AdvancedFilter extends Filter { export class AdvancedFilter extends Filter {
static schemaUrl: string = "http://powerbi.com/product/schema#advanced"; static schemaUrl: string = "http://powerbi.com/product/schema#advanced";

Просмотреть файл

@ -512,6 +512,30 @@ describe("Unit | Filters", function () {
expect(basicFilter.values).toEqual(values); expect(basicFilter.values).toEqual(values);
}); });
it("should accept values as an array of tuples", function () {
// Arrange
const values = [1, 2];
const keyValues = [[1, 2], [3,4]];
// Act
const basicFilter = new models.BasicFilterWithKeys({ table: "t", column: "c" , keys: ["1", "2"]}, "In", values, keyValues);
// Assert
expect(basicFilter.values).toEqual(values);
});
it("should throw an exception when values are an array of tuples, but tuples length is different than keys length", function () {
// Arrange
const values = [1, 2];
const keyValues = [[1, 2], [3,4]];
// Act
const attemptToCreateFilter = () => {
return new models.BasicFilterWithKeys({ table: "t", column: "c" , keys: ["1"]}, "In", values, keyValues);
};
expect(attemptToCreateFilter).toThrowError();
});
it("should return valid json format when toJSON is called", function () { it("should return valid json format when toJSON is called", function () {
// Arrange // Arrange
const expectedFilter: models.IBasicFilter = { const expectedFilter: models.IBasicFilter = {
@ -679,11 +703,12 @@ describe("Unit | Filters", function () {
}); });
}); });
describe('determine filter type', function () { describe('determine types', function () {
it('getFilterType should return type of filter given a filter object', function () { it('getFilterType should return type of filter given a filter object', function () {
// Arrange // Arrange
const testData = { const testData = {
basicFilter: new models.BasicFilter({ table: "a", column: "b" }, "In", ["x", "y"]), basicFilter: new models.BasicFilter({ table: "a", column: "b" }, "In", ["x", "y"]),
basicFilterWithKeys: new models.BasicFilterWithKeys({ table: "a", column: "b", keys: ["1", "2"] }, "In", ["x1", 1], [["x1", 1], ["y2",2]]),
advancedFilter: new models.AdvancedFilter({ table: "a", column: "b" }, "And", advancedFilter: new models.AdvancedFilter({ table: "a", column: "b" }, "And",
{ operator: "Contains", value: "x" }, { operator: "Contains", value: "x" },
{ operator: "Contains", value: "x" } { operator: "Contains", value: "x" }
@ -695,8 +720,31 @@ describe("Unit | Filters", function () {
// Assert // Assert
expect(models.getFilterType(testData.basicFilter.toJSON())).toBe(models.FilterType.Basic); expect(models.getFilterType(testData.basicFilter.toJSON())).toBe(models.FilterType.Basic);
expect(models.getFilterType(testData.basicFilterWithKeys.toJSON())).toBe(models.FilterType.Basic);
expect(models.getFilterType(testData.advancedFilter.toJSON())).toBe(models.FilterType.Advanced); expect(models.getFilterType(testData.advancedFilter.toJSON())).toBe(models.FilterType.Advanced);
expect(models.getFilterType(testData.nonFilter)).toBe(models.FilterType.Unknown); expect(models.getFilterType(testData.nonFilter)).toBe(models.FilterType.Unknown);
}); });
it('isFilterKeyColumnsTarget should return the correct response', function () {
// Arrange
let filterKeyColumnsTarget = { table: "a", column: "b", keys: ["key1"] };
let filterColumnTarget = { table: "a", column: "b"};
// Assert
expect(models.isFilterKeyColumnsTarget(filterKeyColumnsTarget)).toBeTruthy();
expect(models.isFilterKeyColumnsTarget(filterColumnTarget)).toBeFalsy();
});
it('isBasicFilterWithKeys should return the correct response', function () {
// Arrange
const testData = {
basicFilter: new models.BasicFilter({ table: "a", column: "b" }, "In", ["x", "y"]),
basicFilterWithKeys: new models.BasicFilterWithKeys({ table: "a", column: "b", keys: ["1", "2"] }, "In", ["x1", 1], [["x1", 1], ["y2",2]]),
};
// Assert
expect(models.isBasicFilterWithKeys(testData.basicFilter.toJSON())).toBeFalsy();
expect(models.isBasicFilterWithKeys(testData.basicFilterWithKeys.toJSON())).toBeTruthy();
});
}); });
}); });