Split bar graph into two distinct horizontal and vertical bars (#15061)

### Summary

Split BAR into VERTICAL_BAR and HORIZONTAL_BAR as separate chart types.

### The Problem

Initially wanted a simple vertical/horizontal toggle for bar charts, but
ran into a GraphQL union type
constraint: union types can't have the same field name with different
nullability.

- Vertical bars need groupByFieldMetadataIdX as required (categories on
X)
- Horizontal bars need groupByFieldMetadataIdY as required (categories
on Y)
  - GraphQL schema generation fails with this setup

### The Solution

Use semantic primaryAxis and secondaryAxis naming that's
orientation-agnostic:

- primaryAxisGroupByFieldMetadataId = main grouping field (e.g.,
"Company Name")
- secondaryAxisGroupByFieldMetadataId = optional secondary grouping
(e.g., "Stage")

These fields have consistent meaning regardless of orientation. The
visual mapping happens at the UI layer:
  - Vertical bars: primary data renders on X-axis, secondary on Y-axis
  - Horizontal bars: primary data renders on Y-axis, secondary on X-axis

Both chart types share the same DTO structure with consistent
nullability.

### What Changed

  - Split GraphType.BAR → VERTICAL_BAR | HORIZONTAL_BAR
- Renamed fields: primaryAxisGroupByFieldMetadataId,
secondaryAxisGroupByFieldMetadataId (+ subfield
  variants)
- useChartSettingsValues(): Maps semantic fields to setting values (no
swapping)
- getBarChartSettings(): Dynamically arranges settings panel based on
orientation
- transformGroupByDataToBarChartData(): Maps semantic fields to Nivo's
layout prop
  
  video QA
  

https://github.com/user-attachments/assets/479061b5-712e-4ca6-9858-95273d1f16c1
This commit is contained in:
nitin
2025-10-15 15:08:48 +05:30
committed by GitHub
parent d21be90c5d
commit 436084f8f4
48 changed files with 1453 additions and 412 deletions
@@ -0,0 +1,592 @@
import { renderHook } from '@testing-library/react';
import { RecoilRoot } from 'recoil';
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import {
AxisNameDisplay,
type BarChartConfiguration,
BarChartGroupMode,
ExtendedAggregateOperations,
FieldMetadataType,
GraphOrderBy,
GraphType,
} from '~/generated-metadata/graphql';
import { useChartSettingsValues } from '../useChartSettingsValues';
const mockObjectMetadataItem: ObjectMetadataItem = {
id: 'obj-1',
nameSingular: 'company',
namePlural: 'companies',
labelSingular: 'Company',
labelPlural: 'Companies',
fields: [
{
id: 'field-company-name',
name: 'name',
label: 'Company Name',
type: FieldMetadataType.TEXT,
},
{
id: 'field-amount',
name: 'amount',
label: 'Amount',
type: FieldMetadataType.NUMBER,
},
{
id: 'field-stage',
name: 'stage',
label: 'Stage',
type: FieldMetadataType.TEXT,
},
{
id: 'field-full-name',
name: 'fullName',
label: 'Full Name',
type: FieldMetadataType.FULL_NAME,
subFields: [
{
id: 'field-full-name-first',
name: 'firstName',
label: 'First Name',
type: FieldMetadataType.TEXT,
},
],
},
],
} as ObjectMetadataItem;
const buildBarChartConfiguration = (
overrides: Partial<BarChartConfiguration>,
): BarChartConfiguration =>
({
__typename: 'BarChartConfiguration',
aggregateFieldMetadataId: 'field-amount',
aggregateOperation: ExtendedAggregateOperations.SUM,
graphType: GraphType.VERTICAL_BAR,
primaryAxisGroupByFieldMetadataId: 'field-company-name',
primaryAxisGroupBySubFieldName: null,
secondaryAxisGroupByFieldMetadataId: null,
secondaryAxisGroupBySubFieldName: null,
primaryAxisOrderBy: GraphOrderBy.FIELD_ASC,
secondaryAxisOrderBy: null,
axisNameDisplay: AxisNameDisplay.BOTH,
displayDataLabel: false,
groupMode: 'GROUPED',
...overrides,
}) as BarChartConfiguration;
const renderUseChartSettingsValues = (configuration: ChartConfiguration) => {
return renderHook(
() =>
useChartSettingsValues({
objectMetadataId: mockObjectMetadataItem.id,
configuration,
}),
{
wrapper: ({ children }) => (
<RecoilRoot
initializeState={({ set }) => {
set(objectMetadataItemsState, [mockObjectMetadataItem]);
}}
>
{children}
</RecoilRoot>
),
},
);
};
describe('useChartSettingsValues', () => {
describe('Vertical bar chart (1D - single grouping)', () => {
const verticalBarConfig = buildBarChartConfiguration({
graphType: GraphType.VERTICAL_BAR,
primaryAxisGroupByFieldMetadataId: 'field-company-name',
secondaryAxisGroupByFieldMetadataId: null,
});
it('should return primary field label for DATA_ON_DISPLAY_X', () => {
const { result } = renderUseChartSettingsValues(verticalBarConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X,
);
expect(value).toBe('Company Name');
});
it('should return aggregate field with operation for DATA_ON_DISPLAY_Y', () => {
const { result } = renderUseChartSettingsValues(verticalBarConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_Y,
);
expect(value).toBe('Amount (Sum)');
});
it('should return object label plural for SOURCE', () => {
const { result } = renderUseChartSettingsValues(verticalBarConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.SOURCE,
);
expect(value).toBe('Companies');
});
it('should return sort label for SORT_BY_X', () => {
const { result } = renderUseChartSettingsValues(verticalBarConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.SORT_BY_X,
);
expect(value).toBeDefined();
expect(typeof value).toBe('string');
});
it('should return displayDataLabel value for DATA_LABELS', () => {
const { result } = renderUseChartSettingsValues(verticalBarConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.DATA_LABELS,
);
expect(value).toBe(false);
});
it('should return axis name display option for AXIS_NAME', () => {
const { result } = renderUseChartSettingsValues(verticalBarConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.AXIS_NAME,
);
expect(value).toBeDefined();
expect(typeof value).toBe('string');
});
});
describe('Horizontal bar chart (1D - single grouping)', () => {
const horizontalBarConfig = buildBarChartConfiguration({
graphType: GraphType.HORIZONTAL_BAR,
primaryAxisGroupByFieldMetadataId: 'field-company-name',
secondaryAxisGroupByFieldMetadataId: null,
});
it('should return SAME primary field label for DATA_ON_DISPLAY_X (no swapping)', () => {
const { result } = renderUseChartSettingsValues(horizontalBarConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X,
);
// Critical test: horizontal should return the SAME value as vertical
expect(value).toBe('Company Name');
});
it('should return SAME aggregate field for DATA_ON_DISPLAY_Y (no swapping)', () => {
const { result } = renderUseChartSettingsValues(horizontalBarConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_Y,
);
// Critical test: horizontal should return the SAME value as vertical
expect(value).toBe('Amount (Sum)');
});
it('should return SAME sort label for SORT_BY_X (no swapping)', () => {
const { result } = renderUseChartSettingsValues(horizontalBarConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.SORT_BY_X,
);
expect(value).toBeDefined();
expect(typeof value).toBe('string');
});
});
describe('Vertical bar chart (2D - with secondary grouping)', () => {
const verticalBar2DConfig = buildBarChartConfiguration({
graphType: GraphType.VERTICAL_BAR,
primaryAxisGroupByFieldMetadataId: 'field-company-name',
secondaryAxisGroupByFieldMetadataId: 'field-stage',
secondaryAxisOrderBy: GraphOrderBy.FIELD_DESC,
});
it('should return primary field label for DATA_ON_DISPLAY_X', () => {
const { result } = renderUseChartSettingsValues(verticalBar2DConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X,
);
expect(value).toBe('Company Name');
});
it('should return secondary field label for GROUP_BY', () => {
const { result } = renderUseChartSettingsValues(verticalBar2DConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.GROUP_BY,
);
expect(value).toBe('Stage');
});
it('should return secondary sort label for SORT_BY_GROUP_BY_FIELD', () => {
const { result } = renderUseChartSettingsValues(verticalBar2DConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.SORT_BY_GROUP_BY_FIELD,
);
expect(value).toBeDefined();
expect(typeof value).toBe('string');
});
});
describe('Horizontal bar chart (2D - with secondary grouping)', () => {
const horizontalBar2DConfig = buildBarChartConfiguration({
graphType: GraphType.HORIZONTAL_BAR,
primaryAxisGroupByFieldMetadataId: 'field-company-name',
secondaryAxisGroupByFieldMetadataId: 'field-stage',
secondaryAxisOrderBy: GraphOrderBy.FIELD_DESC,
});
it('should return SAME primary field for DATA_ON_DISPLAY_X (no swapping)', () => {
const { result } = renderUseChartSettingsValues(horizontalBar2DConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X,
);
expect(value).toBe('Company Name');
});
it('should return SAME secondary field for GROUP_BY (no swapping)', () => {
const { result } = renderUseChartSettingsValues(horizontalBar2DConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.GROUP_BY,
);
expect(value).toBe('Stage');
});
});
describe('Composite field with subfield', () => {
const configWithSubField = buildBarChartConfiguration({
graphType: GraphType.VERTICAL_BAR,
primaryAxisGroupByFieldMetadataId: 'field-full-name',
primaryAxisGroupBySubFieldName: 'firstName',
});
it('should return field label with subfield label for DATA_ON_DISPLAY_X', () => {
const { result } = renderUseChartSettingsValues(configWithSubField);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X,
);
expect(value).toContain('Full Name');
expect(typeof value).toBe('string');
});
});
describe('Stacked bars setting', () => {
it('should return false when groupMode is GROUPED', () => {
const config = buildBarChartConfiguration({
groupMode: BarChartGroupMode.GROUPED,
});
const { result } = renderUseChartSettingsValues(config);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.STACKED_BARS,
);
expect(value).toBe(false);
});
it('should return true when groupMode is STACKED', () => {
const config = buildBarChartConfiguration({
groupMode: BarChartGroupMode.STACKED,
});
const { result } = renderUseChartSettingsValues(config);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.STACKED_BARS,
);
expect(value).toBe(true);
});
});
describe('Colors setting', () => {
it('should return undefined when no color is set', () => {
const config = buildBarChartConfiguration({});
const { result } = renderUseChartSettingsValues(config);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.COLORS,
);
expect(value).toBeUndefined();
});
it('should return capitalized color when color is set', () => {
const config = buildBarChartConfiguration({
color: 'blue',
} as Partial<BarChartConfiguration>);
const { result } = renderUseChartSettingsValues(config);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.COLORS,
);
expect(value).toBe('Blue');
});
});
describe('No configuration', () => {
it('should return undefined function when configuration is undefined', () => {
const { result } = renderUseChartSettingsValues(undefined as any);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.SOURCE,
);
expect(value).toBeUndefined();
});
});
describe('Edge cases - Missing fields', () => {
it('should handle missing primaryAxisGroupByFieldMetadataId gracefully', () => {
const config = buildBarChartConfiguration({
primaryAxisGroupByFieldMetadataId: 'non-existent-field-id',
});
const { result } = renderUseChartSettingsValues(config);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X,
);
expect(value).toBeUndefined();
});
it('should handle missing aggregateFieldMetadataId gracefully', () => {
const config = buildBarChartConfiguration({
aggregateFieldMetadataId: 'non-existent-aggregate-field',
});
const { result } = renderUseChartSettingsValues(config);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_Y,
);
expect(value).toBe('');
});
it('should handle missing secondaryAxisGroupByFieldMetadataId gracefully', () => {
const config = buildBarChartConfiguration({
secondaryAxisGroupByFieldMetadataId: 'non-existent-secondary-field',
});
const { result } = renderUseChartSettingsValues(config);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.GROUP_BY,
);
expect(value).toBeUndefined();
});
it('should handle missing objectMetadataItem gracefully', () => {
const config = buildBarChartConfiguration({});
const { result } = renderHook(
() =>
useChartSettingsValues({
objectMetadataId: 'non-existent-object-id',
configuration: config,
}),
{
wrapper: ({ children }) => (
<RecoilRoot
initializeState={({ set }) => {
set(objectMetadataItemsState, [mockObjectMetadataItem]);
}}
>
{children}
</RecoilRoot>
),
},
);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.SOURCE,
);
expect(value).toBeUndefined();
});
});
describe('Edge cases - Null/undefined orderBy', () => {
it('should handle null primaryAxisOrderBy gracefully', () => {
const config = buildBarChartConfiguration({
primaryAxisOrderBy: null,
});
const { result } = renderUseChartSettingsValues(config);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.SORT_BY_X,
);
expect(value).toBeUndefined();
});
it('should handle null secondaryAxisOrderBy gracefully', () => {
const config = buildBarChartConfiguration({
secondaryAxisGroupByFieldMetadataId: 'field-stage',
secondaryAxisOrderBy: null,
});
const { result } = renderUseChartSettingsValues(config);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.SORT_BY_GROUP_BY_FIELD,
);
expect(value).toBeUndefined();
});
});
describe('Edge cases - Missing axisNameDisplay', () => {
it('should handle undefined axisNameDisplay gracefully', () => {
const config = buildBarChartConfiguration({
axisNameDisplay: undefined as any,
});
const { result } = renderUseChartSettingsValues(config);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.AXIS_NAME,
);
expect(value).toBeUndefined();
});
});
describe('Edge cases - Composite field with missing subfield', () => {
it('should handle composite field without subfield gracefully', () => {
const config = buildBarChartConfiguration({
primaryAxisGroupByFieldMetadataId: 'field-full-name',
primaryAxisGroupBySubFieldName: null,
});
const { result } = renderUseChartSettingsValues(config);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X,
);
expect(value).toBe('Full Name');
});
it('should handle invalid subfield name gracefully', () => {
const config = buildBarChartConfiguration({
primaryAxisGroupByFieldMetadataId: 'field-full-name',
primaryAxisGroupBySubFieldName: 'invalidSubField' as any,
});
const { result } = renderUseChartSettingsValues(config);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X,
);
expect(value).toBeDefined();
expect(typeof value).toBe('string');
});
});
describe('Critical: Proves no swapping occurs', () => {
it('horizontal bar with NULL secondary should still return primary for DATA_ON_DISPLAY_X', () => {
const horizontalConfig = buildBarChartConfiguration({
graphType: GraphType.HORIZONTAL_BAR,
primaryAxisGroupByFieldMetadataId: 'field-company-name',
secondaryAxisGroupByFieldMetadataId: null,
});
const { result } = renderUseChartSettingsValues(horizontalConfig);
const value = result.current.getChartSettingsValues(
CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X,
);
expect(value).toBe('Company Name');
expect(value).not.toBeUndefined();
});
it('should return identical values for all settings regardless of orientation', () => {
const baseConfig = {
primaryAxisGroupByFieldMetadataId: 'field-company-name',
secondaryAxisGroupByFieldMetadataId: 'field-stage',
aggregateFieldMetadataId: 'field-amount',
aggregateOperation: ExtendedAggregateOperations.SUM,
primaryAxisOrderBy: GraphOrderBy.FIELD_ASC,
secondaryAxisOrderBy: GraphOrderBy.FIELD_DESC,
axisNameDisplay: AxisNameDisplay.BOTH,
displayDataLabel: true,
};
const verticalConfig = buildBarChartConfiguration({
...baseConfig,
graphType: GraphType.VERTICAL_BAR,
});
const horizontalConfig = buildBarChartConfiguration({
...baseConfig,
graphType: GraphType.HORIZONTAL_BAR,
});
const { result: verticalResult } =
renderUseChartSettingsValues(verticalConfig);
const { result: horizontalResult } =
renderUseChartSettingsValues(horizontalConfig);
// Test all setting IDs return IDENTICAL values
const settingIds = [
CHART_CONFIGURATION_SETTING_IDS.SOURCE,
CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X,
CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_Y,
CHART_CONFIGURATION_SETTING_IDS.GROUP_BY,
CHART_CONFIGURATION_SETTING_IDS.SORT_BY_X,
CHART_CONFIGURATION_SETTING_IDS.SORT_BY_GROUP_BY_FIELD,
CHART_CONFIGURATION_SETTING_IDS.AXIS_NAME,
CHART_CONFIGURATION_SETTING_IDS.DATA_LABELS,
];
settingIds.forEach((settingId) => {
const verticalValue =
verticalResult.current.getChartSettingsValues(settingId);
const horizontalValue =
horizontalResult.current.getChartSettingsValues(settingId);
expect(verticalValue).toEqual(horizontalValue);
});
});
});
});
@@ -9,6 +9,7 @@ import { getAggregateOperationLabel } from '@/object-record/record-board/record-
import { useRecoilValue } from 'recoil';
import { type CompositeFieldSubFieldName } from 'twenty-shared/types';
import { capitalize, isDefined } from 'twenty-shared/utils';
import { type GraphOrderBy } from '~/generated-metadata/graphql';
export const useChartSettingsValues = ({
objectMetadataId,
@@ -37,20 +38,43 @@ export const useChartSettingsValues = ({
};
}
const groupByFieldX =
'groupByFieldMetadataIdX' in configuration
? objectMetadataItem?.fields.find(
(fieldMetadataItem) =>
fieldMetadataItem.id === configuration.groupByFieldMetadataIdX,
)
: undefined;
const isBarOrLineChart =
configuration.__typename === 'BarChartConfiguration' ||
configuration.__typename === 'LineChartConfiguration';
let groupByFieldXId: string | undefined;
let groupByFieldYId: string | undefined;
let groupBySubFieldNameX: CompositeFieldSubFieldName | undefined;
let groupBySubFieldNameY: CompositeFieldSubFieldName | undefined;
let xAxisOrderBy: GraphOrderBy | undefined | null;
let groupByOrderBy: GraphOrderBy | undefined | null;
if (isBarOrLineChart) {
groupByFieldXId = configuration.primaryAxisGroupByFieldMetadataId;
groupByFieldYId = configuration.secondaryAxisGroupByFieldMetadataId;
groupBySubFieldNameX = configuration.primaryAxisGroupBySubFieldName as
| CompositeFieldSubFieldName
| undefined;
groupBySubFieldNameY = configuration.secondaryAxisGroupBySubFieldName as
| CompositeFieldSubFieldName
| undefined;
xAxisOrderBy = configuration.primaryAxisOrderBy;
groupByOrderBy = configuration.secondaryAxisOrderBy;
}
const groupByFieldX = isDefined(groupByFieldXId)
? objectMetadataItem?.fields.find((field) => field.id === groupByFieldXId)
: undefined;
const groupByFieldY = isDefined(groupByFieldYId)
? objectMetadataItem?.fields.find((field) => field.id === groupByFieldYId)
: undefined;
const groupBySubFieldNameXLabel =
'groupBySubFieldNameX' in configuration && isDefined(groupByFieldX)
isDefined(groupBySubFieldNameX) && isDefined(groupByFieldX)
? getFieldLabelWithSubField({
field: groupByFieldX,
subFieldName:
configuration.groupBySubFieldNameX as CompositeFieldSubFieldName,
subFieldName: groupBySubFieldNameX,
})
: undefined;
@@ -61,53 +85,36 @@ export const useChartSettingsValues = ({
const yAxisAggregateOperation = configuration.aggregateOperation;
const groupByFieldY =
'groupByFieldMetadataIdY' in configuration
? objectMetadataItem?.fields.find(
(fieldMetadataItem) =>
fieldMetadataItem.id === configuration.groupByFieldMetadataIdY,
)
: undefined;
const xAxisOrderBy =
'orderByX' in configuration ? configuration.orderByX : undefined;
const xAxisOrderByLabel =
isDefined(xAxisOrderBy) && 'groupByFieldMetadataIdX' in configuration
isDefined(xAxisOrderBy) && isDefined(groupByFieldXId)
? getXSortOptionLabel({
graphOrderBy: xAxisOrderBy,
groupByFieldMetadataIdX: configuration.groupByFieldMetadataIdX,
groupBySubFieldNameX:
configuration.groupBySubFieldNameX as CompositeFieldSubFieldName,
groupByFieldMetadataIdX: groupByFieldXId,
groupBySubFieldNameX: groupBySubFieldNameX,
aggregateFieldMetadataId: configuration.aggregateFieldMetadataId,
aggregateOperation: configuration.aggregateOperation ?? undefined,
})
: undefined;
const groupByOrderBy =
'orderByY' in configuration
? configuration.orderByY
: 'orderBy' in configuration
? configuration.orderBy
: undefined;
if (configuration.__typename === 'PieChartConfiguration') {
groupByOrderBy = configuration.orderBy;
groupByFieldYId = configuration.groupByFieldMetadataId;
groupBySubFieldNameY = configuration.groupBySubFieldName as
| CompositeFieldSubFieldName
| undefined;
}
const finalGroupByFieldYId = groupByFieldYId;
const finalGroupBySubFieldNameY = groupBySubFieldNameY;
const groupByOrderByLabel =
isDefined(groupByOrderBy) &&
getGroupBySortOptionLabel({
graphOrderBy: groupByOrderBy,
groupByFieldMetadataId:
'groupByFieldMetadataIdY' in configuration
? configuration.groupByFieldMetadataIdY
: 'groupByFieldMetadataId' in configuration
? configuration.groupByFieldMetadataId
: undefined,
groupBySubFieldName:
'groupBySubFieldNameY' in configuration
? (configuration.groupBySubFieldNameY as CompositeFieldSubFieldName)
: 'groupBySubFieldName' in configuration
? (configuration.groupBySubFieldName as CompositeFieldSubFieldName)
: undefined,
});
isDefined(groupByOrderBy) && isDefined(finalGroupByFieldYId)
? getGroupBySortOptionLabel({
graphOrderBy: groupByOrderBy,
groupByFieldMetadataId: finalGroupByFieldYId,
groupBySubFieldName: finalGroupBySubFieldNameY,
})
: undefined;
const getChartSettingsValues = (
itemId: CHART_CONFIGURATION_SETTING_IDS,
@@ -119,7 +126,7 @@ export const useChartSettingsValues = ({
return groupBySubFieldNameXLabel ?? groupByFieldX?.label;
case CHART_CONFIGURATION_SETTING_IDS.COLORS:
return 'color' in configuration && isDefined(configuration.color)
? capitalize(configuration.color as string)
? capitalize(configuration.color)
: undefined;
case CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_Y: {
const hasAggregateLabel = isDefined(aggregateField?.label);