Skip to content

Commit

Permalink
Labels issue (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
Elena Rodionova authored and ignatvilesov committed Nov 16, 2018
1 parent f3d256e commit 52b7df0
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 63 deletions.
4 changes: 2 additions & 2 deletions src/behavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@
import Selection = d3.Selection;

// powerbi.extensibility.utils.interactivity
import {interactivityService} from "powerbi-visuals-utils-interactivityutils";
import { interactivityService } from "powerbi-visuals-utils-interactivityutils";
import IInteractiveBehavior = interactivityService.IInteractiveBehavior;
import ISelectionHandler = interactivityService.ISelectionHandler;
import IInteractivityService = interactivityService.IInteractivityService;
import { StreamGraphSeries } from "./dataInterfaces";
import {getFillOpacity} from "./utils";
import { getFillOpacity } from "./utils";

export interface BehaviorOptions {
selection: Selection<d3.BaseType, StreamGraphSeries, any, any>;
Expand Down
2 changes: 2 additions & 0 deletions src/dataInterfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ export interface StreamDataPoint extends IDataLabelInfo {
y0?: number;
text: string;
labelFontSize: string;
value?: number;
highlight?: boolean;
}

export interface StreamGraphSeries extends SelectableDataPoint {
Expand Down
40 changes: 29 additions & 11 deletions src/visual.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,8 @@ export class StreamGraph implements IVisual {
? y
: StreamGraph.DefaultValue,
text: label,
labelFontSize: fontSizeInPx
labelFontSize: fontSizeInPx,
highlight: hasHighlights && values[valueIndex].highlights && values[valueIndex].highlights[dataPointValueIndex] !== null
};

series[valueIndex].dataPoints.push(streamDataPoint);
Expand All @@ -351,6 +352,10 @@ export class StreamGraph implements IVisual {
}
stackValues[dataPointValueIndex][label] = streamDataPoint.y;

if (!stackValues[dataPointValueIndex]["highlight"]) {
stackValues[dataPointValueIndex]["highlight"] = streamDataPoint.highlight ? 1 : 0;
}

if (streamDataPoint.x > xMaxValue) {
xMaxValue = streamDataPoint.x;
}
Expand Down Expand Up @@ -413,8 +418,6 @@ export class StreamGraph implements IVisual {
let xAxisFontSize: number = +settings.categoryAxis.fontSize;
let xAxisFontHalfSize: number = xAxisFontSize / 2;



/* Generate stack values for d3.stack V5 */
const allLabels = legendData.dataPoints.map((dataPoint) => dataPoint.label);

Expand Down Expand Up @@ -514,6 +517,10 @@ export class StreamGraph implements IVisual {

this.clearCatcher = appendClearCatcher(this.svg);

this.dataPointsContainer = this.svg
.insert("g")
.classed(StreamGraph.DataPointsContainer, true);

this.axes = this.svg
.append("g")
.classed(StreamGraph.Axes.className, true)
Expand All @@ -528,10 +535,6 @@ export class StreamGraph implements IVisual {
.classed(StreamGraph.Axis.className, true)
.classed(StreamGraph.YAxis.className, true);

this.dataPointsContainer = this.svg
.append("g")
.classed(StreamGraph.DataPointsContainer, true);

this.behavior = new StreamGraphBehavior();

this.interactivityService = createInteractivityService(this.visualHost);
Expand Down Expand Up @@ -580,10 +583,14 @@ export class StreamGraph implements IVisual {
this.svg.attr("width", PixelConverter.toString(this.viewport.width));
this.svg.attr("height", PixelConverter.toString(this.viewport.height));

const values: DataViewValueColumns = this.dataView.categorical.values;
const hasHighlights: boolean = !!(values.length > 0 && values[0].highlights);

const selection: Selection<d3.BaseType, StreamGraphSeries, any, any> = this.renderChart(
this.data.series,
this.data.stackedSeries,
StreamGraph.AnimationDuration
StreamGraph.AnimationDuration,
hasHighlights
);

this.calculateAxes();
Expand Down Expand Up @@ -899,7 +906,8 @@ export class StreamGraph implements IVisual {
private renderChart(
series: StreamGraphSeries[],
stackedSeries: d3.Series<any, any>[],
duration: number
duration: number,
hasHighlights: boolean = false
): Selection<d3.BaseType, StreamGraphSeries, any, any> {

const { width, height } = this.viewport;
Expand Down Expand Up @@ -987,6 +995,7 @@ export class StreamGraph implements IVisual {
stackedSeries.forEach((seriesItem: d3.Series<any, any>) => {
let filteredDataPoints: any[];


filteredDataPoints = seriesItem.filter((dataPoint: any) => {
return dataPoint && dataPoint[0] !== null && dataPoint[0] !== undefined;
}).map((dataPoint: any) => {
Expand All @@ -995,7 +1004,8 @@ export class StreamGraph implements IVisual {
y0: dataPoint[0],
y: dataPoint[1],
text: seriesItem.key,
value: dataPoint.data[seriesItem.key]
value: dataPoint.data[seriesItem.key],
highlight: dataPoint.data.highlight
};
});

Expand All @@ -1005,10 +1015,18 @@ export class StreamGraph implements IVisual {
});

const viewport: IViewport = {
height: height - (this.margin.top + this.data.yAxisFontHalfSize) - margin.bottom,
height: height - (this.margin.top + this.data.yAxisFontHalfSize),
width: width - (this.margin.right + this.data.xAxisValueMaxTextHalfSize) - margin.left,
};

if (hasHighlights) {
const highlightedPointArray: StreamDataPoint[] = dataPointsArray.filter((d: StreamDataPoint) => d.highlight && d.value !== StreamGraph.DefaultValue);
const additionalPointsArray: StreamDataPoint[] = dataPointsArray.filter((d: StreamDataPoint) => highlightedPointArray[0] && d.text === highlightedPointArray[0].text && d.x < highlightedPointArray[0].x);
dataPointsArray = additionalPointsArray.concat(highlightedPointArray);
}

dataLabelUtils.cleanDataLabels(this.svg);

const labels: Selection<d3.BaseType, StreamDataPoint, any, any> =
dataLabelUtils.drawDefaultLabelsForDataPointChart(
dataPointsArray,
Expand Down
1 change: 1 addition & 0 deletions test.webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const webpack = require("webpack");

module.exports = {
devtool: 'source-map',
mode: 'development',
module: {
rules: [
{
Expand Down
131 changes: 82 additions & 49 deletions test/visualData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,36 +32,55 @@ import { ValueType } from "powerbi-visuals-utils-typeutils/lib/valueType";
// powerbi.extensibility.utils.test
import { getRandomNumbers } from "powerbi-visuals-utils-testutils";
import { TestDataViewBuilder, TestDataViewBuilderCategoryColumnOptions } from "powerbi-visuals-utils-testutils/lib/dataViewBuilder/testDataViewBuilder";
import { DataViewBuilderValuesColumnOptions } from "powerbi-visuals-utils-testutils/lib/dataViewBuilder/dataViewBuilder";
import { getRandomUniqueSortedDates } from "./helpers/helpers";

const maxValue: number = 100;

export class ProductSalesByDateData extends TestDataViewBuilder {
private static DefaultFormat: string = "$0,000.00";
private static DefaultDateFormat: string = "dddd MMMM d yyyy";
private static DefaultGroupName: string = "Product";

public static ColumnCategory: string = "Date";
public static GroupCategory: string = "Group";
public static ColumnValues1: string = "Product sales 1";
public static ColumnValues2: string = "Product sales 2";
public static ColumnValues3: string = "Product sales 3";
public static ColumnValues4: string = "Product sales 4";
public static GroupNames: string[] = ["Product 1", "Product 2", "Product 3", "Product 4"];
public static ColumnValues: string[] = ["Product sales 1", "Product sales 2", "Product sales 3", "Product sales 4"];

public valuesDate: Date[] = getRandomUniqueSortedDates(
50,
new Date(2014, 0, 1),
new Date(2015, 5, 10));

public valuesSales1: number[] = getRandomNumbers(this.valuesDate.length);
public valuesSales2: number[] = getRandomNumbers(this.valuesDate.length);
public valuesSales3: number[] = getRandomNumbers(this.valuesDate.length);
public valuesSales4: number[] = getRandomNumbers(this.valuesDate.length);
public valuesSales: [number[], number[], number[], number[]] = [
getRandomNumbers(this.valuesDate.length, -maxValue, maxValue),
getRandomNumbers(this.valuesDate.length, -maxValue, maxValue),
getRandomNumbers(this.valuesDate.length, -maxValue, maxValue),
getRandomNumbers(this.valuesDate.length, -maxValue, maxValue)
];

public groups: string[] = [
"FirstGroup",
"SecondGroup"
];

public getDataView(columnNames?: string[], isGroupsEnabled: boolean = false): DataView {
public generateHightLightedValues(valuesArray: number[], hightlightedElementNumber?: number): number[] {
let array: number[] = [];
const lenght: number = valuesArray.length;
for (let i: number = 0; i < lenght; i++) {
array[i] = null;
}
if (!hightlightedElementNumber)
return array;
if (hightlightedElementNumber >= lenght || hightlightedElementNumber < 0) {
array[0] = valuesArray[0];
} else {
array[hightlightedElementNumber] = valuesArray[hightlightedElementNumber];
}
return array;
}

public getDataView(columnNames?: string[], isGroupsEnabled: boolean = false, withHighlights: boolean = false, hightlightedIndex: number = 0, hightlightedElementNumber: number = 0): DataView {
const categoriesColumn: TestDataViewBuilderCategoryColumnOptions[] = [{
source: {
displayName: ProductSalesByDateData.ColumnCategory,
Expand All @@ -82,48 +101,62 @@ export class ProductSalesByDateData extends TestDataViewBuilder {
});
}

let columns: DataViewBuilderValuesColumnOptions[] = [{
source: {
displayName: ProductSalesByDateData.ColumnValues[0],
isMeasure: true,
format: ProductSalesByDateData.DefaultFormat,
groupName: ProductSalesByDateData.DefaultGroupName,
type: ValueType.fromDescriptor({ numeric: true })
},
values: this.valuesSales[0]
}, {
source: {
displayName: ProductSalesByDateData.ColumnValues[1],
isMeasure: true,
format: ProductSalesByDateData.DefaultFormat,
groupName: ProductSalesByDateData.DefaultGroupName,
type: ValueType.fromDescriptor({ numeric: true })
},
values: this.valuesSales[1]
}, {
source: {
displayName: ProductSalesByDateData.ColumnValues[2],
isMeasure: true,
format: ProductSalesByDateData.DefaultFormat,
groupName: ProductSalesByDateData.DefaultGroupName,
type: ValueType.fromDescriptor({ numeric: true })
},
values: this.valuesSales[2]
}, {
source: {
displayName: ProductSalesByDateData.ColumnValues[3],
isMeasure: true,
format: ProductSalesByDateData.DefaultFormat,
groupName: ProductSalesByDateData.DefaultGroupName,
type: ValueType.fromDescriptor({ numeric: true })
},
values: this.valuesSales[3]
}];

if (withHighlights) {
columns[hightlightedIndex].highlights = this.generateHightLightedValues(this.valuesSales[hightlightedIndex], hightlightedElementNumber);
columns[hightlightedIndex].source.groupName = ProductSalesByDateData.GroupNames[hightlightedIndex];

for (let i = 0; i < columns.length; i++) {
if (i !== hightlightedIndex) {
columns[i].highlights = this.generateHightLightedValues(this.valuesSales[i]);
columns[i].source.groupName = ProductSalesByDateData.GroupNames[i];
}
}
}

return this.createCategoricalDataViewBuilder(
categoriesColumn, [
{
source: {
displayName: ProductSalesByDateData.ColumnValues1,
isMeasure: true,
format: ProductSalesByDateData.DefaultFormat,
groupName: ProductSalesByDateData.DefaultGroupName,
type: ValueType.fromDescriptor({ numeric: true })
},
values: this.valuesSales1
},
{
source: {
displayName: ProductSalesByDateData.ColumnValues2,
isMeasure: true,
format: ProductSalesByDateData.DefaultFormat,
groupName: ProductSalesByDateData.DefaultGroupName,
type: ValueType.fromDescriptor({ numeric: true })
},
values: this.valuesSales1
},
{
source: {
displayName: ProductSalesByDateData.ColumnValues3,
isMeasure: true,
format: ProductSalesByDateData.DefaultFormat,
groupName: ProductSalesByDateData.DefaultGroupName,
type: ValueType.fromDescriptor({ numeric: true })
},
values: this.valuesSales2
},
{
source: {
displayName: ProductSalesByDateData.ColumnValues4,
isMeasure: true,
format: ProductSalesByDateData.DefaultFormat,
groupName: ProductSalesByDateData.DefaultGroupName,
type: ValueType.fromDescriptor({ numeric: true })
},
values: this.valuesSales3
}
columns[0],
columns[1],
columns[2],
columns[3]
], columnNames).build();
}
}
Loading

0 comments on commit 52b7df0

Please sign in to comment.