From 82f4d1ecdc769df4c2a7c5ae7a93e01d6813de7a Mon Sep 17 00:00:00 2001 From: MuJianNan Date: Sun, 3 May 2020 02:27:08 +0800 Subject: [PATCH] The single dropdown work well(twice updatting is not a question). Now adding formatting --- capabilities.json | 152 +++++++++++++++++++++++++++- package-lock.json | 47 --------- package.json | 10 +- src/managers/filterManager.ts | 7 +- src/managers/layoutManager.ts | 4 +- src/managers/managerFactory.ts | 1 + src/managers/selectorManager.ts | 41 ++++++-- src/settings/enums/index.ts | 1 + src/settings/enums/outline.ts | 4 + src/settings/index.ts | 4 + src/settings/itemsSetting.ts | 8 ++ src/settings/slicerHeaderSetting.ts | 9 ++ src/settings/visualSettings.ts | 18 +--- src/visual/visual.ts | 14 +-- src/visual/visualInterfaces.ts | 5 +- 15 files changed, 232 insertions(+), 93 deletions(-) create mode 100644 src/settings/enums/index.ts create mode 100644 src/settings/enums/outline.ts create mode 100644 src/settings/index.ts create mode 100644 src/settings/itemsSetting.ts create mode 100644 src/settings/slicerHeaderSetting.ts diff --git a/capabilities.json b/capabilities.json index e21e535..488097d 100644 --- a/capabilities.json +++ b/capabilities.json @@ -46,7 +46,7 @@ "objects": { "general": { "displayName": "General", - "displayNameKey": "formattingGeneral", + "displayNameKey": "Formatting-General", "properties": { "filter": { "type": { @@ -62,11 +62,12 @@ } } }, - "dataPoint": { - "displayName": "Data colors", + "slicerHeader": { + "displayName": "Slicer header", + "displayNameKey":"Formatting-SicerHeader", "properties": { - "defaultColor": { - "displayName": "Default color", + "fontColor": { + "displayName": "Font color", "type": { "fill": { "solid": { @@ -75,6 +76,63 @@ } } }, + "backgroundColor": { + "displayName": "Background color", + "type": { + "fill": { + "solid": { + "color": true + } + } + } + }, + "outline":{ + "displayName": "Outline", + "type": { + "enumeration": [ + { + "value": "0", + "displayName": "None", + "displayNameKey": "Formatting_Outline_None" + }, + { + "value": "1", + "displayName": "Bottom only", + "displayNameKey": "Formatting_Outline_BottomOnly" + }, + { + "value": "2", + "displayName": "Top only", + "displayNameKey": "Formatting_Outline_TopOnly" + }, + { + "value": "3", + "displayName": "Left only", + "displayNameKey": "Formatting_Outline_LeftOnly" + }, + { + "value": "4", + "displayName": "Right only", + "displayNameKey": "Formatting_Outline_RightOnly" + }, + { + "value": "5", + "displayName": "Top + bottom", + "displayNameKey": "Formatting_Outline_TopAndBottom" + }, + { + "value": "6", + "displayName": "Left + right", + "displayNameKey": "Formatting_Outline_LeftAndRight" + }, + { + "value": "7", + "displayName": "Frame", + "displayNameKey": "Formatting_Outline_Frame" + } + ] + } + }, "showAllDataPoints": { "displayName": "Show all", "type": { @@ -106,6 +164,90 @@ } } } + }, + "items":{ + "displayName": "Items", + "displayNameKey": "Formatting_Items", + "properties": { + "fontColor": { + "displayName": "Font color", + "displayNameKey": "Formatting_Items_FontColor", + "type": { + "fill": { + "solid": { + "color": true + } + } + } + }, + "backgroundColor": { + "displayName": "Background color", + "displayNameKey": "Formatting_Items_BackgroundColor", + + "type": { + "fill": { + "solid": { + "color": true + } + } + } + }, + "outline":{ + "displayName": "Outline", + "displayNameKey": "Formatting_Items_Outline", + "type": { + "enumeration": [ + { + "value": "0", + "displayName": "None", + "displayNameKey": "Formatting_Outline_None" + }, + { + "value": "1", + "displayName": "Bottom only", + "displayNameKey": "Formatting_Outline_BottomOnly" + }, + { + "value": "2", + "displayName": "Top only", + "displayNameKey": "Formatting_Outline_TopOnly" + }, + { + "value": "3", + "displayName": "Left only", + "displayNameKey": "Formatting_Outline_LeftOnly" + }, + { + "value": "4", + "displayName": "Right only", + "displayNameKey": "Formatting_Outline_RightOnly" + }, + { + "value": "5", + "displayName": "Top + bottom", + "displayNameKey": "Formatting_Outline_TopAndBottom" + }, + { + "value": "6", + "displayName": "Left + right", + "displayNameKey": "Formatting_Outline_LeftAndRight" + }, + { + "value": "7", + "displayName": "Frame", + "displayNameKey": "Formatting_Outline_Frame" + } + ] + } + }, + "textSize":{ + "displayName": "Text size", + "displayNameKey": "Formatting_Items_TextSize", + "type":{ + "integer": true + } + } + } } }, "dataViewMappings": [ diff --git a/package-lock.json b/package-lock.json index 42be90a..5f06da3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,23 +53,6 @@ } } }, - "@types/bootstrap": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-3.4.0.tgz", - "integrity": "sha512-LS05hVAAsX86qbHg7W+ydwBlNHrVCoFw6wEP3/uW4eYmRXl08bWmPeN/+onM+8qZTFfDgUlG/OItJI8SW972oQ==", - "requires": { - "@types/jquery": "*" - } - }, - "@types/bootstrap-multiselect": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@types/bootstrap-multiselect/-/bootstrap-multiselect-0.9.0.tgz", - "integrity": "sha512-tJU7V4ORRMdyqA9GoN6KepewlQwKjcCPQC4GrP2cow/ixr1FO6hi4FKfVrgxLg/KnRKCZvJnNthvSXz1y7qqRQ==", - "dev": true, - "requires": { - "@types/jquery": "*" - } - }, "@types/d3": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/@types/d3/-/d3-5.7.2.tgz", @@ -303,11 +286,6 @@ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz", "integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ==" }, - "@types/jquery": { - "version": "2.0.54", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-2.0.54.tgz", - "integrity": "sha512-D/PomKwNkDfSKD13DEVQT/pq2TUjN54c6uB341fEZanIzkjfGe7UaFuuaLZbpEiS5j7Wk2MUHAZqZIoECw29lg==" - }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -338,26 +316,6 @@ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true }, - "bootstrap": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz", - "integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA==" - }, - "bootstrap-multiselect": { - "version": "0.9.15", - "resolved": "https://registry.npmjs.org/bootstrap-multiselect/-/bootstrap-multiselect-0.9.15.tgz", - "integrity": "sha512-UwF32a0QR82xkEEGpuNrn57Bu0b/7DfCuoiOaziSHfQKFj5arR6c7+MYLs5RiIf3zl4XZ+YnY7ZBi6/EN3vEZA==", - "requires": { - "jquery": "~2.1.3" - }, - "dependencies": { - "jquery": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.1.4.tgz", - "integrity": "sha1-IoveaYoMYUMdwmMKahVPFYkNIxc=" - } - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -816,11 +774,6 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "jquery": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz", - "integrity": "sha1-LInWiJterFIqfuoywUUhVZxsvwI=" - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", diff --git a/package.json b/package.json index 304bf25..ee5854a 100644 --- a/package.json +++ b/package.json @@ -9,20 +9,14 @@ "dependencies": { "@babel/runtime": "7.6.0", "@babel/runtime-corejs2": "7.6.0", - "@types/bootstrap": "^3.4.0", "@types/d3": "5.7.2", - "@types/jquery": "^2.0.54", - "bootstrap": "^3.4.1", - "bootstrap-multiselect": "^0.9.15", "core-js": "3.2.1", "d3": "5.12.0", - "jquery": "^2.2.4", - "powerbi-models": "^1.3.3", "powerbi-visuals-api": "~2.6.1", - "powerbi-visuals-utils-dataviewutils": "2.2.1" + "powerbi-visuals-utils-dataviewutils": "2.2.1", + "powerbi-models": "^1.3.3" }, "devDependencies": { - "@types/bootstrap-multiselect": "^0.9.0", "ts-loader": "6.1.0", "tslint": "^5.18.0", "tslint-microsoft-contrib": "^6.2.0", diff --git a/src/managers/filterManager.ts b/src/managers/filterManager.ts index 03f98c0..827a943 100644 --- a/src/managers/filterManager.ts +++ b/src/managers/filterManager.ts @@ -47,7 +47,12 @@ export class FilterManager implements IFilterManager{ "values": selection } console.debug("jsonFilter:",jsonFilter); - this.host.applyJsonFilter(jsonFilter?jsonFilter:null,"general","filter",powerbi.FilterAction.merge); + if(jsonFilter){ + console.debug('apply jsonFilter:',JSON.stringify(jsonFilter)); + this.host.applyJsonFilter(jsonFilter,"general","filter",powerbi.FilterAction.merge); + }else{ + console.debug('not apply jsonFilter:',jsonFilter); + } console.debug("filterStringField end"); } } \ No newline at end of file diff --git a/src/managers/layoutManager.ts b/src/managers/layoutManager.ts index f780f59..2fbff97 100644 --- a/src/managers/layoutManager.ts +++ b/src/managers/layoutManager.ts @@ -16,7 +16,7 @@ export class LayoutManager implements ILayoutManager{ this.layout=layout; this.headerContainer=layout.append("div").classed("header-container",true); this.headerContainer.append('button').attr('clear',true).text('clear').on('click',function(){ - filterManager.clear(); + //filterManager.clear(); }); this.headerContainer.style('display','none'); } @@ -29,6 +29,6 @@ export class LayoutManager implements ILayoutManager{ } update(dataView:DataView,width:number,height:number):void{ - //this.layout.style("width",width+"px").style("height",height+"px"); + this.layout.style("width",width+"px").style("height",height+"px"); } } diff --git a/src/managers/managerFactory.ts b/src/managers/managerFactory.ts index fa1ac24..1100f72 100644 --- a/src/managers/managerFactory.ts +++ b/src/managers/managerFactory.ts @@ -8,6 +8,7 @@ export class ManagerFactory{ return new classLayoutManager(container,filterManager); } public static CreateSelectorManager(classSelectorManager:visualInterfaces.ISelectorManagerConstructor,container:Selection,filterManager:visualInterfaces.IFilterManager):visualInterfaces.ISelectorManager{ + return new classSelectorManager(container,filterManager); } public static CreateFilterManager(classSelectorManager:visualInterfaces.IFilterManagerConstructor,host:powerbi.extensibility.visual.IVisualHost):visualInterfaces.IFilterManager{ diff --git a/src/managers/selectorManager.ts b/src/managers/selectorManager.ts index cc2537f..912de67 100644 --- a/src/managers/selectorManager.ts +++ b/src/managers/selectorManager.ts @@ -4,6 +4,7 @@ import "../../node_modules/bootstrap-multiselect/dist/css/bootstrap-multiselect. import powerbi from "powerbi-visuals-api"; import {ISelectorManager,ISelectorManagerConstructor, IFilterManager} from "../visual/visualInterfaces"; import * as d3 from "d3"; +import * as settings from "../settings"; type Selection = d3.Selection; /* 负责页面上选择器的展示 @@ -21,6 +22,15 @@ export class SelectorManager implements ISelectorManager{ this.selectorContainer=selectorContainer; this.filterManager=filterManager; } + updateFormat(visualSettings:settings.VisualSettings): void { + console.debug('selectorManager updateFormat start'); + console.debug('visualSettings:',visualSettings); + if(visualSettings&&visualSettings.items){ + this.selector.updateFormat(visualSettings.items); + } + console.debug('selectorManager updateFormat end'); + + } public dispose():void{ this.selector.dispose(); this.selectorContainer.remove(); @@ -32,7 +42,6 @@ export class SelectorManager implements ISelectorManager{ } updateData(field: powerbi.DataViewCategoryColumn, defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn){ - if(!this.selector){ let fieldType=field.source.type; if(fieldType.text){ @@ -45,18 +54,15 @@ export class SelectorManager implements ISelectorManager{ throw "only receive text/num/datetime field"; } } - this.selector.update(field, defaultSelect, defaultStart, defaultEnd); }; - public filterStringField(selection:string[]){ - - }; } interface ISelector{ update(field: powerbi.DataViewCategoryColumn, defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn); dispose():void; + updateFormat(itemsSetting:settings.ItemsSetting); } abstract class Selector implements ISelector{ @@ -89,12 +95,20 @@ abstract class Selector implements ISelector{ this.manager=manager; this.createView(); } + public abstract updateFormat(itemsSetting: settings.ItemsSetting); protected abstract createView():void; public abstract dispose():void; protected readonly manager:ISelectorManager; public abstract update(field: powerbi.DataViewCategoryColumn, defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn):void; } class DropDownSelector extends Selector{ + public updateFormat(itemsSetting: settings.ItemsSetting) { + if(itemsSetting){ + if(itemsSetting.backgroundColor){ + this.dropDown.style('background-color',itemsSetting.backgroundColor?itemsSetting.backgroundColor:"transparent"); + } + } + } protected checkDefaultSelectionChange(defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn): boolean { //The defaultSelect is nullable, so first check the new defaultSelect console.debug('checkDefaultSelectionChange start'); @@ -103,6 +117,8 @@ class DropDownSelector extends Selector{ console.debug('new defaultSelect is null, set flag=false') flag=flag||false; }else{ + console.debug('new defaultSelect is not null, check the oldDefaultSelect'); + console.debug('new defaultSelect:',defaultSelect); if(!this.defaultSelect||!this.defaultSelect.values||!defaultSelect.values[0]){ console.debug('previous defaultSelect is null, set flag=true'); flag=flag||true; @@ -172,13 +188,13 @@ class DropDownSelector extends Selector{ .attr('label',function(d){return d.toString();}) .classed('dropDown-option',true) .merge(options) - .property("selected",function(d){ + .attr("selected",function(d){ console.debug('d.toString():',d.toString()); console.debug('newDefaultSelect:',newDefaultSelect); return (d.toString()==newDefaultSelect)?'selected':null; }); - this.dropDown.dispatch('change'); - console.debug('reset defaultSelection end'); + //this.manager.filterManager.filterStringField([newDefaultSelect]);//No matter what, filter after defaultSelection changing + console.debug('Set defaultSelection end'); }else{ console.debug('defaultSelection not reset, start update options'); options.enter().append("option").text(function(d){return d.toString();}).attr('label',function(d){return d.toString();}).classed('dropDown-option',true);//add @@ -187,10 +203,16 @@ class DropDownSelector extends Selector{ console.debug("dropDown:",this.dropDown); this.field=field; this.defaultSelect=defaultSelect; + console.debug('new defaultSelect:',defaultSelect); + console.debug('this.defaultSelect=defaultSelect, this.defaultSelect:',this.defaultSelect); + this.dropDown.dispatch('change'); console.debug('dropDownViewManager','update end'); } } class ListSelector extends Selector{ + public updateFormat(itemsSetting: settings.ItemsSetting) { + throw new Error("Method not implemented."); + } protected checkDefaultSelectionChange(defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn): boolean { throw new Error("Method not implemented."); } @@ -206,6 +228,9 @@ class ListSelector extends Selector{ } } class CalendarSelector extends Selector{ + public updateFormat(itemsSetting: settings.ItemsSetting) { + throw new Error("Method not implemented."); + } protected checkDefaultSelectionChange(defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn): boolean { throw new Error("Method not implemented."); } diff --git a/src/settings/enums/index.ts b/src/settings/enums/index.ts new file mode 100644 index 0000000..01ae5ef --- /dev/null +++ b/src/settings/enums/index.ts @@ -0,0 +1 @@ +export {Outline} from "./outline"; \ No newline at end of file diff --git a/src/settings/enums/outline.ts b/src/settings/enums/outline.ts new file mode 100644 index 0000000..36d5f9d --- /dev/null +++ b/src/settings/enums/outline.ts @@ -0,0 +1,4 @@ +"Use strict"; +export enum Outline{ + None,BottomOnly,TopOnly,LeftOnly,RightOnly,TopAndBottom,LeftAndRight,Frame +} \ No newline at end of file diff --git a/src/settings/index.ts b/src/settings/index.ts new file mode 100644 index 0000000..34cfaad --- /dev/null +++ b/src/settings/index.ts @@ -0,0 +1,4 @@ +export {ItemsSetting} from "./itemsSetting"; +export {SlicerHeaderSetting} from "./slicerHeaderSetting"; +export {VisualSettings} from "./visualSettings"; +export * as Enums from "./enums"; diff --git a/src/settings/itemsSetting.ts b/src/settings/itemsSetting.ts new file mode 100644 index 0000000..d5110b3 --- /dev/null +++ b/src/settings/itemsSetting.ts @@ -0,0 +1,8 @@ +"Use strict"; +import * as enums from "./enums" +export class ItemsSetting{ + public fontColor:string="black"; + public backgroundColor:string=''; + public outline:enums.Outline=enums.Outline.None; + public textSize:number=10; +} \ No newline at end of file diff --git a/src/settings/slicerHeaderSetting.ts b/src/settings/slicerHeaderSetting.ts new file mode 100644 index 0000000..7a7c7a1 --- /dev/null +++ b/src/settings/slicerHeaderSetting.ts @@ -0,0 +1,9 @@ +"Use strict"; + +import * as enums from "./enums"; + +export class SlicerHeaderSetting{ + public fontColor:string=''; + public backgroundColor:string=''; + public outline:enums.Outline=enums.Outline.None; +} diff --git a/src/settings/visualSettings.ts b/src/settings/visualSettings.ts index 002889b..ddb1e19 100644 --- a/src/settings/visualSettings.ts +++ b/src/settings/visualSettings.ts @@ -28,21 +28,11 @@ import { dataViewObjectsParser } from "powerbi-visuals-utils-dataviewutils"; import DataViewObjectsParser = dataViewObjectsParser.DataViewObjectsParser; - +import {SlicerHeaderSetting} from "./slicerHeaderSetting"; +import {ItemsSetting} from "./itemsSetting"; export class VisualSettings extends DataViewObjectsParser { - public dataPoint: dataPointSettings = new dataPointSettings(); + public items: ItemsSetting = new ItemsSetting(); + public slicerHeader:SlicerHeaderSetting=new SlicerHeaderSetting(); } - export class dataPointSettings { - // Default color - public defaultColor: string = ""; - // Show all - public showAllDataPoints: boolean = true; - // Fill - public fill: string = ""; - // Color saturation - public fillRule: string = ""; - // Text Size - public fontSize: number = 12; - } diff --git a/src/visual/visual.ts b/src/visual/visual.ts index 3c828d2..faaf11c 100644 --- a/src/visual/visual.ts +++ b/src/visual/visual.ts @@ -44,7 +44,6 @@ import * as d3 from "d3"; import { getObject } from "powerbi-visuals-utils-dataviewutils/lib/dataViewObjects"; import { getMeasureIndexOfRole } from "powerbi-visuals-utils-dataviewutils/lib/dataRoleHelper"; import { selector } from "d3"; - export class Visual implements IVisual { /* SelectorManager: a custom manager, used to manage dropDownSelector, listSelector, calendarSelector, and so on @@ -55,12 +54,12 @@ export class Visual implements IVisual { private layoutManager: visualInterfaces.ILayoutManager; private selectorManager: visualInterfaces.ISelectorManager; private filterManager:visualInterfaces.IFilterManager; - private selectionManager:powerbi.extensibility.ISelectionManager; + //private selectionManager:powerbi.extensibility.ISelectionManager; constructor(options: VisualConstructorOptions) { console.debug('Visual constructor', options); this.events = options.host.eventService; if (document) { - this.selectionManager =options.host.createSelectionManager(); + //this.selectionManager =options.host.createSelectionManager(); let container=d3.select(options.element).append("div").classed("container",true); //overload context menu @@ -111,18 +110,19 @@ export class Visual implements IVisual { }); let width:number=options.viewport.width; let height:number=options.viewport.height; - + console.debug("start layoutManager updateView"); this.layoutManager.update(dataView,width-10,height-10); console.debug("start filterManager updateView"); this.filterManager.update(field); - this.events.renderingFinished(options); console.debug("start selectorManager updateView"); this.selectorManager.updateData(field,defaultSelect,defaultStart,defaultEnd); - - + //this.selectorManager.updateFormat(this.settings); + + console.debug('visual update end'); + this.events.renderingFinished(options); } private static parseSettings(dataView: DataView): VisualSettings { diff --git a/src/visual/visualInterfaces.ts b/src/visual/visualInterfaces.ts index c1f2b2e..876be98 100644 --- a/src/visual/visualInterfaces.ts +++ b/src/visual/visualInterfaces.ts @@ -10,6 +10,9 @@ type Selection = d3.Selection; Main interfaces */ +//IVisualSettings + + //ISelectorManager export interface ILayoutManager{ layout:Selection; @@ -26,12 +29,12 @@ export interface ISelectorManager{ filterManager:IFilterManager; dispose():void; updateData(field:powerbi.DataViewCategoryColumn,defaultSelect:powerbi.DataViewValueColumn,defaultStart:powerbi.DataViewValueColumn,defaultEnd:powerbi.DataViewValueColumn):void; + updateFormat(visualSettings:VisualSettings):void; } export interface ISelectorManagerConstructor{ new(selectorContainer:Selection,filterManager:IFilterManager):ISelectorManager; } - //IFilterManager export interface IFilterManager{ update(field:powerbi.DataViewCategoryColumn):void;