New option: Provide min optimal height of node (#40)

* New option: Provide min optimal height of node
* Settings tests added
* Change variable name to camel case
This commit is contained in:
Ilfat Galiev 2017-11-24 14:24:58 +03:00 коммит произвёл Ignat Vilesov
Родитель 734da5350e
Коммит b76d91ef30
8 изменённых файлов: 118 добавлений и 19 удалений

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

@ -1,3 +1,7 @@
## 1.6.0
* New option: provide min optimal height of node
## 1.5.2
* Drag&drop crashes browser - fix

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

@ -212,12 +212,19 @@
}
},
"scaleSettings": {
"displayName": "Enable logarithmic scale",
"displayNameKey": "Visual_ScaleSettings",
"displayName": "Scale settings",
"displayNameKey": "Visual_SankeyScaleSettings",
"properties": {
"show": {
"displayName": "Enable",
"displayNameKey": "Visual_Enable",
"lnScale": {
"displayName": "Enable logarithmic scale",
"displayNameKey": "Visual_ScaleSettings",
"type": {
"bool": true
}
},
"provideMinHeight": {
"displayName": "Provide min optimal height of node",
"displayNameKey": "Visual_MinOptimalHeight",
"type": {
"bool": true
}

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

@ -59,6 +59,6 @@
"powerbi-visuals-utils-tooltiputils": "^0.3.0",
"powerbi-visuals-utils-typeutils": "^0.2.0",
"tslint": "4.0.2",
"typings": "2.0.0"
"typescript": "2.1.5"
}
}

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

@ -1,10 +1,10 @@
{
"visual": {
"name": "SankeyDiagram",
"displayName": "Sankey 1.5.2",
"displayName": "Sankey 1.6.0",
"guid": "SankeyDiagram1446463184954",
"visualClassName": "SankeyDiagram",
"version": "1.5.2",
"version": "1.6.0",
"description": "Sankey is a type of flow diagram in which the width of the series is in proportion to the quantity of the flow. Use it to find major contributions to an overall flow.",
"supportUrl": "http://community.powerbi.com",
"gitHubUrl": "https://github.com/Microsoft/powerbi-visuals-sankey"

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

@ -51,8 +51,9 @@ module powerbi.extensibility.visual {
public y: number = 1;
}
export class SankeyLnScaleSettings {
public show: boolean = false;
export class SankeyScaleSettings {
public provideMinHeight: boolean = true;
public lnScale: boolean = false;
}
export class SankeyComplexSettings {
@ -69,7 +70,7 @@ module powerbi.extensibility.visual {
public linkLabels: SankeyDiagramLinkLabelsSettings = new SankeyDiagramLinkLabelsSettings();
public labels: SankeyDiagramLabelsSettings = new SankeyDiagramLabelsSettings();
public _scale: SankeyDiagramScaleSettings = new SankeyDiagramScaleSettings();
public scaleSettings: SankeyLnScaleSettings = new SankeyLnScaleSettings();
public scaleSettings: SankeyScaleSettings = new SankeyScaleSettings();
public nodeComplexSettings: SankeyComplexSettings = new SankeyComplexSettings();
public _nodePositions: SankeyDiagramNodePositionSetting[] = [];
public _viewportSize: ViewportSize = {};

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

@ -154,15 +154,16 @@ module powerbi.extensibility.visual {
private static MinDomainOfScale = 0;
private static MaxDomainOfScale = 9;
private static MinRangeOfScale = 3;
private static MaxRangeOfScale = 100;
private static DefaultMinRangeOfScale = 3;
private static MinRangeOfScale = 0;
private static DefaultMaxRangeOfScale = 100;
public static DublicatedNamePostfix: string = "_SK_SELFLINK";
private static MinWidthOfLink: number = 1;
private static DefaultWeightOfLink: number = 1;
private static MinHeightOfNode: number = 5;
private static MinHeightOfNode: number = 1;
private static ScaleStep: number = 0.1;
private static ScaleStepLimit: number = 1;
@ -887,18 +888,20 @@ module powerbi.extensibility.visual {
maxWeightInData = maxWeigthLink.weigth;
}
let minRangeOfScale: number = sankeyDiagramDataView.settings.scaleSettings.provideMinHeight ? SankeyDiagram.DefaultMinRangeOfScale : SankeyDiagram.MinRangeOfScale;
while (minHeight <= SankeyDiagram.MinHeightOfNode && scaleStepCount < SankeyDiagram.ScaleStepLimit) {
let weightScale: any;
if (sankeyDiagramDataView.settings.scaleSettings.show) {
if (sankeyDiagramDataView.settings.scaleSettings.lnScale) {
weightScale = d3.scale.log()
.base(Math.E)
.domain([Math.exp(SankeyDiagram.MinDomainOfScale + scaleShift), Math.exp(SankeyDiagram.MaxDomainOfScale + scaleShift)])
.range([SankeyDiagram.MinRangeOfScale, SankeyDiagram.MaxRangeOfScale]);
.range([minRangeOfScale, SankeyDiagram.DefaultMaxRangeOfScale]);
} else {
weightScale = d3.scale.linear()
.domain([minWeightInData + scaleShift, maxWeightInData + scaleShift])
.range([SankeyDiagram.MinRangeOfScale, SankeyDiagram.MaxRangeOfScale]);
.range([minRangeOfScale, SankeyDiagram.DefaultMaxRangeOfScale]);
}
sankeyDiagramDataView.links.forEach((l) => {
@ -917,7 +920,7 @@ module powerbi.extensibility.visual {
}
});
minWeight = Math.abs(minWeight) + SankeyDiagram.MinRangeOfScale;
minWeight = Math.abs(minWeight);
// shift weight values to eliminate negative values
sankeyDiagramDataView.links.forEach((link: SankeyDiagramLink) => {
link.weigth += minWeight;
@ -1289,7 +1292,7 @@ module powerbi.extensibility.visual {
.attr({
x: SankeyDiagram.DefaultPosition,
y: SankeyDiagram.DefaultPosition,
height: (node: SankeyDiagramNode) => node.height,
height: (node: SankeyDiagramNode) => node.height < SankeyDiagram.MinHeightOfNode ? SankeyDiagram.MinHeightOfNode : node.height,
width: (node: SankeyDiagramNode) => node.width
});
@ -1760,6 +1763,10 @@ module powerbi.extensibility.visual {
this.enumerateLinks(instanceEnumeration);
}
// hide scale settings
(<VisualObjectInstanceEnumerationObject>instanceEnumeration).instances = (<VisualObjectInstanceEnumerationObject>instanceEnumeration).instances
.filter( (instance) => instance.objectName !== SankeyDiagram.NodeComplexSettingsPropertyIdentifier.objectName );
return instanceEnumeration || [];
}

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

@ -14,6 +14,8 @@
"Visual_DataPointsLinkLabels": "Data link labels",
"Visual_Links": "Links",
"Visual_ScaleSettings": "Enable logarithmic scale",
"Visual_SankeyScaleSettings": "Scale settings",
"Visual_MinOptimalHeight": "Provide min optimal height of node",
"Visual_Enable": "Enable",
"Visual_SankeySettings": "Sankey settigns",
"Visual_NodePositions": "Node positions",

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

@ -633,6 +633,84 @@ module powerbi.extensibility.visual.test {
});
});
describe("Scale settings test:", () => {
it("the visual must provide min height of node", done => {
let dataView: DataView = defaultDataViewBuilder.getDataViewWithLowValue();
const firstElement: number = 0;
dataView.metadata.objects = {
scaleSettings: {
provideMinHeight: true
}
};
// the dataset has significantly different range of values
// the visual must provide min height of node
dataView.categorical.values[firstElement].values[0] = 1;
dataView.categorical.values[firstElement].values[1] = 1;
dataView.categorical.values[firstElement].values[2] = 1000000;
visualBuilder.updateRenderTimeout([dataView], () => {
const minHeightOfNode: number = 5;
let nodes = visualBuilder.nodeElements;
let minHeight: number = +nodes[firstElement].children[firstElement].getAttribute("height");
nodes.each((index: number, el: HTMLElement) => {
let height = +el.children[firstElement].getAttribute("height");
if (height < minHeight) {
minHeight = height;
}
});
expect(minHeight).toBeGreaterThan(minHeightOfNode);
done();
});
});
it("the visual must not provide min height of node", done => {
let dataView: DataView = defaultDataViewBuilder.getDataViewWithLowValue();
const firstElement: number = 0;
dataView.metadata.objects = {
scaleSettings: {
provideMinHeight: false
}
};
// the dataset has significantly different range of values
// the visual must not provide min height of node
// the height of node can be 1px;npm
dataView.categorical.values[firstElement].values[0] = 1;
dataView.categorical.values[firstElement].values[1] = 1;
dataView.categorical.values[firstElement].values[2] = 1000000;
visualBuilder.updateRenderTimeout([dataView], () => {
const minHeightOfNode: number = 5;
let nodes = visualBuilder.nodeElements;
let minHeight: number = +nodes[firstElement].children[firstElement].getAttribute("height");
nodes.each((index: number, el: HTMLElement) => {
let height = +el.children[firstElement].getAttribute("height");
if (height < minHeight) {
minHeight = height;
}
});
expect(minHeight).toBeLessThan(minHeightOfNode);
done();
});
});
});
describe("Settings tests:", () => {
it("nodeComplexSettings properties must be hidden", done => {
let objectInstanes: VisualObjectInstanceEnumerationObject = <VisualObjectInstanceEnumerationObject>visualBuilder.instance.enumerateObjectInstances({
objectName: "nodeComplexSettings"
});
expect(objectInstanes.instances.length).toBe(0);
done();
});
});
describe("Capabilities tests", () => {
it("all items having displayName should have displayNameKey property", () => {
jasmine.getJSONFixtures().fixturesPath = "base";