Skip to content

Commit

Permalink
Merge pull request #45 from jku-vds-lab/jakob/defect-colors
Browse files Browse the repository at this point in the history
Jakob/defect colors
  • Loading branch information
jzethofer authored Mar 2, 2022
2 parents acb31fb + a6c2c0c commit ac2e82b
Show file tree
Hide file tree
Showing 7 changed files with 294 additions and 39 deletions.
51 changes: 49 additions & 2 deletions capabilities.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@
"integer": true
}
]
},
{
"displayName": "Legend",
"name": "legend",
"kind": "Grouping"
}
],
"dataViewMappings": [
Expand All @@ -82,6 +87,9 @@
"slabY": {
"max": 1
},
"legend": {
"max": 1
},
"category": {
"max": 16
},
Expand Down Expand Up @@ -117,8 +125,17 @@
"for": {
"in": "tooltip"
}
},
{
"for": {
"in": "legend"
}
}
]
], "dataReductionAlgorithm": {
"top": {
"count": 2000
}
}
}
}
}
Expand Down Expand Up @@ -202,6 +219,28 @@
}
}
},
"legendSettings": {
"displayName": "Legend Settings",
"properties": {
"legendTitle": {
"displayName": "Legend Title",
"type": {
"text": true
}
},
"legendColor": {
"displayName": "Legend Color",
"description": "The color of this legend type.",
"type": {
"fill": {
"solid": {
"color": true
}
}
}
}
}
},
"plotSettings": {
"displayName": "Plot Settings",
"properties": {
Expand Down Expand Up @@ -229,6 +268,12 @@
}
}
}
},
"useLegendColor": {
"displayName": "Use Legend Color",
"type": {
"bool": true
}
}
}
},
Expand Down Expand Up @@ -310,7 +355,9 @@
"properties": {
"show": {
"displayName": "Enable Zooming",
"type": {"bool": true}
"type": {
"bool": true
}
},
"maximum": {
"displayName": "Maximum Zoom Factor",
Expand Down
8 changes: 7 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export enum Settings {
axisSettings = "axisSettings",
colorSelector = "colorSelector",
colorSettings = "colorSettings",
legendSettings = "legendSettings",
overlayPlotSettings = "overlayPlotSettings",
plotTitleSettings = "plotTitleSettings",
tooltipTitleSettings = "tooltipTitleSettings",
Expand All @@ -13,10 +14,15 @@ export enum YRangeSettingsNames{
min = "min",
max = "max"
}
export enum LegendSettingsNames{
legendTitle = "legendTitle",
legendColor = "legendColor"
}

export enum PlotSettingsNames {
plotType = "plotType",
fill = "fill"
fill = "fill",
useLegendColor = "useLegendColor"
}
export enum TooltipTitleSettingsNames {
title = "title"
Expand Down
11 changes: 11 additions & 0 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ export class PlotSizeError extends ParseAndTransformError {

}
}
export class PlotLegendError extends ParseAndTransformError {
/**
*
*/
constructor(plotName:string) {
const name = "Plot Legend Error";
const message = `There is legend no data but legend colors are set to be used by ${plotName}. Please add legend data in the field pane.`;
super(message, name);

}
}

export class GetAxisInformationError extends ParseAndTransformError {
/**
Expand Down
3 changes: 2 additions & 1 deletion src/marginSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { Margins } from './plotInterface';

export class MarginSettings {
static readonly svgTopPadding = 0;
static readonly svgBottomPadding = 10
static readonly svgBottomPadding = 0;
static readonly plotTitleHeight = 18;
static readonly legendHeight = 20;
static readonly dotMargin = 4;
static readonly margins: Margins = {
top: 10,
Expand Down
118 changes: 96 additions & 22 deletions src/parseAndTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import IVisualHost = powerbi.extensibility.visual.IVisualHost;
import VisualUpdateOptions = powerbi.extensibility.visual.VisualUpdateOptions;
import ISandboxExtendedColorPalette = powerbi.extensibility.ISandboxExtendedColorPalette;
import { getValue, getColumnnColorByIndex, getAxisTextFillColor, getPlotFillColor, getColorSettings } from './objectEnumerationUtility';
import { ViewModel, DataPoint, FormatSettings, PlotSettings, PlotModel, TooltipDataPoint, XAxisData, YAxisData, PlotType, SlabRectangle, SlabType, GeneralPlotSettings, Margins, AxisInformation, AxisInformationInterface, TooltipModel, ZoomingSettings } from './plotInterface';
import { ViewModel, DataPoint, FormatSettings, PlotSettings, PlotModel, TooltipDataPoint, XAxisData, YAxisData, PlotType, SlabRectangle, SlabType, GeneralPlotSettings, Margins, AxisInformation, AxisInformationInterface, TooltipModel, ZoomingSettings, LegendData, Legend, LegendValue } from './plotInterface';
import { Color } from 'd3';
import { AxisSettingsNames, PlotSettingsNames, Settings, ColorSettingsNames, OverlayPlotSettingsNames, PlotTitleSettingsNames, TooltipTitleSettingsNames, YRangeSettingsNames, ZoomingSettingsNames } from './constants';
import { MarginSettings } from './marginSettings'
import { ok, err, Result } from 'neverthrow'
import { AxisError, AxisNullValuesError, GetAxisInformationError, NoAxisError, NoValuesError, ParseAndTransformError, PlotSizeError, SVGSizeError } from './errors'
import { AxisError, AxisNullValuesError, GetAxisInformationError, NoAxisError, NoValuesError, ParseAndTransformError, PlotLegendError, PlotSizeError, SVGSizeError } from './errors'

// TODO #n: Allow user to change bars colors

Expand Down Expand Up @@ -65,15 +65,15 @@ export function visualTransform(options: VisualUpdateOptions, host: IVisualHost)
let xData = new Array<XAxisData>(xCount);
let yData = new Array<YAxisData>(yCount);
let tooltipData = new Array<YAxisData>(tooltipCount);

let legendData: LegendData = null;


let xDataPoints: number[] = [];
let yDataPoints: number[] = [];
let dataPoints: DataPoint[] = [];
let slabWidth: number[] = [];
let slabLength: number[] = [];

let legend: Legend = null;

//aquire all categorical values
if (categorical.categories !== undefined) {
Expand Down Expand Up @@ -109,6 +109,13 @@ export function visualTransform(options: VisualUpdateOptions, host: IVisualHost)
};
tooltipData[tooltipId] = data;
}
else if (roles.legend) {
legendData = {
name: category.source.displayName,
values: <string[]>category.values,
columnId: category.source.index
};
}
}
}
//aquire all measure values
Expand Down Expand Up @@ -146,14 +153,63 @@ export function visualTransform(options: VisualUpdateOptions, host: IVisualHost)
};
tooltipData[tooltipId] = data;
}
else if (roles.legend) {
legendData = {
name: value.source.displayName,
values: <string[]>value.values,
columnId: value.source.index
};
}
}
}



const possibleNullValues: XAxisData[] = xData.filter(x => x.values.filter(y => y === null || y === undefined).length > 0)
if (possibleNullValues.length > 0) {
return err(new AxisNullValuesError(possibleNullValues[0].name));
}

const legendColors = {
OZE: "#e41a1c",
GZE: "#377eb8",
RAS: "#4daf4a"
}

if (legendData != null) {
let legendSet = new Set(legendData.values);

if (legendSet.has(null)) {
legendSet.delete(null);
}
let legendValues = Array.from(legendSet);
legend = {
legendDataPoints: [],
legendValues: []
}
for (let i = 0; i < legendValues.length; i++) {
const val = legendValues[i]
legend.legendValues.push({
color: legendColors[val],
selected: false,
value: val,
identity: host.createSelectionIdBuilder().createSelectionId()
});
}
let legendXValues = xData[0].values;
for (let i = 0; i < Math.min(legendData.values.length, legendXValues.length); i++) {
legend.legendDataPoints.push({
xValue: legendXValues[i],
yValue: legendData.values[i]
});

}


}

debugger;

let plotTitles: string[] = [];
for (let plotNr = 0; plotNr < yCount; plotNr++) {
let yAxis: YAxisData = yData[plotNr]
Expand All @@ -163,7 +219,7 @@ export function visualTransform(options: VisualUpdateOptions, host: IVisualHost)
}
let plotTitlesCount = plotTitles.filter(x => x.length > 0).length;
let viewModel: ViewModel;
let viewModelResult = createViewModel(options, yCount, objects, colorPalette, plotTitlesCount)
let viewModelResult = createViewModel(options, yCount, objects, colorPalette, plotTitlesCount, legend)
.map(vm => viewModel = vm)
if (viewModelResult.isErr()) {
return viewModelResult.mapErr(err => { return err; });
Expand All @@ -182,25 +238,41 @@ export function visualTransform(options: VisualUpdateOptions, host: IVisualHost)
yDataPoints = yAxis.values;
const maxLengthAttributes = Math.max(xDataPoints.length, yDataPoints.length);
dataPoints = [];

const yColumnId = yData[plotNr].columnId;
const yColumnObjects = metadataColumns[yColumnId].objects;
const plotSettings: PlotSettings = {
plotSettings: {
fill: getPlotFillColor(yColumnObjects, colorPalette, '#000000'),
plotType: PlotType[getValue<string>(yColumnObjects, Settings.plotSettings, PlotSettingsNames.plotType, PlotType.LinePlot)],
useLegendColor: getValue<boolean>(yColumnObjects, Settings.plotSettings, PlotSettingsNames.useLegendColor, false)
}
}
//create datapoints
for (let pointNr = 0; pointNr < maxLengthAttributes; pointNr++) {
const color: string = '#0f0f0f'; //getColumnnColorByIndex(xDataPoints, i, colorPalette); // TODO Add colors only if required

const selectionId: ISelectionId = host.createSelectionIdBuilder().withMeasure(xDataPoints[pointNr].toString()).createSelectionId();
let color = plotSettings.plotSettings.fill;
const xVal = xDataPoints[pointNr];
if (plotSettings.plotSettings.useLegendColor) {
if (legend != null) {
const legendVal = legend.legendDataPoints.find(x => x.xValue == xVal).yValue;
color = legendVal == null ? color : legend.legendValues.find(x => x.value == legendVal).color;
}else{
return err(new PlotLegendError(yAxis.name));
}
}

//const color = legend.legendValues.fin legend.legendDataPoints[pointNr].yValue
let dataPoint: DataPoint = {
xValue: xDataPoints[pointNr],
xValue: xVal,
yValue: yDataPoints[pointNr],
identity: selectionId,
selected: false,
color: color,
color: color
};
dataPoints.push(dataPoint);
}
//get index of y-column in metadata
let yColumnId = yData[plotNr].columnId;
let yColumnObjects = metadataColumns[yColumnId].objects;


dataPoints = dataPoints.sort((a: DataPoint, b: DataPoint) => {
return <number>a.xValue - <number>b.xValue;
Expand Down Expand Up @@ -228,18 +300,14 @@ export function visualTransform(options: VisualUpdateOptions, host: IVisualHost)
let plotTitle = plotTitles[plotNr]
plotTop = plotTitle.length > 0 ? plotTop + MarginSettings.plotTitleHeight : plotTop;


let plotModel: PlotModel = {
plotId: plotNr,
formatSettings: formatSettings,
xName: xAxis.name,
yName: yAxis.name,
plotTop: plotTop,
plotSettings: {
plotSettings: {
fill: getPlotFillColor(yColumnObjects, colorPalette, '#000000'),
plotType: PlotType[getValue<string>(yColumnObjects, Settings.plotSettings, PlotSettingsNames.plotType, PlotType.LinePlot)]
},
},
plotSettings: plotSettings,
plotTitleSettings: {
title: plotTitle//getValue<string>(yColumnObjects, Settings.plotTitleSettings, PlotTitleSettingsNames.title, yAxis.name)
},
Expand All @@ -261,6 +329,7 @@ export function visualTransform(options: VisualUpdateOptions, host: IVisualHost)
viewModel.plotModels[plotNr] = plotModel;
plotTop += viewModel.generalPlotSettings.plotHeight + MarginSettings.margins.top + MarginSettings.margins.bottom;
}
viewModel.generalPlotSettings.legendYPostion = plotTop;

return ok(viewModel);

Expand Down Expand Up @@ -324,30 +393,34 @@ function createSlabInformation(slabLength: number[], slabWidth: number[], viewMo
}
}

function createViewModel(options: VisualUpdateOptions, yCount: number, objects: powerbi.DataViewObjects, colorPalette: ISandboxExtendedColorPalette, plotTitlesCount: number): Result<ViewModel, ParseAndTransformError> {
function createViewModel(options: VisualUpdateOptions, yCount: number, objects: powerbi.DataViewObjects, colorPalette: ISandboxExtendedColorPalette, plotTitlesCount: number, legend: Legend): Result<ViewModel, ParseAndTransformError> {
const margins = MarginSettings
const svgHeight: number = options.viewport.height;
const svgWidth: number = options.viewport.width;
const legendHeight = legend ? margins.legendHeight : 0;
if (svgHeight === undefined || svgWidth === undefined || !svgHeight || !svgWidth) {
return err(new SVGSizeError());
}
const plotHeightSpace: number = (svgHeight - margins.svgTopPadding - margins.svgBottomPadding - margins.plotTitleHeight * plotTitlesCount) / yCount;
const plotHeightSpace: number = (svgHeight - margins.svgTopPadding - margins.svgBottomPadding - legendHeight - margins.plotTitleHeight * plotTitlesCount) / yCount;
if (plotHeightSpace < margins.miniumumPlotHeight) {
return err(new PlotSizeError("vertical"));
}
const plotWidth: number = svgWidth - margins.margins.left - margins.margins.right;
if (plotWidth < margins.miniumumPlotWidth) {
return err(new PlotSizeError("horizontal"));
}

let generalPlotSettings: GeneralPlotSettings = {
plotTitleHeight: margins.plotTitleHeight,
dotMargin: margins.dotMargin,
plotHeight: plotHeightSpace - margins.margins.top - margins.margins.bottom,
plotWidth: plotWidth,
legendHeight: legendHeight,
xScalePadding: 0.1,
solidOpacity: 1,
transparentOpacity: 1,
margins: margins.margins
margins: margins.margins,
legendYPostion: 0
};

const zoomingSettings: ZoomingSettings = {
Expand All @@ -369,7 +442,8 @@ function createViewModel(options: VisualUpdateOptions, yCount: number, objects:
svgHeight: svgHeight,
svgTopPadding: margins.svgTopPadding,
svgWidth: svgWidth,
zoomingSettings: zoomingSettings
zoomingSettings: zoomingSettings,
legend: legend
};
return ok(viewModel);
}
Expand Down
Loading

0 comments on commit ac2e82b

Please sign in to comment.