Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix colors in high contrast mode and x-axis settings #91

Merged
merged 4 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.0.1.0
* Fix x-axis settings
* Fix colors in high contrast mode

## 3.0.0.0
* Update packages to the latest versions
* Replace custom scroll with native
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# PowerBI-visuals-Tornado
[![build](https://github.com/microsoft/PowerBI-visuals-Tornado/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/microsoft/PowerBI-visuals-Tornado/actions/workflows/build.yml)
[![build](https://github.com/microsoft/PowerBI-visuals-Tornado/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/microsoft/PowerBI-visuals-Tornado/actions/workflows/build.yml)


> A bar chart with category values listed vertically. Use for comparing the relative importance of a variable between two distinct groups.

![Tornado chart screenshot](https://github.com/microsoft/PowerBI-visuals-Tornado/blob/master/assets/screenshot.png?raw=true)
![Tornado chart screenshot](https://github.com/microsoft/PowerBI-visuals-Tornado/blob/main/assets/screenshot.png?raw=true)
# Overview
Tornado charts, are a special type of Bar chart, where the data categories are listed vertically instead of the standard horizontal presentation, and the categories are ordered so that the largest bar appears at the top of the chart, the second largest appears second from the top, and so on. They are so named because the final chart visually resembles either one half of or a complete tornado.

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "powerbi-visuals-tornadochart",
"version": "3.0.0.0",
"version": "3.0.1.0",
"author": {
"name": "Microsoft",
"email": "[email protected]"
Expand Down
4 changes: 2 additions & 2 deletions pbiviz.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"visual": {
"name": "TornadoChart",
"displayName": "Tornado 3.0.0.0",
"displayName": "Tornado 3.0.1.0",
"guid": "TornadoChart1452517688218",
"visualClassName": "TornadoChart",
"version": "3.0.0.0",
"version": "3.0.1.0",
"description": "A bar chart with category values listed vertically. Use for comparing the relative importance of a variable between two distinct groups.",
"supportUrl": "https://community.powerbi.com",
"gitHubUrl": "https://github.com/Microsoft/PowerBI-visuals-Tornado"
Expand Down
35 changes: 23 additions & 12 deletions src/TornadoChart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ type Selection<T> = d3Selection<any, T, any, any>;

import DataView = powerbiVisualsApi.DataView;
import IViewport = powerbiVisualsApi.IViewport;
import DataViewObject = powerbiVisualsApi.DataViewObject;
import DataViewObjects = powerbiVisualsApi.DataViewObjects;
import DataViewObjectPropertyIdentifier = powerbiVisualsApi.DataViewObjectPropertyIdentifier;
import DataViewValueColumn = powerbiVisualsApi.DataViewValueColumn;
import DataViewCategorical = powerbiVisualsApi.DataViewCategorical;
import DataViewValueColumns = powerbiVisualsApi.DataViewValueColumns;
import DataViewObjectWithId = powerbiVisualsApi.DataViewObjectWithId;
import DataViewMetadataColumn = powerbiVisualsApi.DataViewMetadataColumn;
import DataViewCategoryColumn = powerbiVisualsApi.DataViewCategoryColumn;
import DataViewValueColumnGroup = powerbiVisualsApi.DataViewValueColumnGroup;
Expand Down Expand Up @@ -214,7 +216,7 @@ export class TornadoChart implements IVisual {
for (let seriesIndex = 0; seriesIndex < Math.min(values.length, TornadoChart.MaxSeries); seriesIndex++) {
const columnGroup: DataViewValueColumnGroup = groupedValues && groupedValues.length > seriesIndex
&& groupedValues[seriesIndex].values ? groupedValues[seriesIndex] : null;
const parsedSeries: TornadoChartSeries = TornadoChart.parseSeries(dataView, values, hostService, seriesIndex, hasDynamicSeries, columnGroup, colors, formattingSettings);
const parsedSeries: TornadoChartSeries = TornadoChart.parseSeries(dataView, values, hostService, seriesIndex, hasDynamicSeries, columnGroup, colors);
const currentSeries: DataViewValueColumn = values[seriesIndex];
const measureName: string = currentSeries.source.queryName;

Expand Down Expand Up @@ -287,8 +289,7 @@ export class TornadoChart implements IVisual {
index: number,
isGrouped: boolean,
columnGroup: DataViewValueColumnGroup,
colors: IColorPalette,
formattingSettings: TornadoChartSettingsModel): TornadoChartSeries {
colors: IColorPalette): TornadoChartSeries {

if (!dataView) {
return;
Expand All @@ -308,15 +309,18 @@ export class TornadoChart implements IVisual {
sourceGroupName = "" + source.groupName;
}

let objects: DataViewObjects;
let objects: DataViewObjects,
categoryAxisObject: DataViewObject | DataViewObjectWithId[];

const displayName: PrimitiveValue = source ? sourceGroupName
? sourceGroupName : source.displayName
: null;

if (isGrouped && columnGroup && columnGroup.objects) {
categoryAxisObject = columnGroup.objects ? columnGroup.objects["categoryAxis"] : null;
objects = columnGroup.objects;
} else if (source && source.objects) {
categoryAxisObject = objects ? objects["categoryAxis"] : null;
objects = source.objects;
} else if (dataView && dataView.metadata && dataView.metadata.objects) {
objects = dataView.metadata.objects;
Expand All @@ -327,7 +331,12 @@ export class TornadoChart implements IVisual {
["purple", "teal"][index],
objects, colors);

const categoryAxisEnd: number = formattingSettings.categoryAxisCardSettings.end.value;
let categoryAxisEnd: number = categoryAxisObject ? categoryAxisObject["end"] : null;
if(!categoryAxisEnd){
if(objects?.categoryAxis?.end){
categoryAxisEnd = objects.categoryAxis.end as number;
}
}

return <TornadoChartSeries>{
fill: fillColor,
Expand Down Expand Up @@ -991,7 +1000,7 @@ export class TornadoChart implements IVisual {

labelSelectionMerged
.select(TornadoChart.LabelText.selectorName)
.attr("fill", (p: TornadoChartPoint) => p.label.color)
.attr("fill", (p: TornadoChartPoint) => this.colorHelper.isHighContrast ? this.colorHelper.getHighContrastColor("foreground", p.color) : p.label.color)
.attr("font-size", fontSizeInPx)
.attr("font-family", labelFontFamily)
.attr("font-weight", labelFontIsBold ? "bold" : "normal")
Expand Down Expand Up @@ -1062,7 +1071,7 @@ export class TornadoChart implements IVisual {

categoriesSelectionMerged
.select(TornadoChart.CategoryText.selectorName)
.attr("fill", color)
.attr("fill", this.colorHelper.isHighContrast ? this.colorHelper.getHighContrastColor("foreground", color) : color)
.attr("font-size", fontSizeInPx)
.attr("font-family", categoryFontFamily)
.attr("font-weight", categoryFontIsBold ? "bold" : "normal")
Expand All @@ -1086,12 +1095,14 @@ export class TornadoChart implements IVisual {
if (!legend) {
return;
}

const legendLabelsColor: string = formattingSettings.legendCardSettings.labelColor.value.value;
const legendData: LegendData = {
title: legend.title,
dataPoints: legend.dataPoints,
fontSize: formattingSettings.legendCardSettings.font.fontSize.value,
fontFamily: formattingSettings.legendCardSettings.font.fontFamily.value,
labelColor: formattingSettings.legendCardSettings.labelColor.value.value
labelColor: this.colorHelper.isHighContrast ? this.colorHelper.getHighContrastColor("foreground", legendLabelsColor) : legendLabelsColor
};

if (this.dataView.legendObjectProperties) {
Expand All @@ -1105,10 +1116,10 @@ export class TornadoChart implements IVisual {
}

this.legend.drawLegend(legendData, { ...this.viewport });
d3Select(this.element.node()).selectAll("g#legendGroup text")
.style("font-weight", () => this.formattingSettings.legendCardSettings.font.bold.value ? "bold" : "normal")
.style("font-style", () => this.formattingSettings.legendCardSettings.font.italic.value ? "italic" : "normal")
.style("text-decoration", () => this.formattingSettings.legendCardSettings.font.underline.value ? "underline" : "none");
this.element.selectAll("g#legendGroup text")
.style("font-weight", () => this.formattingSettings.legendCardSettings.font.bold.value ? "bold" : "normal")
.style("font-style", () => this.formattingSettings.legendCardSettings.font.italic.value ? "italic" : "normal")
.style("text-decoration", () => this.formattingSettings.legendCardSettings.font.underline.value ? "underline" : "none");

if (legendData.dataPoints.length > 0 && formattingSettings.legendCardSettings.show.value) {
this.updateViewport();
Expand Down
24 changes: 2 additions & 22 deletions src/TornadoChartSettingsModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,7 @@ class CategoryAxisCardSettings extends Card {
name: "end",
displayName: "End",
displayNameKey: "Visual_XAxisEnd",
value: 0,
options: {
minValue: {
type: powerbiVisualsApi.visuals.ValidatorType.Min,
value: 0,
},
maxValue: {
type: powerbiVisualsApi.visuals.ValidatorType.Max,
value: 25,
}
}
value: 0
});

name: string = "categoryAxis";
Expand Down Expand Up @@ -313,17 +303,7 @@ export class TornadoChartSettingsModel extends Model {
value: dataPoint.categoryAxisEnd ? dataPoint.categoryAxisEnd : 0,
selector: ColorHelper.normalizeSelector(
dataPoint.selectionId.getSelector(),
false),
options: {
minValue: {
type: powerbiVisualsApi.visuals.ValidatorType.Min,
value: 0,
},
maxValue: {
type: powerbiVisualsApi.visuals.ValidatorType.Max,
value: 25,
}
}
false)
})
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/TornadoWebBehavior.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class TornadoWebBehavior implements IInteractiveBehavior {
event.ctrlKey || event.metaKey || event.shiftKey);
});

this.columns.on("keypress", (event : KeyboardEvent, dataPoint: TornadoChartPoint) => {
this.columns.on("keydown", (event : KeyboardEvent, dataPoint: TornadoChartPoint) => {
if(event?.code == "Enter" || event?.code == "Space")
{
selectionHandler.handleSelection(
Expand Down
6 changes: 2 additions & 4 deletions test/TornadoChartBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ export class TornadoChartBuilder extends VisualBuilderBase<VisualClass> {
dataViewValueColumns: DataViewValueColumns,
index: number,
isGrouped: boolean,
columnGroup: DataViewValueColumnGroup,
formattingSettings: TornadoChartSettingsModel): TornadoChartSeries {
columnGroup: DataViewValueColumnGroup): TornadoChartSeries {

return VisualClass.parseSeries(
dataView,
Expand All @@ -107,8 +106,7 @@ export class TornadoChartBuilder extends VisualBuilderBase<VisualClass> {
index,
isGrouped,
columnGroup,
this.visual.colors,
formattingSettings);
this.visual.colors);
}

public converter(dataView: DataView, formattingSettings: TornadoChartSettingsModel): TornadoChartDataView {
Expand Down
15 changes: 6 additions & 9 deletions test/visualTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,15 +167,15 @@ describe("TornadoChart", () => {
});

it("every argument is null", () => {
callParseSeriesAndExpectExceptions(null, null, null, null, null, null);
callParseSeriesAndExpectExceptions(null, null, null, null, null);
});

it("every argument is undefined", () => {
callParseSeriesAndExpectExceptions(undefined, undefined, undefined, undefined, undefined, undefined);
callParseSeriesAndExpectExceptions(undefined, undefined, undefined, undefined, undefined);
});

it("index is negative, other arguments are null", () => {
callParseSeriesAndExpectExceptions(null, null, -5, null, null, null);
callParseSeriesAndExpectExceptions(null, null, -5, null, null);
});

it("every argument is correct", () => {
Expand All @@ -185,8 +185,7 @@ describe("TornadoChart", () => {
dataView.categorical!.values!,
index,
true,
dataView.categorical!.values!.grouped()[index],
visualBuilder.instance.formattingSettings)!;
dataView.categorical!.values!.grouped()[index])!;

expect(series.categoryAxisEnd).toBeDefined();
expect(series.name).toBeDefined();
Expand All @@ -203,8 +202,7 @@ describe("TornadoChart", () => {
dataViewValueColumns: DataViewValueColumns | null | undefined,
index: number | null | undefined,
isGrouped: boolean | null | undefined,
columnGroup: DataViewValueColumnGroup | null | undefined,
formattingSettings: TornadoChartSettingsModel | null | undefined): TornadoChartSeries | undefined {
columnGroup: DataViewValueColumnGroup | null | undefined): TornadoChartSeries | undefined {

let series: TornadoChartSeries | undefined = undefined;
expect(() => {
Expand All @@ -213,8 +211,7 @@ describe("TornadoChart", () => {
dataViewValueColumns!,
index!,
isGrouped!,
columnGroup!,
formattingSettings!);
columnGroup!);
}).not.toThrow();

return series;
Expand Down
Loading