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 config + visual props POC #26

Closed
wants to merge 12 commits into from
133 changes: 95 additions & 38 deletions example/custom-bar-chart/custom-chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Copyright: ThoughtSpot Inc. 2023
*/

import { VisualPropEditorDefinition } from '@thoughtspot/ts-chart-sdk';
import {
ChartColumn,
ChartConfig,
Expand All @@ -21,7 +22,12 @@ import {
Query,
VisualProps,
} from '@thoughtspot/ts-chart-sdk';
import {
ChartConfigEditorDefinition,
CustomChartEditorDefinitionProps,
} 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 Down Expand Up @@ -151,6 +157,11 @@ function render(ctx: CustomChartContext) {
visualPropKeyMap[2],
false,
);
const labelColor = _.get(
chartModel.visualProps,
visualPropKeyMap[1],
'blue',
);
if (!dataModel) {
return;
}
Expand All @@ -174,11 +185,8 @@ function render(ctx: CustomChartContext) {
plugins: {
// Change options for ALL labels of THIS CHART
datalabels: {
display: allowLabels ? 'auto' : false,
formatter: value => numberFormatter(value),
color: 'blue',
textStrokeColor: 'white',
textStrokeWidth: 5,
display: allowLabels,
color: labelColor,
labels: {
title: {
font: {
Expand Down Expand Up @@ -312,34 +320,67 @@ 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',
chartConfigEditorDefinition: (
configInfo: CustomChartEditorDefinitionProps,
): ChartConfigEditorDefinition[] => {
const {
chartModel,
updatedChartConfig,
updatedVisualProps,
} = configInfo;

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

const config = [
{
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++) {
config[0].columnSections.push({
key: `layers${i}`,
label: `Measures layer${i}`,
allowAttributeColumns: false,
allowMeasureColumns: true,
allowTimeSeriesColumns: false,
},
],
},
],
visualPropEditorDefinition: {
elements: [
});
}
}
return config;
},
visualPropEditorDefinition: (
visualInfo: CustomChartEditorDefinitionProps,
): VisualPropEditorDefinition => {
const {
chartModel,
updatedVisualProps,
updatedChartConfig,
} = visualInfo;
const elements = [
{
key: 'color',
type: 'radio',
Expand All @@ -352,13 +393,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 +401,30 @@ const renderChart = async (ctx: CustomChartContext): Promise<void> => {
},
],
},
],
];
if (updatedVisualProps?.length !== 0) {
if (updatedVisualProps?.accordion?.datalabels) {
elements[1].children?.push({
key: 'Color2',
type: 'radio',
defaultValue: 'blue',
values: ['blue', 'white', 'red'],
label: 'Color2',
});
}
} else {
if (chartModel?.visualProps?.accordion?.datalabels) {
elements[1].children?.push({
key: 'Color2',
type: 'radio',
defaultValue: 'blue',
values: ['blue', 'white', 'red'],
label: 'Color2',
});
}
}

return { elements };
},
});

Expand Down
113 changes: 106 additions & 7 deletions src/main/custom-chart-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,20 @@

let isInitialized = false;

export type CustomChartEditorDefinitionProps = {
chartModel: ChartModel;
updatedChartConfig?: ChartConfig[];
updatedVisualProps?: VisualProps;
};

export type ConfigEditorDefinitionCallback = (
configInfo: CustomChartEditorDefinitionProps,
) => ChartConfigEditorDefinition[];

export type VisualEditorDefinitionCallback = (
visualInfo: CustomChartEditorDefinitionProps,
) => VisualPropEditorDefinition;

export type CustomChartContextProps = {
/**
* Generate the default axis configuration for rendering the chart on first load.
Expand Down Expand Up @@ -106,7 +120,9 @@
*
* @version SDK: 0.1 | ThoughtSpot:
*/
chartConfigEditorDefinition?: ChartConfigEditorDefinition[];
chartConfigEditorDefinition:
| ConfigEditorDefinitionCallback
| ChartConfigEditorDefinition[];

/**
* Definition to help edit/customize the visual properties from chart settings editor
Expand All @@ -117,7 +133,9 @@
* @returns {@link VisualPropEditorDefinition}
* @version SDK: 0.1 | ThoughtSpot:
*/
visualPropEditorDefinition?: VisualPropEditorDefinition;
visualPropEditorDefinition:
| VisualEditorDefinitionCallback
| VisualPropEditorDefinition;
};

/**
Expand All @@ -126,7 +144,7 @@
const DEFAULT_CHART_CONTEXT_PROPS: Partial<CustomChartContextProps> = {
validateConfig: () => ({ isValid: true }),
validateVisualProps: () => ({ isValid: true }),
chartConfigEditorDefinition: undefined,
chartConfigEditorDefinition: () => undefined,
};

export class CustomChartContext {
Expand Down Expand Up @@ -241,7 +259,7 @@
* @version SDK: 0.1 | ThoughtSpot:
*/
public initialize = (): Promise<void> => {
console.log('Chart Context: initialization start');

Check warning on line 262 in src/main/custom-chart-context.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement
return this.hasInitializedPromise;
};

Expand Down Expand Up @@ -273,7 +291,7 @@
*/
public off<T extends keyof TSToChartEventsPayloadMap>(eventType: T): void {
if (_.isNil(this.eventListeners[eventType])) {
console.log('No event listener found to remove');

Check warning on line 294 in src/main/custom-chart-context.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement
this.eventListeners[eventType] = [];
return;
}
Expand Down Expand Up @@ -430,7 +448,7 @@
...eventPayload: ChartToTSEventsPayloadMap[T]
): Promise<any> {
if (!isInitialized) {
console.log(

Check warning on line 451 in src/main/custom-chart-context.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement
'Chart Context: not initialized the context, something went wrong',
);
return Promise.reject(new Error('Context not initialized'));
Expand All @@ -453,7 +471,7 @@
*/
private registerEventProcessor = () => {
if (isInitialized) {
console.error(

Check warning on line 474 in src/main/custom-chart-context.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement
'The context is already initialized. you cannot have multiple contexts',
);
throw new Error(ErrorType.MultipleContextsNotSupported);
Expand All @@ -473,7 +491,7 @@
return;
}

console.log(

Check warning on line 494 in src/main/custom-chart-context.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement
'Chart Context: message received:',
event.data.eventType,
event.data,
Expand Down Expand Up @@ -532,6 +550,38 @@
payload.visualProps,
this.chartModel,
);
if (validationResponse.isValid) {
const visualPropEditorDefinition = _.isFunction(
this.chartContextProps.visualPropEditorDefinition,
)
? this.chartContextProps.visualPropEditorDefinition(
{
chartModel: this.chartModel,
updatedChartConfig:
this.chartModel.config.chartConfig,
updatedVisualProps: payload.visualProps,
},
)
: this.chartContextProps.visualPropEditorDefinition;
const chartConfigEditorDefinition = _.isFunction(
this.chartContextProps.chartConfigEditorDefinition,
)
? this.chartContextProps.chartConfigEditorDefinition(
{
chartModel: this.chartModel,
updatedChartConfig:
this.chartModel.config.chartConfig,
updatedVisualProps: payload.visualProps,
},
)
: this.chartContextProps
.chartConfigEditorDefinition;
return {
...validationResponse,
visualPropEditorDefinition,
chartConfigEditorDefinition,
};
}
return validationResponse;
}
// this will never be true
Expand All @@ -553,6 +603,39 @@
payload.chartConfig,
this.chartModel,
);
if (validationResponse.isValid) {
const chartConfigEditorDefinition = _.isFunction(
this.chartContextProps.chartConfigEditorDefinition,
)
? this.chartContextProps.chartConfigEditorDefinition(
{
chartModel: this.chartModel,
updatedChartConfig: payload.chartConfig,
updatedVisualProps:
this.chartModel.visualProps,
},
)
: this.chartContextProps
.chartConfigEditorDefinition;

const visualPropEditorDefinition = _.isFunction(
this.chartContextProps.visualPropEditorDefinition,
)
? this.chartContextProps.visualPropEditorDefinition(
{
chartModel: this.chartModel,
updatedChartConfig: payload.chartConfig,
updatedVisualProps:
this.chartModel.visualProps,
},
)
: this.chartContextProps.visualPropEditorDefinition;
return {
...validationResponse,
visualPropEditorDefinition,
chartConfigEditorDefinition,
};
}
return validationResponse;
}
// this will never be true
Expand Down Expand Up @@ -615,7 +698,7 @@
isValid: true,
};
} catch (error: unknown) {
console.log(

Check warning on line 701 in src/main/custom-chart-context.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement
'ContextMenuCustomAction: payload recieved:',
payload,
'CustomActionCallbackStore:',
Expand Down Expand Up @@ -658,7 +741,7 @@
isValid: true,
};
} catch (error: unknown) {
console.log(

Check warning on line 744 in src/main/custom-chart-context.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement
'AxisMenuCustomAction: payload recieved:',
payload,
'CustomActionCallbackStore:',
Expand Down Expand Up @@ -776,13 +859,29 @@
this.chartModel,
);
}
const chartConfigEditorDefinition = _.isFunction(
this.chartContextProps.chartConfigEditorDefinition,
)
? this.chartContextProps.chartConfigEditorDefinition({
chartModel: this.chartModel,
updatedChartConfig: this.chartModel.config.chartConfig,
updatedVisualProps: this.chartModel.visualProps,
})
: this.chartContextProps.chartConfigEditorDefinition;
const visualPropEditorDefinition = _.isFunction(
this.chartContextProps.visualPropEditorDefinition,
)
? this.chartContextProps.visualPropEditorDefinition({
chartModel: this.chartModel,
updatedChartConfig: this.chartModel.config.chartConfig,
updatedVisualProps: this.chartModel.visualProps,
})
: this.chartContextProps.visualPropEditorDefinition;
return {
isConfigValid: isValid,
defaultChartConfig,
chartConfigEditorDefinition:
this.chartContextProps.chartConfigEditorDefinition,
visualPropEditorDefinition:
this.chartContextProps.visualPropEditorDefinition,
chartConfigEditorDefinition,
visualPropEditorDefinition,
};
};

Expand Down Expand Up @@ -810,7 +909,7 @@
};
}

console.log(

Check warning on line 912 in src/main/custom-chart-context.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement
'ChartContext: Response:',
event.data.eventType,
response,
Expand Down
4 changes: 4 additions & 0 deletions src/types/common.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
*/

import { ChartColumn } from './answer-column.types';
import { ChartConfigEditorDefinition } from './configurator.types';
import { VisualPropEditorDefinition } from './visual-prop.types';

/**
* List of Columns for a dimension in the Custom Chart Config.
Expand Down Expand Up @@ -144,6 +146,8 @@ export interface ChartModel {
export type ValidationResponse = {
isValid: boolean;
validationErrorMessage?: string[];
chartConfigEditorDefinition?: ChartConfigEditorDefinition[];
visualPropEditorDefinition?: VisualPropEditorDefinition;
};

/**
Expand Down
Loading