Add ReadMe.md; Compare jsonFilters to judge restore or common
This commit is contained in:
parent
3d759644d1
commit
ad38c05613
22
ReadMe.md
Normal file
22
ReadMe.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# A utility slicer for Power Bi
|
||||||
|
Assign default selection to this slicer by messures, just use DAX!
|
||||||
|
## Functionalities
|
||||||
|
* Implemented
|
||||||
|
1. Dropdown-slicer for text field
|
||||||
|
1. Use DAX to assign **single** default selected items to the dropdown-slicer
|
||||||
|
1. Support async slicers
|
||||||
|
* Planned
|
||||||
|
1. List-slicer for text field
|
||||||
|
1. Use DAX to assign **one** default selected items to the list-slicer
|
||||||
|
1. Use DAX to assign **multiple** default selected items to the dropdown-slicer and list-slicer
|
||||||
|
1. Range-slicer for number field
|
||||||
|
1. Use DAX to assign default selected range to the range-slicer
|
||||||
|
1. Single-date-slicer for datetime field
|
||||||
|
1. Use DAX to assign default selected date to the single-date-slicer
|
||||||
|
1. Period-slicer for datetime field
|
||||||
|
1. Use DAX to assign default selected period to the period-slicer
|
||||||
|
## Known issures
|
||||||
|
1. Slicer components for number field and datetime field are in developing, just slicer for text field is usable now
|
||||||
|
1. The outline setting has no effectivity on dropdown items
|
||||||
|
1. I can't change background-color of dropdown items
|
||||||
|
1. This slicer wouldn't support bookmarks
|
5
package-lock.json
generated
5
package-lock.json
generated
@ -905,6 +905,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/powerbi-visuals-utils-dataviewutils/-/powerbi-visuals-utils-dataviewutils-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/powerbi-visuals-utils-dataviewutils/-/powerbi-visuals-utils-dataviewutils-2.2.1.tgz",
|
||||||
"integrity": "sha512-Ai+TM1gj6DpAsNbn0IhOwUCAPfcaH4Z7y6Ow2OwAfbxNpELwQSF0S8D+vlJN2AoqV/ruQhnEngUC88mMFNyvJQ=="
|
"integrity": "sha512-Ai+TM1gj6DpAsNbn0IhOwUCAPfcaH4Z7y6Ow2OwAfbxNpELwQSF0S8D+vlJN2AoqV/ruQhnEngUC88mMFNyvJQ=="
|
||||||
},
|
},
|
||||||
|
"powerbi-visuals-utils-typeutils": {
|
||||||
|
"version": "2.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/powerbi-visuals-utils-typeutils/-/powerbi-visuals-utils-typeutils-2.2.1.tgz",
|
||||||
|
"integrity": "sha512-xm5xNBVudCiU9ZZggsLlpHr+a4bnHtgw6Cy1UtNM/zILtOE2HUamjw+yZovLe6YNov4N2EaCmPO8XPhcXkuz+A=="
|
||||||
|
},
|
||||||
"process-nextick-args": {
|
"process-nextick-args": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
"d3": "5.12.0",
|
"d3": "5.12.0",
|
||||||
"powerbi-models": "^1.3.3",
|
"powerbi-models": "^1.3.3",
|
||||||
"powerbi-visuals-api": "~2.6.1",
|
"powerbi-visuals-api": "~2.6.1",
|
||||||
"powerbi-visuals-utils-dataviewutils": "2.2.1"
|
"powerbi-visuals-utils-dataviewutils": "2.2.1",
|
||||||
|
"powerbi-visuals-utils-typeutils": "^2.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^13.13.4",
|
"@types/node": "^13.13.4",
|
||||||
|
@ -11,12 +11,17 @@ import { select, json } from "d3";
|
|||||||
export class FilterManager implements IFilterManager{
|
export class FilterManager implements IFilterManager{
|
||||||
private target: models.IFilterColumnTarget={table:'',column:''};
|
private target: models.IFilterColumnTarget={table:'',column:''};
|
||||||
private host:IVisualHost;
|
private host:IVisualHost;
|
||||||
private jsonFilter:powerbi.IFilter;
|
private _jsonFilter:powerbi.IFilter;
|
||||||
|
|
||||||
|
public get jsonFilter() : powerbi.IFilter {
|
||||||
|
return this._jsonFilter;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(host:IVisualHost){
|
constructor(host:IVisualHost){
|
||||||
this.host=host;
|
this.host=host;
|
||||||
}
|
}
|
||||||
setFilter(jsonFilter: powerbi.IFilter,applyNow:boolean): void {
|
setFilter(jsonFilter: powerbi.IFilter,applyNow:boolean): void {
|
||||||
this.jsonFilter=jsonFilter;
|
this._jsonFilter=jsonFilter;
|
||||||
if(applyNow){
|
if(applyNow){
|
||||||
this.applyJsonFilter();
|
this.applyJsonFilter();
|
||||||
}
|
}
|
||||||
@ -24,7 +29,7 @@ export class FilterManager implements IFilterManager{
|
|||||||
|
|
||||||
public applyJsonFilter():void{
|
public applyJsonFilter():void{
|
||||||
console.debug('filter manager applyJsonFilter start');
|
console.debug('filter manager applyJsonFilter start');
|
||||||
this.host.applyJsonFilter(this.jsonFilter,'general','filter',powerbi.FilterAction.merge);
|
this.host.applyJsonFilter(this._jsonFilter,'general','filter',powerbi.FilterAction.merge);
|
||||||
console.debug('filter manager applyJsonFilter end');
|
console.debug('filter manager applyJsonFilter end');
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -61,7 +66,7 @@ export class FilterManager implements IFilterManager{
|
|||||||
"values": selection
|
"values": selection
|
||||||
}
|
}
|
||||||
console.debug("jsonFilter:",jsonFilter);
|
console.debug("jsonFilter:",jsonFilter);
|
||||||
this.jsonFilter=jsonFilter;
|
this._jsonFilter=jsonFilter;
|
||||||
if(applyNow){
|
if(applyNow){
|
||||||
this.applyJsonFilter();
|
this.applyJsonFilter();
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import powerbi from "powerbi-visuals-api";
|
|||||||
import * as d3 from "d3";
|
import * as d3 from "d3";
|
||||||
import { selection } from "d3";
|
import { selection } from "d3";
|
||||||
type Selection<T extends d3.BaseType> = d3.Selection<T, any, any, any>;
|
type Selection<T extends d3.BaseType> = d3.Selection<T, any, any, any>;
|
||||||
|
import {pixelConverter} from "powerbi-visuals-utils-typeutils";
|
||||||
|
|
||||||
export class DropDownSelector extends Selector {
|
export class DropDownSelector extends Selector {
|
||||||
public select(items: string[]): void {
|
public select(items: string[]): void {
|
||||||
@ -25,7 +26,7 @@ export class DropDownSelector extends Selector {
|
|||||||
this.dropDown.style('background-color', itemsSetting.backgroundColor)
|
this.dropDown.style('background-color', itemsSetting.backgroundColor)
|
||||||
.attr('postion','absolute')
|
.attr('postion','absolute')
|
||||||
.style('color', itemsSetting.fontColor)
|
.style('color', itemsSetting.fontColor)
|
||||||
.style('font-size', itemsSetting.textSize + 'px')
|
.style('font-size',pixelConverter.fromPointToPixel(itemsSetting.textSize) + 'px')
|
||||||
.style('width', (width - 10) + 'px')
|
.style('width', (width - 10) + 'px')
|
||||||
.style('border-style', settings.Enums.getOutlineStyle(itemsSetting.outline))
|
.style('border-style', settings.Enums.getOutlineStyle(itemsSetting.outline))
|
||||||
.style('border-width', '2px')
|
.style('border-width', '2px')
|
||||||
@ -37,8 +38,7 @@ export class DropDownSelector extends Selector {
|
|||||||
.style('width', (width - 10) + 'px')
|
.style('width', (width - 10) + 'px')
|
||||||
.style('border-style', settings.Enums.getOutlineStyle(itemsSetting.outline))
|
.style('border-style', settings.Enums.getOutlineStyle(itemsSetting.outline))
|
||||||
.style('border-width', '2px')
|
.style('border-width', '2px')
|
||||||
.style('border-color', 'black')
|
.style('border-color', 'black');
|
||||||
.style('maxHeight','200px');
|
|
||||||
}
|
}
|
||||||
console.debug('dropDownSelector updateFormat end');
|
console.debug('dropDownSelector updateFormat end');
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ export class DropDownSelector extends Selector {
|
|||||||
protected createView(container: Selection<HTMLDivElement>) {
|
protected createView(container: Selection<HTMLDivElement>) {
|
||||||
console.debug('dropDownViewManager', 'createView start');
|
console.debug('dropDownViewManager', 'createView start');
|
||||||
this.container = container;
|
this.container = container;
|
||||||
this.dropDown = this.container.append("select").classed("dropDown-selector", true).classed("selector", true);//.attr("multiple",false);
|
this.dropDown = this.container.append("select").classed("dropDown-selector", true).classed("selector", true);//.attr('multiple',true);
|
||||||
let dropDownSelector=this;
|
let dropDownSelector=this;
|
||||||
//on change, filter
|
//on change, filter
|
||||||
this.dropDown.on("input change", function () {
|
this.dropDown.on("input change", function () {
|
||||||
@ -95,6 +95,7 @@ export class DropDownSelector extends Selector {
|
|||||||
}
|
}
|
||||||
console.debug("this", this.selectedOptions);
|
console.debug("this", this.selectedOptions);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.debug('dropDownViewManager', 'createView end');
|
console.debug('dropDownViewManager', 'createView end');
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -116,6 +117,7 @@ export class DropDownSelector extends Selector {
|
|||||||
newDefaultSelect = defaultSelect.values[0].toString();
|
newDefaultSelect = defaultSelect.values[0].toString();
|
||||||
console.debug('newDefaultSelect:', newDefaultSelect);
|
console.debug('newDefaultSelect:', newDefaultSelect);
|
||||||
}
|
}
|
||||||
|
//let values=field.values
|
||||||
let options: d3.Selection<HTMLOptionElement, powerbi.PrimitiveValue, HTMLSelectElement, any> = <d3.Selection<HTMLOptionElement, powerbi.PrimitiveValue, HTMLSelectElement, any>>this.dropDown.selectAll("option").data(field.values, function (d) { return d.toString(); });//map data
|
let options: d3.Selection<HTMLOptionElement, powerbi.PrimitiveValue, HTMLSelectElement, any> = <d3.Selection<HTMLOptionElement, powerbi.PrimitiveValue, HTMLSelectElement, any>>this.dropDown.selectAll("option").data(field.values, function (d) { return d.toString(); });//map data
|
||||||
options.exit().remove();//delete
|
options.exit().remove();//delete
|
||||||
|
|
||||||
@ -125,6 +127,7 @@ export class DropDownSelector extends Selector {
|
|||||||
.text(function (d) { return d.toString(); })
|
.text(function (d) { return d.toString(); })
|
||||||
.attr('label', function (d) { return d.toString(); })
|
.attr('label', function (d) { return d.toString(); })
|
||||||
.classed('dropDown-option', true)
|
.classed('dropDown-option', true)
|
||||||
|
.attr('title',function (d) { return d.toString(); })
|
||||||
.merge(options)
|
.merge(options)
|
||||||
.attr("selected", function (d) {
|
.attr("selected", function (d) {
|
||||||
console.debug('d.toString():', d.toString());
|
console.debug('d.toString():', d.toString());
|
||||||
@ -134,10 +137,14 @@ export class DropDownSelector extends Selector {
|
|||||||
console.debug('Set defaultSelection end');
|
console.debug('Set defaultSelection end');
|
||||||
} else {
|
} else {
|
||||||
console.debug('defaultSelection not reset, start update options');
|
console.debug('defaultSelection not reset, start update options');
|
||||||
options=options.enter().append("option").text(function (d) { return d.toString(); }).attr('label', function (d) { return d.toString(); }).classed('dropDown-option', true).merge(options);//add
|
options=options.enter().append("option")
|
||||||
|
.text(function (d) { return d.toString(); })
|
||||||
|
.attr('label', function (d) { return d.toString(); })
|
||||||
|
.attr('title',function (d) { return d.toString(); })
|
||||||
|
.attr('label', function (d) { return d.toString(); }).classed('dropDown-option', true).merge(options);//add
|
||||||
console.debug('defaultSelection not reset, end update options');
|
console.debug('defaultSelection not reset, end update options');
|
||||||
}
|
}
|
||||||
|
|
||||||
let selectedValues: string[] = [];
|
let selectedValues: string[] = [];
|
||||||
this.dropDown.selectAll('option').each(function(d,i){
|
this.dropDown.selectAll('option').each(function(d,i){
|
||||||
let option=d3.select(this);
|
let option=d3.select(this);
|
||||||
|
@ -84,7 +84,6 @@ export class Visual implements IVisual {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//First, create the filterManager
|
//First, create the filterManager
|
||||||
this.filterManager=ManagerFactory.CreateFilterManager(FilterManager,options.host);
|
this.filterManager=ManagerFactory.CreateFilterManager(FilterManager,options.host);
|
||||||
//Then, layoutManager and selectorManager, both use the filterManager
|
//Then, layoutManager and selectorManager, both use the filterManager
|
||||||
@ -142,18 +141,35 @@ export class Visual implements IVisual {
|
|||||||
this.selectorManager.updateData(field,defaultSelect,defaultStart,defaultEnd);
|
this.selectorManager.updateData(field,defaultSelect,defaultStart,defaultEnd);
|
||||||
this.selectorManager.updateFormat(this.settings,width,height);
|
this.selectorManager.updateFormat(this.settings,width,height);
|
||||||
console.debug("previous filter",JSON.stringify(options.jsonFilters));
|
console.debug("previous filter",JSON.stringify(options.jsonFilters));
|
||||||
if(this.isFirstUpdate&&options.jsonFilters&&options.jsonFilters[0]){
|
/*
|
||||||
//Sync slicers
|
Compare two jsonFilters(filterManager.jsonFilter and options.jsonFilters[0]).
|
||||||
console.debug('Sync slicers init end');
|
Use method JSON.stringify.
|
||||||
this.filterManager.setFilter(options.jsonFilters[0],false);
|
1. filterManager.jsonFilter is null, options.jsonFilter[0] is null
|
||||||
this.selectorManager.select(options.jsonFilters[0]['values'])
|
Don't restore
|
||||||
console.debug('Sync slicers init end');
|
2. filterManager.jsonFilter is Null, options.jsonFilter[0] is not null
|
||||||
|
Restore
|
||||||
|
3. filterManager.jsonFilter is not null, options.jsonFilter[0] is null
|
||||||
|
Don't restore
|
||||||
|
4. filterManager.jsonFilter != options.jsonFilter[0]
|
||||||
|
Restore
|
||||||
|
5. filterManager.jsonFilter == options.jsonFilter[0]
|
||||||
|
Don't restore
|
||||||
|
*/
|
||||||
|
if(options.jsonFilters&&options.jsonFilters[0]&&this.isFirstUpdate){
|
||||||
|
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');
|
||||||
|
}//end if
|
||||||
}else{
|
}else{
|
||||||
console.debug('Neednt init a sync slicer');
|
console.debug('Neednt init a sync slicer or restore a bookmark');
|
||||||
}
|
}
|
||||||
console.debug("isFirstUpdate:",this.isFirstUpdate);
|
|
||||||
this.isFirstUpdate=false;
|
|
||||||
console.debug('visual update end');
|
console.debug('visual update end');
|
||||||
|
this.isFirstUpdate=false;
|
||||||
this.filterManager.applyJsonFilter();
|
this.filterManager.applyJsonFilter();
|
||||||
this.events.renderingFinished(options);
|
this.events.renderingFinished(options);
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ export interface ISelectorManagerConstructor{
|
|||||||
|
|
||||||
//IFilterManager
|
//IFilterManager
|
||||||
export interface IFilterManager{
|
export interface IFilterManager{
|
||||||
|
jsonFilter:powerbi.IFilter;
|
||||||
update(field:powerbi.DataViewCategoryColumn):void;
|
update(field:powerbi.DataViewCategoryColumn):void;
|
||||||
setFilter_String(selection:string[],applyNow:boolean):void;
|
setFilter_String(selection:string[],applyNow:boolean):void;
|
||||||
setFilter(jsonFilter:powerbi.IFilter,applyNow:boolean):void;
|
setFilter(jsonFilter:powerbi.IFilter,applyNow:boolean):void;
|
||||||
|
Loading…
Reference in New Issue
Block a user