diff --git a/ReadMe.md b/ReadMe.md index 1372c2f..24bbcba 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -1,5 +1,9 @@ # A utility slicer for Power Bi Assign default selection to this slicer by messures, just use DAX! +## Tutorial +1. Click the top right corner of this slicer +1. Click "Edit" +1. Save&publish the report ## Functionalities * Implemented 1. Dropdown-slicer for text field diff --git a/capabilities.json b/capabilities.json index 395f1ae..55a80e5 100644 --- a/capabilities.json +++ b/capabilities.json @@ -1,5 +1,6 @@ { "supportsSynchronizingFilterState": true, + "advancedEditModeSupport": 1, "dataRoles": [ { "displayName": "Field", @@ -134,6 +135,22 @@ ] } }, + "outlineColor":{ + "displayName": "Outline color", + "type": { + "fill": { + "solid": { + "color":true + } + } + } + }, + "outlineWeight":{ + "displayName": "Outline weight", + "type":{ + "integer": true + } + }, "showAllDataPoints": { "displayName": "Show all", "type": { diff --git a/src/managers/filterManager.ts b/src/managers/filterManager.ts index 94c54b8..d8cd37c 100644 --- a/src/managers/filterManager.ts +++ b/src/managers/filterManager.ts @@ -11,16 +11,26 @@ import { select, json } from "d3"; export class FilterManager implements IFilterManager{ private target: models.IFilterColumnTarget={table:'',column:''}; private host:IVisualHost; - private _jsonFilter:powerbi.IFilter; + private _jsonFilter:models.IAdvancedFilter; - public get jsonFilter() : powerbi.IFilter { + public get jsonFilter() : models.IAdvancedFilter { return this._jsonFilter; } - + public get advancedEditModeMark():string{ + return 'SyinpoSlicer_AdvancedEditMode_'+this.inAdvancedEditMode; + } constructor(host:IVisualHost){ this.host=host; } - setFilter(jsonFilter: powerbi.IFilter,applyNow:boolean): void { + _inAdvancedEditMode: boolean=false; + public set inAdvancedEditMode(newValue:boolean){ + this._inAdvancedEditMode=this._inAdvancedEditMode?true:newValue; + } + public get inAdvancedEditMode():boolean{ + return this._inAdvancedEditMode; + } + setFilter(jsonFilter:models.IAdvancedFilter,applyNow:boolean): void { + jsonFilter.conditions[0].value=this.advancedEditModeMark this._jsonFilter=jsonFilter; if(applyNow){ this.applyJsonFilter(); @@ -30,6 +40,7 @@ export class FilterManager implements IFilterManager{ public applyJsonFilter():void{ console.debug('filter manager applyJsonFilter start'); this.host.applyJsonFilter(this._jsonFilter,'general','filter',powerbi.FilterAction.merge); + console.debug(this.jsonFilter); console.debug('filter manager applyJsonFilter end'); } @@ -58,12 +69,25 @@ export class FilterManager implements IFilterManager{ } public setFilter_String(selection:string[],applyNow:boolean):void{ console.debug("setFilter_String start:",selection); - let jsonFilter:models.IBasicFilter={ - "$schema": "http://powerbi.com/product/schema#basic", + let conditions:models.IAdvancedFilterCondition[]=[]; + + conditions.push({ + "operator":"StartsWith", + "value":this.advancedEditModeMark + }); + + selection.forEach(function(item){ + conditions.push({ + "operator":"Is", + "value":item + }); + }); + let jsonFilter:models.IAdvancedFilter={ + "$schema": "http://powerbi.com/product/schema#advanced", "target": this.target, - "filterType": models.FilterType.Basic, - "operator":"In", - "values": selection + "filterType": models.FilterType.Advanced, + "conditions":conditions, + "logicalOperator":"Or" } console.debug("jsonFilter:",jsonFilter); this._jsonFilter=jsonFilter; diff --git a/src/managers/selectors/dropDownSelector.ts b/src/managers/selectors/dropDownSelector.ts index 16624f5..488a3f7 100644 --- a/src/managers/selectors/dropDownSelector.ts +++ b/src/managers/selectors/dropDownSelector.ts @@ -32,10 +32,8 @@ export class DropDownSelector extends Selector { .style('border-width', '2px') .style('border-color', 'black'); this.dropDown.selectAll('option').style('background-color', itemsSetting.backgroundColor) - .style('padding','0px 0px') .style('color', itemsSetting.fontColor) - .style('font-size', itemsSetting.textSize + 'px') - .style('width', (width - 10) + 'px') + .style('font-size', pixelConverter.fromPointToPixel(itemsSetting.textSize) + 'px') .style('border-style', settings.Enums.getOutlineStyle(itemsSetting.outline)) .style('border-width', '2px') .style('border-color', 'black'); diff --git a/src/settings/slicerHeaderSetting.ts b/src/settings/slicerHeaderSetting.ts index 7a7c7a1..1fb74e4 100644 --- a/src/settings/slicerHeaderSetting.ts +++ b/src/settings/slicerHeaderSetting.ts @@ -6,4 +6,6 @@ export class SlicerHeaderSetting{ public fontColor:string=''; public backgroundColor:string=''; public outline:enums.Outline=enums.Outline.None; + public outlineWeight:number=2; + public outlineColor:string="gray"; } diff --git a/src/visual/visual.ts b/src/visual/visual.ts index 8f635af..25a32a3 100644 --- a/src/visual/visual.ts +++ b/src/visual/visual.ts @@ -47,7 +47,7 @@ import { getMeasureIndexOfRole } from "powerbi-visuals-utils-dataviewutils/lib/d import { selector, json } from "d3"; import { debuglog } from "util"; import { EventEmitter } from "events"; - +import * as models from 'powerbi-models'; export class Visual implements IVisual { /* SelectorManager: a custom manager, used to manage dropDownSelector, listSelector, calendarSelector, and so on @@ -64,6 +64,7 @@ export class Visual implements IVisual { //private selectionManager:powerbi.extensibility.ISelectionManager; constructor(options: VisualConstructorOptions) { console.debug('Visual constructor start'); + console.debug('options:',options); this.events = options.host.eventService; if (document) { //this.selectionManager =options.host.createSelectionManager(); @@ -107,8 +108,10 @@ export class Visual implements IVisual { public update(options: VisualUpdateOptions) { console.debug('visual update start'); console.debug('id:',this.id); + console.debug('options:',options); //console.debug('operationKind',options.operationKind.toString()); this.events.renderingStarted(options); + this.filterManager.inAdvancedEditMode=options.editMode==powerbi.EditMode.Advanced this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]); let dataView=options.dataViews[0]; let field=dataView.categorical.categories[0]; @@ -159,11 +162,24 @@ export class Visual implements IVisual { console.debug('options.jsonFilters[0] is not null'); if((!this.filterManager.jsonFilter)|| (JSON.stringify(this.filterManager.jsonFilter)!=JSON.stringify(options.jsonFilters[0]))){ - //Sync slicers - console.debug('Sync slicers init or restore a bookmark start'); - this.filterManager.setFilter(options.jsonFilters[0],false); - this.selectorManager.select(options.jsonFilters[0]['values']) - console.debug('Sync slicers init or restore a bookmark end'); + console.debug('Two filter are different'); + let advancedFilter:models.IAdvancedFilter=options.jsonFilters[0] as models.IAdvancedFilter; + console.debug("Cast as advancedFilter:",advancedFilter); + if(advancedFilter.conditions[0].value=='SyinpoSlicer_AdvancedEditMode_true'){ + console.debug('previous filter is created in AdvancedEditMode'); + }else{ + //Sync slicers + console.debug('Sync slicers init or restore a bookmark start'); + this.filterManager.setFilter(advancedFilter,false); + let oldSelection:string[]=[]; + advancedFilter.conditions.map(function(condition,index){ + oldSelection.push(condition.value as string); + }); + this.selectorManager.select(oldSelection); + console.debug('Sync slicers init or restore a bookmark end'); + } + }else{ + console.debug('Two filter are equal'); }//end if }else{ console.debug('Neednt init a sync slicer or restore a bookmark'); diff --git a/src/visual/visualInterfaces.ts b/src/visual/visualInterfaces.ts index f467413..c4ec938 100644 --- a/src/visual/visualInterfaces.ts +++ b/src/visual/visualInterfaces.ts @@ -43,10 +43,11 @@ export interface ISelectorManagerConstructor{ //IFilterManager export interface IFilterManager{ - jsonFilter:powerbi.IFilter; + jsonFilter:models.IAdvancedFilter; + inAdvancedEditMode:boolean; update(field:powerbi.DataViewCategoryColumn):void; setFilter_String(selection:string[],applyNow:boolean):void; - setFilter(jsonFilter:powerbi.IFilter,applyNow:boolean):void; + setFilter(jsonFilter:models.IAdvancedFilter,applyNow:boolean):void; applyJsonFilter():void; clear():void; dispose():void;