Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
17015f13e6 | |||
ad38c05613 | |||
3d759644d1 | |||
d1ad27312b | |||
084a65c507 | |||
82f4d1ecdc | |||
b2639bcebe | |||
c676bb727e |
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
|||||||
/dist
|
/dist
|
||||||
/.tmp
|
/.tmp
|
||||||
/.vscode
|
/.vscode
|
||||||
|
webpack.statistics.*
|
26
ReadMe.md
Normal file
26
ReadMe.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# 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
|
||||||
|
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
|
@ -1,4 +1,6 @@
|
|||||||
{
|
{
|
||||||
|
"supportsSynchronizingFilterState": true,
|
||||||
|
"advancedEditModeSupport": 1,
|
||||||
"dataRoles": [
|
"dataRoles": [
|
||||||
{
|
{
|
||||||
"displayName": "Field",
|
"displayName": "Field",
|
||||||
@ -46,7 +48,7 @@
|
|||||||
"objects": {
|
"objects": {
|
||||||
"general": {
|
"general": {
|
||||||
"displayName": "General",
|
"displayName": "General",
|
||||||
"displayNameKey": "formattingGeneral",
|
"displayNameKey": "Formatting-General",
|
||||||
"properties": {
|
"properties": {
|
||||||
"filter": {
|
"filter": {
|
||||||
"type": {
|
"type": {
|
||||||
@ -62,11 +64,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dataPoint": {
|
"slicerHeader": {
|
||||||
"displayName": "Data colors",
|
"displayName": "Slicer header",
|
||||||
|
"displayNameKey":"Formatting-SicerHeader",
|
||||||
"properties": {
|
"properties": {
|
||||||
"defaultColor": {
|
"fontColor": {
|
||||||
"displayName": "Default color",
|
"displayName": "Font color",
|
||||||
"type": {
|
"type": {
|
||||||
"fill": {
|
"fill": {
|
||||||
"solid": {
|
"solid": {
|
||||||
@ -75,6 +78,79 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outlineColor":{
|
||||||
|
"displayName": "Outline color",
|
||||||
|
"type": {
|
||||||
|
"fill": {
|
||||||
|
"solid": {
|
||||||
|
"color":true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outlineWeight":{
|
||||||
|
"displayName": "Outline weight",
|
||||||
|
"type":{
|
||||||
|
"integer": true
|
||||||
|
}
|
||||||
|
},
|
||||||
"showAllDataPoints": {
|
"showAllDataPoints": {
|
||||||
"displayName": "Show all",
|
"displayName": "Show all",
|
||||||
"type": {
|
"type": {
|
||||||
@ -106,6 +182,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": [
|
"dataViewMappings": [
|
||||||
|
56
package-lock.json
generated
56
package-lock.json
generated
@ -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": {
|
"@types/d3": {
|
||||||
"version": "5.7.2",
|
"version": "5.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/d3/-/d3-5.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/d3/-/d3-5.7.2.tgz",
|
||||||
@ -303,10 +286,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz",
|
||||||
"integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ=="
|
"integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ=="
|
||||||
},
|
},
|
||||||
"@types/jquery": {
|
"@types/node": {
|
||||||
"version": "2.0.54",
|
"version": "13.13.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-2.0.54.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.4.tgz",
|
||||||
"integrity": "sha512-D/PomKwNkDfSKD13DEVQT/pq2TUjN54c6uB341fEZanIzkjfGe7UaFuuaLZbpEiS5j7Wk2MUHAZqZIoECw29lg=="
|
"integrity": "sha512-x26ur3dSXgv5AwKS0lNfbjpCakGIduWU1DU91Zz58ONRWrIKGunmZBNv4P7N+e27sJkiGDsw/3fT4AtsqQBrBA==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"ansi-styles": {
|
"ansi-styles": {
|
||||||
"version": "3.2.1",
|
"version": "3.2.1",
|
||||||
@ -338,26 +322,6 @@
|
|||||||
"integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
|
"integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
|
||||||
"dev": true
|
"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": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
@ -816,11 +780,6 @@
|
|||||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"jquery": {
|
|
||||||
"version": "2.2.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz",
|
|
||||||
"integrity": "sha1-LInWiJterFIqfuoywUUhVZxsvwI="
|
|
||||||
},
|
|
||||||
"js-tokens": {
|
"js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||||
@ -946,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",
|
||||||
|
10
package.json
10
package.json
@ -9,20 +9,16 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "7.6.0",
|
"@babel/runtime": "7.6.0",
|
||||||
"@babel/runtime-corejs2": "7.6.0",
|
"@babel/runtime-corejs2": "7.6.0",
|
||||||
"@types/bootstrap": "^3.4.0",
|
|
||||||
"@types/d3": "5.7.2",
|
"@types/d3": "5.7.2",
|
||||||
"@types/jquery": "^2.0.54",
|
|
||||||
"bootstrap": "^3.4.1",
|
|
||||||
"bootstrap-multiselect": "^0.9.15",
|
|
||||||
"core-js": "3.2.1",
|
"core-js": "3.2.1",
|
||||||
"d3": "5.12.0",
|
"d3": "5.12.0",
|
||||||
"jquery": "^2.2.4",
|
|
||||||
"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/bootstrap-multiselect": "^0.9.0",
|
"@types/node": "^13.13.4",
|
||||||
"ts-loader": "6.1.0",
|
"ts-loader": "6.1.0",
|
||||||
"tslint": "^5.18.0",
|
"tslint": "^5.18.0",
|
||||||
"tslint-microsoft-contrib": "^6.2.0",
|
"tslint-microsoft-contrib": "^6.2.0",
|
||||||
|
@ -18,10 +18,7 @@
|
|||||||
"icon": "assets/icon.png"
|
"icon": "assets/icon.png"
|
||||||
},
|
},
|
||||||
"externalJS": [
|
"externalJS": [
|
||||||
"node_modules/jquery/dist/jquery.min.js",
|
"./src/cover.js"
|
||||||
"src/coverJquery.js",
|
|
||||||
"node_modules/bootstrap/dist/js/bootstrap.min.js",
|
|
||||||
"node_modules/bootstrap-multiselect/dist/js/bootstrap-multiselect.min.js"
|
|
||||||
],
|
],
|
||||||
"style": "style/visual.less",
|
"style": "style/visual.less",
|
||||||
"capabilities": "capabilities.json",
|
"capabilities": "capabilities.json",
|
||||||
|
7
src/cover.js
Normal file
7
src/cover.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
var Debug=true;
|
||||||
|
function blankConsoleDebug(){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!Debug){
|
||||||
|
console.debug=blankConsoleDebug;
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
var jQuery = typeof jQuery !== 'undefined'
|
|
||||||
? jQuery
|
|
||||||
: window['$'];
|
|
@ -11,9 +11,53 @@ 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:models.IAdvancedFilter;
|
||||||
|
|
||||||
|
public get jsonFilter() : models.IAdvancedFilter {
|
||||||
|
return this._jsonFilter;
|
||||||
|
}
|
||||||
|
public get advancedEditModeMark():string{
|
||||||
|
return 'SyinpoSlicer_AdvancedEditMode_'+this.inAdvancedEditMode;
|
||||||
|
}
|
||||||
constructor(host:IVisualHost){
|
constructor(host:IVisualHost){
|
||||||
this.host=host;
|
this.host=host;
|
||||||
}
|
}
|
||||||
|
_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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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');
|
||||||
|
|
||||||
|
}
|
||||||
|
public dispose():void{
|
||||||
|
console.debug('filterManager disposing');
|
||||||
|
|
||||||
|
if(this.target.table&&this.target.column){
|
||||||
|
this.clear();
|
||||||
|
}
|
||||||
|
console.debug('filterManager disposed');
|
||||||
|
|
||||||
|
}
|
||||||
|
public clear():void{
|
||||||
|
console.debug("clear start:");
|
||||||
|
this.host.applyJsonFilter(null,"general","filter",powerbi.FilterAction.remove);
|
||||||
|
console.debug("clear end");
|
||||||
|
}
|
||||||
public update(field:powerbi.DataViewCategoryColumn):void{
|
public update(field:powerbi.DataViewCategoryColumn):void{
|
||||||
let queryName:string=field.source.queryName;
|
let queryName:string=field.source.queryName;
|
||||||
let splitPosition:number=queryName.indexOf('.');
|
let splitPosition:number=queryName.indexOf('.');
|
||||||
@ -23,17 +67,33 @@ export class FilterManager implements IFilterManager{
|
|||||||
console.debug("queryName.length:",queryName.length);
|
console.debug("queryName.length:",queryName.length);
|
||||||
console.debug("filterManager update end, now filter:",this.target);
|
console.debug("filterManager update end, now filter:",this.target);
|
||||||
}
|
}
|
||||||
public filterStringField(selection:string[]):void{
|
public setFilter_String(selection:string[],applyNow:boolean):void{
|
||||||
console.debug("filterStringField start:",selection);
|
console.debug("setFilter_String start:",selection);
|
||||||
let jsonFilter:models.IBasicFilter={
|
let conditions:models.IAdvancedFilterCondition[]=[];
|
||||||
"$schema": "http://powerbi.com/product/schema#basic",
|
|
||||||
|
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,
|
"target": this.target,
|
||||||
"filterType": models.FilterType.Basic,
|
"filterType": models.FilterType.Advanced,
|
||||||
"operator":"In",
|
"conditions":conditions,
|
||||||
"values": selection
|
"logicalOperator":"Or"
|
||||||
}
|
}
|
||||||
console.debug("jsonFilter:",jsonFilter);
|
console.debug("jsonFilter:",jsonFilter);
|
||||||
this.host.applyJsonFilter(jsonFilter?jsonFilter:null,"general","filter",powerbi.FilterAction.merge);
|
this._jsonFilter=jsonFilter;
|
||||||
console.debug("filterStringField end");
|
if(applyNow){
|
||||||
|
this.applyJsonFilter();
|
||||||
|
}
|
||||||
|
console.debug("setFilter_String end");
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,14 +3,32 @@ import powerbi from "powerbi-visuals-api";
|
|||||||
import DataView = powerbi.DataView;
|
import DataView = powerbi.DataView;
|
||||||
import * as visualInterfaces from "../visual/visualInterfaces";
|
import * as visualInterfaces from "../visual/visualInterfaces";
|
||||||
import * as d3 from "d3";
|
import * as d3 from "d3";
|
||||||
import { ILayoutManager } from "../visual/visualInterfaces";
|
import { ILayoutManager,IFilterManager } from "../visual/visualInterfaces";
|
||||||
|
import { IFilter } from "powerbi-models";
|
||||||
type Selection<T extends d3.BaseType> = d3.Selection<T, any, any, any>;
|
type Selection<T extends d3.BaseType> = d3.Selection<T, any, any, any>;
|
||||||
export class LayoutManager implements ILayoutManager{
|
export class LayoutManager implements ILayoutManager{
|
||||||
layout:Selection<HTMLElement>;
|
layout:Selection<HTMLElement>;
|
||||||
// constructor(layout:Selection<HTMLElement>){
|
// constructor(layout:Selection<HTMLElement>){
|
||||||
// this.layout=layout;
|
// this.layout=layout;
|
||||||
// }
|
// }
|
||||||
|
headerContainer:Selection<HTMLDivElement>
|
||||||
|
constructor(layout:Selection<HTMLElement>,filterManager:IFilterManager){
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
this.headerContainer.style('display','none');
|
||||||
|
}
|
||||||
|
public dispose():void{
|
||||||
|
console.debug('layoutManager disposing');
|
||||||
|
|
||||||
|
this.headerContainer.remove();
|
||||||
|
this.layout.remove();
|
||||||
|
console.debug('layoutManager disposed');
|
||||||
|
|
||||||
|
}
|
||||||
update(dataView:DataView,width:number,height:number):void{
|
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,15 @@
|
|||||||
import * as visualInterfaces from "../visual/visualInterfaces";
|
import * as visualInterfaces from "../visual/visualInterfaces";
|
||||||
import * as d3 from "d3";
|
import * as d3 from "d3";
|
||||||
import powerbi from "powerbi-visuals-api";
|
import powerbi from "powerbi-visuals-api";
|
||||||
|
import { EventEmitter } from "events";
|
||||||
type Selection<T extends d3.BaseType> = d3.Selection<T, any, any, any>;
|
type Selection<T extends d3.BaseType> = d3.Selection<T, any, any, any>;
|
||||||
export class ManagerFactory{
|
export class ManagerFactory{
|
||||||
public static CreateLayoutManager(classLayoutManager:visualInterfaces.ILayoutManagerConstructor,container:Selection<HTMLElement>):visualInterfaces.ILayoutManager{
|
public static CreateLayoutManager(classLayoutManager:visualInterfaces.ILayoutManagerConstructor,container:Selection<HTMLElement>,filterManager:visualInterfaces.IFilterManager):visualInterfaces.ILayoutManager{
|
||||||
return new classLayoutManager(container);
|
return new classLayoutManager(container,filterManager);
|
||||||
}
|
}
|
||||||
public static CreateSelectorManager(classSelectorManager:visualInterfaces.ISelectorManagerConstructor,container:Selection<HTMLElement>,filterManager:visualInterfaces.IFilterManager):visualInterfaces.ISelectorManager{
|
public static CreateSelectorManager(classSelectorManager:visualInterfaces.ISelectorManagerConstructor,container:Selection<HTMLElement>):visualInterfaces.ISelectorManager&EventEmitter{
|
||||||
return new classSelectorManager(container,filterManager);
|
|
||||||
|
return new classSelectorManager(container);
|
||||||
}
|
}
|
||||||
public static CreateFilterManager(classSelectorManager:visualInterfaces.IFilterManagerConstructor,host:powerbi.extensibility.visual.IVisualHost):visualInterfaces.IFilterManager{
|
public static CreateFilterManager(classSelectorManager:visualInterfaces.IFilterManagerConstructor,host:powerbi.extensibility.visual.IVisualHost):visualInterfaces.IFilterManager{
|
||||||
return new classSelectorManager(host);
|
return new classSelectorManager(host);
|
||||||
|
@ -1,145 +1,75 @@
|
|||||||
"Use strict";
|
"Use strict";
|
||||||
import "../../node_modules/bootstrap/dist/css/bootstrap.css";
|
|
||||||
import "../../node_modules/bootstrap-multiselect/dist/css/bootstrap-multiselect.css";
|
|
||||||
import powerbi from "powerbi-visuals-api";
|
import powerbi from "powerbi-visuals-api";
|
||||||
import {ISelectorManager,ISelectorManagerConstructor, IFilterManager} from "../visual/visualInterfaces";
|
import {ISelectorManager,ISelectorManagerConstructor} from "../visual/visualInterfaces";
|
||||||
import * as d3 from "d3";
|
import * as d3 from "d3";
|
||||||
|
import * as settings from "../settings";
|
||||||
|
import * as selectors from "./selectors";
|
||||||
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 {EventEmitter} from "events";
|
||||||
/*
|
/*
|
||||||
负责页面上选择器的展示
|
负责页面上选择器的展示
|
||||||
*/
|
*/
|
||||||
export class SelectorManager implements ISelectorManager{
|
export class SelectorManager extends EventEmitter implements ISelectorManager {
|
||||||
public selectorContainer : Selection<HTMLElement>;
|
public selectorContainer : Selection<HTMLElement>;
|
||||||
private selector:ISelector;
|
private selector:selectors.ISelector;
|
||||||
public filterManager:IFilterManager;
|
|
||||||
private categories: powerbi.DataViewCategoryColumn;
|
private field: powerbi.DataViewCategoryColumn;
|
||||||
private defaultSelect: powerbi.DataViewValueColumn;
|
private defaultSelect: powerbi.DataViewValueColumn;
|
||||||
private defaultStart: powerbi.DataViewValueColumn;
|
private defaultStart: powerbi.DataViewValueColumn;
|
||||||
private defaultEnd: powerbi.DataViewValueColumn;
|
private defaultEnd: powerbi.DataViewValueColumn;
|
||||||
constructor(selectorContainer:Selection<HTMLElement>,filterManager:IFilterManager){
|
|
||||||
|
//events
|
||||||
|
public stringFieldFilter_event: string="stringFieldFilter_event";
|
||||||
|
|
||||||
|
constructor(selectorContainer:Selection<HTMLElement>){
|
||||||
|
super();
|
||||||
console.debug("selectorManager constructor start");
|
console.debug("selectorManager constructor start");
|
||||||
this.selectorContainer=selectorContainer;
|
this.selectorContainer=selectorContainer;
|
||||||
this.filterManager=filterManager;
|
|
||||||
}
|
}
|
||||||
public switchSelector<T extends ISelector>(classSelector:new ()=>T){
|
select(items: string[]): void {
|
||||||
|
this.selector.select(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFormat(visualSettings:settings.VisualSettings,width:number,height:number): void {
|
||||||
|
console.debug('selectorManager updateFormat start');
|
||||||
|
console.debug('visualSettings:',visualSettings);
|
||||||
|
if(visualSettings&&visualSettings.items){
|
||||||
|
this.selector.updateFormat(visualSettings.items,width,height);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.debug('selectorManager updateFormat end');
|
||||||
|
|
||||||
|
}
|
||||||
|
public dispose():void{
|
||||||
|
this.selector.dispose();
|
||||||
|
this.selectorContainer.remove();
|
||||||
|
}
|
||||||
|
public switchSelector<T extends selectors.ISelector>(classSelector:new ()=>T){
|
||||||
let newSelector=new classSelector();
|
let newSelector=new classSelector();
|
||||||
this.selector?.dispose();
|
this.selector?.dispose();
|
||||||
this.selector=newSelector;
|
this.selector=newSelector;
|
||||||
}
|
}
|
||||||
updateData(categories: powerbi.DataViewCategoryColumn, defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn){
|
updateData(field: powerbi.DataViewCategoryColumn, defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn){
|
||||||
|
|
||||||
|
|
||||||
if(!this.selector){
|
if(!this.selector){
|
||||||
let fieldType=categories.source.type;
|
let fieldType=field.source.type;
|
||||||
if(fieldType.text){
|
if(fieldType.text){
|
||||||
this.selector=new DropDownSelector(this);
|
let dropDownSelectorContainer=this.selectorContainer.append("div").classed("dropDown-selector-container",true);
|
||||||
|
this.selector=new selectors.DropDownSelector(dropDownSelectorContainer);
|
||||||
}else if(fieldType.numeric){
|
}else if(fieldType.numeric){
|
||||||
this.selector=new DropDownSelector(this);
|
let dropDownSelectorContainer=this.selectorContainer.append("div").classed("dropDown-selector-container",true);
|
||||||
|
this.selector=new selectors.DropDownSelector(dropDownSelectorContainer);
|
||||||
}else if(fieldType.dateTime){
|
}else if(fieldType.dateTime){
|
||||||
this.selector=new CalendarSelector(this);
|
let dropDownSelectorContainer=this.selectorContainer.append("div").classed("dropDown-selector-container",true);
|
||||||
|
this.selector=new selectors.DropDownSelector(dropDownSelectorContainer);
|
||||||
}else{
|
}else{
|
||||||
throw "only receive text/num/datetime field";
|
throw "only receive text/num/datetime field";
|
||||||
}
|
}
|
||||||
|
this.selector.on(this.selector.stringFieldFilter_event,(selectionValues:string[],applyNow:boolean)=>{
|
||||||
|
this.emit(this.stringFieldFilter_event,selectionValues,applyNow);
|
||||||
|
});
|
||||||
|
console.debug('selector stringFieldFilter registered');
|
||||||
}
|
}
|
||||||
|
this.selector.update(field, defaultSelect, defaultStart, defaultEnd);
|
||||||
|
|
||||||
this.selector.update(categories, defaultSelect, defaultStart, defaultEnd);
|
|
||||||
};
|
|
||||||
public filterStringField(selection:string[]){
|
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ISelector{
|
|
||||||
update(categories: powerbi.DataViewCategoryColumn, defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn);
|
|
||||||
dispose():void;
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class Selector implements ISelector{
|
|
||||||
constructor(manager: ISelectorManager){
|
|
||||||
console.debug("Abstract selector:","constructor start");
|
|
||||||
this.manager=manager;
|
|
||||||
this.createView();
|
|
||||||
}
|
|
||||||
protected abstract createView():void;
|
|
||||||
public abstract dispose():void;
|
|
||||||
protected readonly manager:ISelectorManager;
|
|
||||||
public abstract update(categories: powerbi.DataViewCategoryColumn, defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn):void;
|
|
||||||
}
|
|
||||||
class DropDownSelector extends Selector{
|
|
||||||
private dropDown:Selection<HTMLSelectElement>;
|
|
||||||
protected createView() {
|
|
||||||
console.debug('dropDownViewManager','createView start');
|
|
||||||
this.dropDown=this.manager.selectorContainer.append("select").classed("dropDown-selector",true).classed("selector",true).attr("multiple",true);
|
|
||||||
console.debug('dropDownViewManager','createView end');
|
|
||||||
}
|
|
||||||
public dispose(){
|
|
||||||
this.dropDown.remove();
|
|
||||||
}
|
|
||||||
public update(categories: powerbi.DataViewCategoryColumn, defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn) {
|
|
||||||
console.debug('dropDownViewManager','update start');
|
|
||||||
let options=this.dropDown.selectAll("option").data(categories.values,function(d){return d.toString();});//map data
|
|
||||||
options.enter().append("option").text(function(d){return d.toString();}).attr('dropDown-option');//add
|
|
||||||
options.exit().remove();//delete
|
|
||||||
console.debug("dropDown:",this.dropDown);
|
|
||||||
let filterManager:IFilterManager=this.manager.filterManager;
|
|
||||||
// this.dropDown.on("input change",function(){
|
|
||||||
// console.debug('DropDownSelector:',"input change");
|
|
||||||
// console.debug('this',this);
|
|
||||||
// console.debug('filterManager:',filterManager);
|
|
||||||
// let selectedValues:string[]=[];
|
|
||||||
// for(let i=0;i<this.selectedOptions.length;i++){
|
|
||||||
// let option=this.selectedOptions.item(i);
|
|
||||||
// if(option.selected){
|
|
||||||
// console.debug("option selected",option);
|
|
||||||
// console.debug('option.text:',option.text);
|
|
||||||
// selectedValues.push(option.text);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if(selectedValues.length==0){
|
|
||||||
// }else{
|
|
||||||
// console.debug("selection.length",selectedValues.length);
|
|
||||||
// filterManager.filterStringField(selectedValues);
|
|
||||||
// }
|
|
||||||
// console.debug("this",this.selectedOptions);
|
|
||||||
// });
|
|
||||||
|
|
||||||
$('.dropDown-selector').multiselect({
|
|
||||||
onChange:function(){
|
|
||||||
let selectedValues:string[]=[];
|
|
||||||
$('option:selected').map(function(a,item){
|
|
||||||
selectedValues.push(item.textContent);
|
|
||||||
console.debug('item:',item.textContent);
|
|
||||||
filterManager.filterStringField(selectedValues);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
maxHeight:100,
|
|
||||||
includeSelectAllOption:true
|
|
||||||
});
|
|
||||||
console.debug('dropDownViewManager','update end');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class ListSelector extends Selector{
|
|
||||||
public dispose() {
|
|
||||||
throw new Error("Method not implemented.");
|
|
||||||
}
|
|
||||||
protected createView() {
|
|
||||||
throw new Error("Method not implemented.");
|
|
||||||
}
|
|
||||||
public update(categories: powerbi.DataViewCategoryColumn, defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn) {
|
|
||||||
console.debug('ListSelector','updateView');
|
|
||||||
let dropDownSelector=this.manager.selectorContainer.append("select").classed("listSelector");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class CalendarSelector extends Selector{
|
|
||||||
public dispose() {
|
|
||||||
throw new Error("Method not implemented.");
|
|
||||||
}
|
|
||||||
protected createView() {
|
|
||||||
throw new Error("Method not implemented.");
|
|
||||||
}
|
|
||||||
public update(categories: powerbi.DataViewCategoryColumn, defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn) {
|
|
||||||
console.debug('calendarViewManager','updateView');
|
|
||||||
let dropDownSelector=this.manager.selectorContainer.append("select").classed("listSelector");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
/*
|
|
||||||
In the future, move all selectors here.
|
|
||||||
*/
|
|
0
src/managers/selectors/calendarSelector.ts
Normal file
0
src/managers/selectors/calendarSelector.ts
Normal file
168
src/managers/selectors/dropDownSelector.ts
Normal file
168
src/managers/selectors/dropDownSelector.ts
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
import { Selector } from "./selector";
|
||||||
|
import * as settings from "../../settings";
|
||||||
|
import powerbi from "powerbi-visuals-api";
|
||||||
|
import * as d3 from "d3";
|
||||||
|
import { selection } from "d3";
|
||||||
|
type Selection<T extends d3.BaseType> = d3.Selection<T, any, any, any>;
|
||||||
|
import {pixelConverter} from "powerbi-visuals-utils-typeutils";
|
||||||
|
|
||||||
|
export class DropDownSelector extends Selector {
|
||||||
|
public select(items: string[]): void {
|
||||||
|
console.debug('dropDownSelector select items:',items);
|
||||||
|
this.dropDown.selectAll('option').each(function(d,i){
|
||||||
|
console.debug('this.text:',d3.select(this).text());
|
||||||
|
if(items.includes(d3.select(this).text())){
|
||||||
|
console.debug('dropDownSelector select, included this:',this);
|
||||||
|
d3.select(this).attr('selected','selected');
|
||||||
|
}else{
|
||||||
|
console.debug('dropDownSelector select, not included this:',this);
|
||||||
|
d3.select(this).attr('selected',null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public updateFormat(itemsSetting: settings.ItemsSetting, width: number, height: number) {
|
||||||
|
console.debug('dropDownSelector updateFormat start');
|
||||||
|
if (itemsSetting) {
|
||||||
|
this.dropDown.style('background-color', itemsSetting.backgroundColor)
|
||||||
|
.attr('postion','absolute')
|
||||||
|
.style('color', itemsSetting.fontColor)
|
||||||
|
.style('font-size',pixelConverter.fromPointToPixel(itemsSetting.textSize) + 'px')
|
||||||
|
.style('width', (width - 10) + 'px')
|
||||||
|
.style('border-style', settings.Enums.getOutlineStyle(itemsSetting.outline))
|
||||||
|
.style('border-width', '2px')
|
||||||
|
.style('border-color', 'black');
|
||||||
|
this.dropDown.selectAll('option').style('background-color', itemsSetting.backgroundColor)
|
||||||
|
.style('color', itemsSetting.fontColor)
|
||||||
|
.style('font-size', pixelConverter.fromPointToPixel(itemsSetting.textSize) + 'px')
|
||||||
|
.style('border-style', settings.Enums.getOutlineStyle(itemsSetting.outline))
|
||||||
|
.style('border-width', '2px')
|
||||||
|
.style('border-color', 'black');
|
||||||
|
}
|
||||||
|
console.debug('dropDownSelector updateFormat end');
|
||||||
|
}
|
||||||
|
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');
|
||||||
|
let flag: boolean;
|
||||||
|
if (!defaultSelect || !defaultSelect.values || !defaultSelect.values[0]) {
|
||||||
|
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;
|
||||||
|
} else {
|
||||||
|
if (defaultSelect.values[0].toString() != this.defaultSelect.values[0].toString()) {
|
||||||
|
console.debug('new defaultSelect not equal to the previous, set flag=true');
|
||||||
|
flag = flag || true;
|
||||||
|
} else {
|
||||||
|
console.debug('new defaultSelect equal to the previous, set flag=false');
|
||||||
|
flag = flag || false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.debug('checkDefaultSelectionChange end, result:', flag);
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
private container: Selection<HTMLDivElement>;
|
||||||
|
private dropDown: Selection<HTMLSelectElement>;
|
||||||
|
protected createView(container: Selection<HTMLDivElement>) {
|
||||||
|
console.debug('dropDownViewManager', 'createView start');
|
||||||
|
this.container = container;
|
||||||
|
this.dropDown = this.container.append("select").classed("dropDown-selector", true).classed("selector", true);//.attr('multiple',true);
|
||||||
|
let dropDownSelector=this;
|
||||||
|
//on change, filter
|
||||||
|
this.dropDown.on("input change", function () {
|
||||||
|
console.debug('DropDownSelector:', "input change");
|
||||||
|
console.debug('this', this);
|
||||||
|
let selectedValues: string[] = [];
|
||||||
|
for (let i = 0; i < this.selectedOptions.length; i++) {
|
||||||
|
let option = this.selectedOptions.item(i);
|
||||||
|
if (option.selected) {
|
||||||
|
console.debug("option selected", option);
|
||||||
|
console.debug('option.text:', option.text);
|
||||||
|
selectedValues.push(option.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selectedValues.length == 0) {
|
||||||
|
} else {
|
||||||
|
console.debug("selection", selectedValues);
|
||||||
|
dropDownSelector.emit(dropDownSelector.stringFieldFilter_event,selectedValues,true);
|
||||||
|
}
|
||||||
|
console.debug("this", this.selectedOptions);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.debug('dropDownViewManager', 'createView end');
|
||||||
|
|
||||||
|
}
|
||||||
|
public dispose() {
|
||||||
|
console.debug('dropDown-selector disposing');
|
||||||
|
this.dropDown.remove();
|
||||||
|
console.debug('dropDown-selector disposed');
|
||||||
|
|
||||||
|
}
|
||||||
|
public update(field: powerbi.DataViewCategoryColumn, defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn) {
|
||||||
|
console.debug('dropDownViewManager', 'update start');
|
||||||
|
//Check field, defaultSelect are changed or not
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let needUpdateDefaultSelection: boolean = this.checkFieldAndDefaultSelectionChange(field, defaultSelect, defaultStart, defaultEnd);
|
||||||
|
let newDefaultSelect: string;
|
||||||
|
if (needUpdateDefaultSelection && defaultSelect && defaultSelect.values && defaultSelect.values[0]) {
|
||||||
|
newDefaultSelect = defaultSelect.values[0].toString();
|
||||||
|
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
|
||||||
|
options.exit().remove();//delete
|
||||||
|
|
||||||
|
if (needUpdateDefaultSelection && newDefaultSelect) {
|
||||||
|
console.debug('reset defaultSelection start');
|
||||||
|
options = options.enter().append("option")
|
||||||
|
.text(function (d) { return d.toString(); })
|
||||||
|
.attr('label', function (d) { return d.toString(); })
|
||||||
|
.classed('dropDown-option', true)
|
||||||
|
.attr('title',function (d) { return d.toString(); })
|
||||||
|
.merge(options)
|
||||||
|
.attr("selected", function (d) {
|
||||||
|
console.debug('d.toString():', d.toString());
|
||||||
|
console.debug('newDefaultSelect:', newDefaultSelect);
|
||||||
|
return (d.toString() == newDefaultSelect) ? 'selected' : null;
|
||||||
|
});
|
||||||
|
console.debug('Set defaultSelection end');
|
||||||
|
} else {
|
||||||
|
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(); })
|
||||||
|
.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');
|
||||||
|
}
|
||||||
|
|
||||||
|
let selectedValues: string[] = [];
|
||||||
|
this.dropDown.selectAll('option').each(function(d,i){
|
||||||
|
let option=d3.select(this);
|
||||||
|
console.debug('option',option.text());
|
||||||
|
console.debug('selected?',option.property('selected'));
|
||||||
|
if(option.property('selected')){
|
||||||
|
console.debug('find a selected option:',option.text());
|
||||||
|
selectedValues.push(option.text());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (selectedValues.length == 0) {
|
||||||
|
} else {
|
||||||
|
console.debug("selection", selectedValues);
|
||||||
|
}
|
||||||
|
this.emit(this.stringFieldFilter_event,selectedValues,false);
|
||||||
|
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);
|
||||||
|
console.debug('dropDownViewManager', 'update end');
|
||||||
|
}
|
||||||
|
}
|
5
src/managers/selectors/index.ts
Normal file
5
src/managers/selectors/index.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
/*
|
||||||
|
In the future, move all selectors here.
|
||||||
|
*/
|
||||||
|
export {ISelector,Selector} from "./selector";
|
||||||
|
export {DropDownSelector} from "./dropDownSelector";
|
0
src/managers/selectors/listSelector.ts
Normal file
0
src/managers/selectors/listSelector.ts
Normal file
52
src/managers/selectors/selector.ts
Normal file
52
src/managers/selectors/selector.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import powerbi from "powerbi-visuals-api";
|
||||||
|
import * as settings from "../../settings";
|
||||||
|
import * as d3 from "d3";
|
||||||
|
import { EventEmitter } from "events";
|
||||||
|
type Selection<T extends d3.BaseType> = d3.Selection<T, any, any, any>;
|
||||||
|
export interface ISelector extends EventEmitter{
|
||||||
|
update(field: powerbi.DataViewCategoryColumn, defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn):void;
|
||||||
|
dispose():void;
|
||||||
|
select(items:string[]):void;
|
||||||
|
updateFormat(itemsSetting:settings.ItemsSetting,width:number,height:number):void;
|
||||||
|
stringFieldFilter_event:string;//filter a string field, give one param: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class Selector extends EventEmitter implements ISelector{
|
||||||
|
protected field: powerbi.DataViewCategoryColumn;
|
||||||
|
protected defaultSelect: powerbi.DataViewValueColumn;
|
||||||
|
protected defaultStart: powerbi.DataViewValueColumn;
|
||||||
|
protected defaultEnd: powerbi.DataViewValueColumn;
|
||||||
|
//events
|
||||||
|
public stringFieldFilter_event:string="stringFieldFilter_event";
|
||||||
|
|
||||||
|
protected checkFieldChange(field: powerbi.DataViewCategoryColumn):boolean{
|
||||||
|
//Field is not null, so first check the old field
|
||||||
|
if(!this.field){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(field.source.queryName==this.field.source.queryName){
|
||||||
|
console.debug('checkFieldChange: false');
|
||||||
|
return false;
|
||||||
|
}else{
|
||||||
|
console.debug('checkFieldChange: true');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected abstract checkDefaultSelectionChange(defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn):boolean;
|
||||||
|
protected checkFieldAndDefaultSelectionChange(field: powerbi.DataViewCategoryColumn, defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn){
|
||||||
|
console.debug('checkFieldAndDefaultSelectionChange start');
|
||||||
|
let flag:boolean=this.checkFieldChange(field)||this.checkDefaultSelectionChange(defaultSelect,defaultStart,defaultEnd)
|
||||||
|
console.debug('checkFieldAndDefaultSelectionChange end, result:',flag);
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
constructor(container:Selection<HTMLDivElement>){
|
||||||
|
super();
|
||||||
|
console.debug("Abstract selector:","constructor start");
|
||||||
|
this.createView(container);
|
||||||
|
}
|
||||||
|
public abstract select(items: string[]):void;
|
||||||
|
public abstract updateFormat(itemsSetting: settings.ItemsSetting,width:number,height:number):void;
|
||||||
|
protected abstract createView(container:Selection<HTMLDivElement>):void;
|
||||||
|
public abstract dispose():void;
|
||||||
|
public abstract update(field: powerbi.DataViewCategoryColumn, defaultSelect: powerbi.DataViewValueColumn, defaultStart: powerbi.DataViewValueColumn, defaultEnd: powerbi.DataViewValueColumn):void;
|
||||||
|
}
|
1
src/settings/enums/index.ts
Normal file
1
src/settings/enums/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export {Outline,getOutlineStyle} from "./outline";
|
38
src/settings/enums/outline.ts
Normal file
38
src/settings/enums/outline.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
"Use strict";
|
||||||
|
export enum Outline {
|
||||||
|
None, BottomOnly, TopOnly, LeftOnly, RightOnly, TopAndBottom, LeftAndRight, Frame
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function getOutlineStyle(outline: Outline): string {
|
||||||
|
let outlineStyle: string;
|
||||||
|
switch (outline) {
|
||||||
|
case Outline.None:
|
||||||
|
outlineStyle = 'none';
|
||||||
|
break;
|
||||||
|
case Outline.BottomOnly:
|
||||||
|
outlineStyle = 'none none solid none';
|
||||||
|
break;
|
||||||
|
case Outline.TopOnly:
|
||||||
|
outlineStyle = 'solid none none none';
|
||||||
|
break;
|
||||||
|
case Outline.LeftOnly:
|
||||||
|
outlineStyle = 'none none none solid';
|
||||||
|
break;
|
||||||
|
case Outline.RightOnly:
|
||||||
|
outlineStyle = 'none solid none none';
|
||||||
|
break;
|
||||||
|
case Outline.TopAndBottom:
|
||||||
|
outlineStyle = 'solid none';
|
||||||
|
break;
|
||||||
|
case Outline.LeftAndRight:
|
||||||
|
outlineStyle = 'none solid';
|
||||||
|
break;
|
||||||
|
case Outline.Frame:
|
||||||
|
outlineStyle = 'solid';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return outlineStyle;
|
||||||
|
}
|
4
src/settings/index.ts
Normal file
4
src/settings/index.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export {ItemsSetting} from "./itemsSetting";
|
||||||
|
export {SlicerHeaderSetting} from "./slicerHeaderSetting";
|
||||||
|
export {VisualSettings} from "./visualSettings";
|
||||||
|
export * as Enums from "./enums";
|
8
src/settings/itemsSetting.ts
Normal file
8
src/settings/itemsSetting.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
"Use strict";
|
||||||
|
import * as enums from "./enums"
|
||||||
|
export class ItemsSetting{
|
||||||
|
public fontColor:string="black";
|
||||||
|
public backgroundColor:string='transparent';
|
||||||
|
public outline:enums.Outline=enums.Outline.None;
|
||||||
|
public textSize:number=10;
|
||||||
|
}
|
11
src/settings/slicerHeaderSetting.ts
Normal file
11
src/settings/slicerHeaderSetting.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
"Use strict";
|
||||||
|
|
||||||
|
import * as enums from "./enums";
|
||||||
|
|
||||||
|
export class SlicerHeaderSetting{
|
||||||
|
public fontColor:string='';
|
||||||
|
public backgroundColor:string='';
|
||||||
|
public outline:enums.Outline=enums.Outline.None;
|
||||||
|
public outlineWeight:number=2;
|
||||||
|
public outlineColor:string="gray";
|
||||||
|
}
|
@ -28,21 +28,11 @@
|
|||||||
|
|
||||||
import { dataViewObjectsParser } from "powerbi-visuals-utils-dataviewutils";
|
import { dataViewObjectsParser } from "powerbi-visuals-utils-dataviewutils";
|
||||||
import DataViewObjectsParser = dataViewObjectsParser.DataViewObjectsParser;
|
import DataViewObjectsParser = dataViewObjectsParser.DataViewObjectsParser;
|
||||||
|
import {SlicerHeaderSetting} from "./slicerHeaderSetting";
|
||||||
|
import {ItemsSetting} from "./itemsSetting";
|
||||||
export class VisualSettings extends DataViewObjectsParser {
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ import VisualObjectInstance = powerbi.VisualObjectInstance;
|
|||||||
import DataView = powerbi.DataView;
|
import DataView = powerbi.DataView;
|
||||||
import VisualObjectInstanceEnumerationObject = powerbi.VisualObjectInstanceEnumerationObject;
|
import VisualObjectInstanceEnumerationObject = powerbi.VisualObjectInstanceEnumerationObject;
|
||||||
import IVisualEventService = powerbi.extensibility.IVisualEventService;
|
import IVisualEventService = powerbi.extensibility.IVisualEventService;
|
||||||
|
import SelectionManager=powerbi.extensibility.ISelectionManager;
|
||||||
import * as visualInterfaces from "./visualInterfaces";
|
import * as visualInterfaces from "./visualInterfaces";
|
||||||
import IVisualHost = powerbi.extensibility.visual.IVisualHost;
|
import IVisualHost = powerbi.extensibility.visual.IVisualHost;
|
||||||
import { VisualSettings } from "../settings/visualSettings";
|
import { VisualSettings } from "../settings/visualSettings";
|
||||||
@ -43,8 +44,10 @@ import {FilterManager,ManagerFactory,SelectorManager,LayoutManager} from "../man
|
|||||||
import * as d3 from "d3";
|
import * as d3 from "d3";
|
||||||
import { getObject } from "powerbi-visuals-utils-dataviewutils/lib/dataViewObjects";
|
import { getObject } from "powerbi-visuals-utils-dataviewutils/lib/dataViewObjects";
|
||||||
import { getMeasureIndexOfRole } from "powerbi-visuals-utils-dataviewutils/lib/dataRoleHelper";
|
import { getMeasureIndexOfRole } from "powerbi-visuals-utils-dataviewutils/lib/dataRoleHelper";
|
||||||
import { selector } from "d3";
|
import { selector, json } from "d3";
|
||||||
|
import { debuglog } from "util";
|
||||||
|
import { EventEmitter } from "events";
|
||||||
|
import * as models from 'powerbi-models';
|
||||||
export class Visual implements IVisual {
|
export class Visual implements IVisual {
|
||||||
/*
|
/*
|
||||||
SelectorManager: a custom manager, used to manage dropDownSelector, listSelector, calendarSelector, and so on
|
SelectorManager: a custom manager, used to manage dropDownSelector, listSelector, calendarSelector, and so on
|
||||||
@ -52,39 +55,63 @@ export class Visual implements IVisual {
|
|||||||
*/
|
*/
|
||||||
private events: IVisualEventService;
|
private events: IVisualEventService;
|
||||||
private settings: VisualSettings;
|
private settings: VisualSettings;
|
||||||
|
private selectionManager:SelectionManager;
|
||||||
private layoutManager: visualInterfaces.ILayoutManager;
|
private layoutManager: visualInterfaces.ILayoutManager;
|
||||||
private selectorManager: visualInterfaces.ISelectorManager;
|
private selectorManager: visualInterfaces.ISelectorManager&EventEmitter;
|
||||||
private view:SVGElement;
|
|
||||||
private filterManager:visualInterfaces.IFilterManager;
|
private filterManager:visualInterfaces.IFilterManager;
|
||||||
private selectionManager:powerbi.extensibility.ISelectionManager;
|
private readonly id:number;
|
||||||
|
private isFirstUpdate:boolean=true;
|
||||||
|
//private selectionManager:powerbi.extensibility.ISelectionManager;
|
||||||
constructor(options: VisualConstructorOptions) {
|
constructor(options: VisualConstructorOptions) {
|
||||||
console.debug('Visual constructor', options);
|
console.debug('Visual constructor start');
|
||||||
|
console.debug('options:',options);
|
||||||
this.events = options.host.eventService;
|
this.events = options.host.eventService;
|
||||||
if (document) {
|
if (document) {
|
||||||
this.selectionManager =options.host.createSelectionManager();
|
//this.selectionManager =options.host.createSelectionManager();
|
||||||
let container=d3.select(options.element).append("div").classed("container",true);
|
let container=d3.select(options.element).append("div").classed("container",true);
|
||||||
d3.select(options.element).on('contextmenu', () => {
|
|
||||||
const mouseEvent: MouseEvent = <MouseEvent>d3.event;
|
//overload context menu
|
||||||
//const eventTarget: EventTarget = mouseEvent.target;
|
let coverContextMenu=false;
|
||||||
//let dataPoint = d3.select(eventTarget).datum();
|
if(coverContextMenu){
|
||||||
this.selectionManager.showContextMenu({}, {
|
d3.select(options.element).on('contextmenu', () => {
|
||||||
x: mouseEvent.clientX,
|
const mouseEvent: MouseEvent = <MouseEvent>d3.event;
|
||||||
y: mouseEvent.clientY
|
//const eventTarget: EventTarget = mouseEvent.target;
|
||||||
|
//let dataPoint = d3.select(eventTarget).datum();
|
||||||
|
this.selectionManager.showContextMenu({}, {
|
||||||
|
x: mouseEvent.clientX,
|
||||||
|
y: mouseEvent.clientY
|
||||||
|
});
|
||||||
|
//mouseEvent.preventDefault();
|
||||||
});
|
});
|
||||||
//mouseEvent.preventDefault();
|
}
|
||||||
});
|
|
||||||
let headerContainer=container.append("div").classed("header-container",true);
|
//First, create the filterManager
|
||||||
let selectorContainer=container.append("div").classed("selector-container",true);
|
|
||||||
this.layoutManager=ManagerFactory.CreateLayoutManager(LayoutManager,container);
|
|
||||||
this.filterManager=ManagerFactory.CreateFilterManager(FilterManager,options.host);
|
this.filterManager=ManagerFactory.CreateFilterManager(FilterManager,options.host);
|
||||||
this.selectorManager=ManagerFactory.CreateSelectorManager(SelectorManager,selectorContainer,this.filterManager);
|
//Then, layoutManager and selectorManager, both use the filterManager
|
||||||
|
//Lagyoutmanager manage the whole div and the slicer-header
|
||||||
|
this.layoutManager=ManagerFactory.CreateLayoutManager(LayoutManager,container,this.filterManager);
|
||||||
|
//SelectorManager manage selectors
|
||||||
|
let selectorContainer=container.append("div").classed("selector-container",true);
|
||||||
|
this.selectorManager=ManagerFactory.CreateSelectorManager(SelectorManager,selectorContainer);
|
||||||
|
|
||||||
|
//events
|
||||||
|
this.selectorManager.on(this.selectorManager.stringFieldFilter_event,(selectionValues:string[],applyNow:boolean)=>{
|
||||||
|
this.filterManager.setFilter_String(selectionValues,applyNow);
|
||||||
|
});
|
||||||
|
console.debug('selectorManager stringFieldFilter_event registered');
|
||||||
|
//set id
|
||||||
|
this.id=Math.random();
|
||||||
}
|
}
|
||||||
console.debug('end constructor');
|
console.debug('end constructor');
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(options: VisualUpdateOptions) {
|
public update(options: VisualUpdateOptions) {
|
||||||
console.debug('visual update start');
|
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.events.renderingStarted(options);
|
||||||
|
this.filterManager.inAdvancedEditMode=options.editMode==powerbi.EditMode.Advanced
|
||||||
this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
|
this.settings = Visual.parseSettings(options && options.dataViews && options.dataViews[0]);
|
||||||
let dataView=options.dataViews[0];
|
let dataView=options.dataViews[0];
|
||||||
let field=dataView.categorical.categories[0];
|
let field=dataView.categorical.categories[0];
|
||||||
@ -108,16 +135,60 @@ export class Visual implements IVisual {
|
|||||||
let height:number=options.viewport.height;
|
let height:number=options.viewport.height;
|
||||||
|
|
||||||
console.debug("start layoutManager updateView");
|
console.debug("start layoutManager updateView");
|
||||||
this.layoutManager.update(dataView,width-10,height-10);
|
this.layoutManager.update(dataView,width,height);
|
||||||
|
|
||||||
console.debug("start selectorManager updateView");
|
|
||||||
this.selectorManager.updateData(field,defaultSelect,defaultStart,defaultEnd);
|
|
||||||
|
|
||||||
console.debug("start filterManager updateView");
|
console.debug("start filterManager updateView");
|
||||||
this.filterManager.update(field);
|
this.filterManager.update(field);
|
||||||
|
|
||||||
|
console.debug("start selectorManager update");
|
||||||
|
this.selectorManager.updateData(field,defaultSelect,defaultStart,defaultEnd);
|
||||||
|
this.selectorManager.updateFormat(this.settings,width,height);
|
||||||
|
console.debug("previous filter",JSON.stringify(options.jsonFilters));
|
||||||
|
/*
|
||||||
|
Compare two jsonFilters(filterManager.jsonFilter and options.jsonFilters[0]).
|
||||||
|
Use method JSON.stringify.
|
||||||
|
1. filterManager.jsonFilter is null, options.jsonFilter[0] is null
|
||||||
|
Don't restore
|
||||||
|
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]))){
|
||||||
|
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');
|
||||||
|
}
|
||||||
|
console.debug('visual update end');
|
||||||
|
this.isFirstUpdate=false;
|
||||||
|
this.filterManager.applyJsonFilter();
|
||||||
this.events.renderingFinished(options);
|
this.events.renderingFinished(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static parseSettings(dataView: DataView): VisualSettings {
|
private static parseSettings(dataView: DataView): VisualSettings {
|
||||||
return <VisualSettings>VisualSettings.parse(dataView);
|
return <VisualSettings>VisualSettings.parse(dataView);
|
||||||
}
|
}
|
||||||
|
@ -6,35 +6,51 @@ import {VisualSettings} from "../settings/visualSettings";
|
|||||||
import * as d3 from "d3";
|
import * as d3 from "d3";
|
||||||
import { IFilter } from "powerbi-models";
|
import { IFilter } from "powerbi-models";
|
||||||
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 {EventEmitter} from "events";
|
||||||
|
import * as models from 'powerbi-models';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Main interfaces
|
Main interfaces
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//IVisualSettings
|
||||||
|
|
||||||
|
|
||||||
//ISelectorManager
|
//ISelectorManager
|
||||||
export interface ILayoutManager{
|
export interface ILayoutManager{
|
||||||
layout:Selection<HTMLElement>;
|
layout:Selection<HTMLElement>;
|
||||||
update(dataView:DataView,width:number,height:number):void;
|
update(dataView:DataView,width:number,height:number):void;
|
||||||
|
dispose():void;
|
||||||
}
|
}
|
||||||
export interface ILayoutManagerConstructor{
|
export interface ILayoutManagerConstructor{
|
||||||
new(container:Selection<HTMLElement>):ILayoutManager;
|
new(container:Selection<HTMLElement>,filterManager:IFilterManager):ILayoutManager;
|
||||||
};
|
}
|
||||||
|
|
||||||
//ISelectorManager
|
//ISelectorManager
|
||||||
|
|
||||||
export interface ISelectorManager{
|
export interface ISelectorManager{
|
||||||
selectorContainer:Selection<HTMLElement>;
|
selectorContainer:Selection<HTMLElement>;
|
||||||
filterManager:IFilterManager;
|
stringFieldFilter_event:string;//filter a string field, give one param: string[]
|
||||||
updateData(field:powerbi.DataViewCategoryColumn,defaultSelect:powerbi.DataViewValueColumn,defaultStart:powerbi.DataViewValueColumn,defaultEnd:powerbi.DataViewValueColumn);
|
dispose():void;
|
||||||
|
updateData(field:powerbi.DataViewCategoryColumn,defaultSelect:powerbi.DataViewValueColumn,defaultStart:powerbi.DataViewValueColumn,defaultEnd:powerbi.DataViewValueColumn):void;
|
||||||
|
updateFormat(visualSettings:VisualSettings,width:number,height:number):void;
|
||||||
|
select(items:string[]):void;
|
||||||
|
|
||||||
}
|
}
|
||||||
export interface ISelectorManagerConstructor{
|
export interface ISelectorManagerConstructor{
|
||||||
new(selectorContainer:Selection<HTMLElement>,filterManager:IFilterManager):ISelectorManager;
|
new(selectorContainer:Selection<HTMLElement>):ISelectorManager&EventEmitter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//IFilterManager
|
//IFilterManager
|
||||||
export interface IFilterManager{
|
export interface IFilterManager{
|
||||||
|
jsonFilter:models.IAdvancedFilter;
|
||||||
|
inAdvancedEditMode:boolean;
|
||||||
update(field:powerbi.DataViewCategoryColumn):void;
|
update(field:powerbi.DataViewCategoryColumn):void;
|
||||||
filterStringField(selection:string[]):void;
|
setFilter_String(selection:string[],applyNow:boolean):void;
|
||||||
|
setFilter(jsonFilter:models.IAdvancedFilter,applyNow:boolean):void;
|
||||||
|
applyJsonFilter():void;
|
||||||
|
clear():void;
|
||||||
|
dispose():void;
|
||||||
}
|
}
|
||||||
export interface IFilterManagerConstructor{
|
export interface IFilterManagerConstructor{
|
||||||
new(host:IVisualHost):IFilterManager;
|
new(host:IVisualHost):IFilterManager;
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
@import "/node_modules/bootstrap/dist/css/bootstrap.min.css";
|
|
||||||
@import "/node_modules/bootstrap-multiselect/dist/css/bootstrap-multiselect.css";
|
|
||||||
p {
|
p {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user