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

Dynamic configuration and visual props #29

Merged
merged 20 commits into from
Jul 18, 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
154 changes: 98 additions & 56 deletions example/custom-bar-chart/custom-chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
* Copyright: ThoughtSpot Inc. 2023
*/

import {
ValidationResponse,
VisualPropEditorDefinition,
} from '@thoughtspot/ts-chart-sdk';
import {
ChartColumn,
ChartConfig,
Expand All @@ -21,7 +25,9 @@ import {
Query,
VisualProps,
} from '@thoughtspot/ts-chart-sdk';
import { ChartConfigEditorDefinition } from '@thoughtspot/ts-chart-sdk/src';
import Chart from 'chart.js/auto';
import { toDimension } from 'chart.js/dist/helpers/helpers.core';
import ChartDataLabels from 'chartjs-plugin-datalabels';
import _ from 'lodash';

Expand All @@ -37,22 +43,9 @@ const visualPropKeyMap = {
2: 'accordion.datalabels',
};

const numberFormatter = value => {
if (value > 1000000000) {
return (value / 1000000000).toFixed(2) + 'B';
}
if (value > 1000000) {
return (value / 1000000).toFixed(2) + 'M';
}
if (value > 1000) {
return (value / 1000).toFixed(2) + 'K';
}
return value;
};

function getDataForColumn(column: ChartColumn, dataArr: DataPointsArray) {
const idx = _.findIndex(dataArr.columns, colId => column.id === colId);
return _.map(dataArr.dataValue, row => row[idx]);
const idx = _.findIndex(dataArr.columns, (colId) => column.id === colId);
return _.map(dataArr.dataValue, (row) => row[idx]);
}

function getColumnDataModel(
Expand Down Expand Up @@ -151,6 +144,11 @@ function render(ctx: CustomChartContext) {
visualPropKeyMap[2],
false,
);
const labelColor = _.get(
chartModel.visualProps,
visualPropKeyMap[1],
availableColor[0],
);
if (!dataModel) {
return;
}
Expand All @@ -174,11 +172,8 @@ function render(ctx: CustomChartContext) {
plugins: {
// Change options for ALL labels of THIS CHART
datalabels: {
display: allowLabels ? 'auto' : false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we seem to have removed a lot of properties... is this working as expected?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is working

formatter: value => numberFormatter(value),
color: 'blue',
textStrokeColor: 'white',
textStrokeWidth: 5,
Comment on lines -178 to -181
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how are these properties working today?

display: allowLabels,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

display takes true now?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://chartjs-plugin-datalabels.netlify.app/guide/positioning.html#rotation

will depend on implementation, true is also a valid value as mentioned above in the documentation

color: labelColor,
labels: {
title: {
font: {
Expand Down Expand Up @@ -268,12 +263,12 @@ const renderChart = async (ctx: CustomChartContext): Promise<void> => {

const measureColumns = _.filter(
cols,
col => col.type === ColumnType.MEASURE,
(col) => col.type === ColumnType.MEASURE,
);

const attributeColumns = _.filter(
cols,
col => col.type === ColumnType.ATTRIBUTE,
(col) => col.type === ColumnType.ATTRIBUTE,
);

const axisConfig: ChartConfig = {
Expand Down Expand Up @@ -311,35 +306,77 @@ const renderChart = async (ctx: CustomChartContext): Promise<void> => {
);
return queries;
},
renderChart: ctx => renderChart(ctx),
chartConfigEditorDefinition: [
{
key: 'column',
label: 'Custom Column',
descriptionText:
'X Axis can only have attributes, Y Axis can only have measures, Color can only have attributes. ' +
'Should have just 1 column in Y axis with colors columns.',
columnSections: [
{
key: 'x',
label: 'Custom X Axis',
allowAttributeColumns: true,
allowMeasureColumns: false,
allowTimeSeriesColumns: true,
maxColumnCount: 1,
},
{
key: 'y',
label: 'Custom Y Axis',
renderChart: (ctx) => renderChart(ctx),
validateConfig: (
updatedConfig: any[],
chartModel: any,
): ValidationResponse => {
if (updatedConfig.length <= 0) {
return {
isValid: false,
validationErrorMessage: ['Invalid config. no config found'],
};
} else {
return {
isValid: true,
};
}
},
chartConfigEditorDefinition: (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for backward compatibility verification should we keep this as it is?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have checked the backwards compatibilty it is working for both object and function we can keep it like this for a sample chart.

currentChartConfig: ChartModel,
ctx: CustomChartContext,
): ChartConfigEditorDefinition[] => {
const { config, visualProps } = currentChartConfig;

const yColumns = config?.chartConfig?.[0]?.dimensions.find(
(dimension) => dimension.key === 'y' && dimension.columns,
);

const configDefinition = [
{
key: 'column',
label: 'Custom Column',
descriptionText:
'X Axis can only have attributes, Y Axis can only have measures, Color can only have attributes. ' +
'Should have just 1 column in Y axis with colors columns.',
columnSections: [
{
key: 'x',
label: 'Custom X Axis',
allowAttributeColumns: true,
allowMeasureColumns: false,
allowTimeSeriesColumns: true,
maxColumnCount: 1,
},
{
key: 'y',
label: 'Custom Y Axis',
allowAttributeColumns: false,
allowMeasureColumns: true,
allowTimeSeriesColumns: false,
},
],
},
];
if (yColumns?.columns.length) {
for (let i = 0; i < yColumns.columns.length; i++) {
configDefinition[0].columnSections.push({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where are we using this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This I have added for an example purpose, when we are adding measures to y-axis, a new layer will be created with the same.

key: `layers${i}`,
label: `Measures layer${i}`,
allowAttributeColumns: false,
allowMeasureColumns: true,
allowTimeSeriesColumns: false,
},
],
},
],
visualPropEditorDefinition: {
elements: [
});
}
}
return configDefinition;
},
visualPropEditorDefinition: (
currentVisualProps: ChartModel,
ctx: CustomChartContext,
): VisualPropEditorDefinition => {
const { visualProps } = currentVisualProps;
const elements = [
{
key: 'color',
type: 'radio',
Expand All @@ -352,13 +389,6 @@ const renderChart = async (ctx: CustomChartContext): Promise<void> => {
key: 'accordion',
label: 'Accordion',
children: [
{
key: 'Color2',
type: 'radio',
defaultValue: 'blue',
values: ['blue', 'white', 'red'],
label: 'Color2',
},
{
key: 'datalabels',
type: 'toggle',
Expand All @@ -367,7 +397,19 @@ const renderChart = async (ctx: CustomChartContext): Promise<void> => {
},
],
},
],
];
if (visualProps?.length !== 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not an array but an object right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

element is an array, visualPropEditordefinition is an Object

if (visualProps?.accordion?.datalabels) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whats the value in this change? I see no difference?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

elements[1].children?.push({
key: 'Color2',
type: 'radio',
defaultValue: 'blue',
values: ['blue', 'white', 'red'],
label: 'Color2',
});
}
}
return { elements };
},
});

Expand Down
Loading
Loading