Raphaël Bosi
2025-11-27 16:13:06 +01:00
committed by GitHub
parent 65480eb492
commit accd55d7cb
3 changed files with 209 additions and 42 deletions
@@ -3,6 +3,7 @@ import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pa
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
import { buildChartGroupByFieldConfigUpdate } from '@/command-menu/pages/page-layout/utils/buildChartGroupByFieldConfigUpdate';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { isCompositeFieldType } from '@/object-record/object-filter-dropdown/utils/isCompositeFieldType';
@@ -22,7 +23,6 @@ import { useMemo, useState } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
import { MenuItemSelect } from 'twenty-ui/navigation';
import { BarChartGroupMode } from '~/generated/graphql';
import { filterBySearchQuery } from '~/utils/filterBySearchQuery';
type ChartGroupByFieldSelectionDropdownContentBaseProps<
@@ -93,48 +93,18 @@ export const ChartGroupByFieldSelectionDropdownContentBase = <
return null;
}
const buildConfigUpdate = (
fieldId: string | null,
subFieldName: string | null,
) => {
const isSecondaryAxis =
fieldMetadataIdKey === 'secondaryAxisGroupByFieldMetadataId';
const baseConfig = {
[fieldMetadataIdKey]: fieldId,
[subFieldNameKey]: subFieldName,
};
if (!isSecondaryAxis) {
return baseConfig;
}
if (configuration.__typename === 'BarChartConfiguration') {
return {
...baseConfig,
groupMode: isDefined(fieldId)
? (configuration.groupMode ?? BarChartGroupMode.STACKED)
: null,
};
}
if (configuration.__typename === 'LineChartConfiguration') {
return {
...baseConfig,
isStacked: isDefined(fieldId)
? (configuration.isStacked ?? true)
: null,
};
}
return baseConfig;
};
const handleSelectField = (fieldMetadataItem: FieldMetadataItem) => {
if (isCompositeFieldType(fieldMetadataItem.type)) {
setSelectedCompositeField(fieldMetadataItem);
} else {
updateCurrentWidgetConfig({
configToUpdate: buildConfigUpdate(fieldMetadataItem.id, null),
configToUpdate: buildChartGroupByFieldConfigUpdate({
configuration,
fieldMetadataIdKey,
subFieldNameKey,
fieldId: fieldMetadataItem.id,
subFieldName: null,
}),
});
closeDropdown();
}
@@ -142,7 +112,13 @@ export const ChartGroupByFieldSelectionDropdownContentBase = <
const handleSelectNone = () => {
updateCurrentWidgetConfig({
configToUpdate: buildConfigUpdate(null, null),
configToUpdate: buildChartGroupByFieldConfigUpdate({
configuration,
fieldMetadataIdKey,
subFieldNameKey,
fieldId: null,
subFieldName: null,
}),
});
closeDropdown();
};
@@ -157,10 +133,13 @@ export const ChartGroupByFieldSelectionDropdownContentBase = <
}
updateCurrentWidgetConfig({
configToUpdate: buildConfigUpdate(
selectedCompositeField.id,
configToUpdate: buildChartGroupByFieldConfigUpdate({
configuration,
fieldMetadataIdKey,
subFieldNameKey,
fieldId: selectedCompositeField.id,
subFieldName,
),
}),
});
closeDropdown();
};
@@ -0,0 +1,77 @@
import { ObjectRecordGroupByDateGranularity } from 'twenty-shared/types';
import {
type BarChartConfiguration,
BarChartGroupMode,
GraphOrderBy,
type PieChartConfiguration,
} from '~/generated/graphql';
import { buildChartGroupByFieldConfigUpdate } from '../buildChartGroupByFieldConfigUpdate';
describe('buildChartGroupByFieldConfigUpdate', () => {
it('sets default orderBy and dateGranularity for primary axis', () => {
const result = buildChartGroupByFieldConfigUpdate({
configuration: {
__typename: 'BarChartConfiguration',
} as BarChartConfiguration,
fieldMetadataIdKey: 'primaryAxisGroupByFieldMetadataId',
subFieldNameKey: 'primaryAxisGroupBySubFieldName',
fieldId: 'field',
subFieldName: null,
});
expect(result).toMatchObject({
primaryAxisOrderBy: GraphOrderBy.FIELD_ASC,
primaryAxisDateGranularity: ObjectRecordGroupByDateGranularity.DAY,
});
});
it('clears orderBy and dateGranularity when primary axis fieldId is null', () => {
const result = buildChartGroupByFieldConfigUpdate({
configuration: {
__typename: 'BarChartConfiguration',
} as BarChartConfiguration,
fieldMetadataIdKey: 'primaryAxisGroupByFieldMetadataId',
subFieldNameKey: 'primaryAxisGroupBySubFieldName',
fieldId: null,
subFieldName: null,
});
expect(result).toMatchObject({
primaryAxisOrderBy: null,
primaryAxisDateGranularity: null,
});
});
it('sets groupMode for bar chart secondary axis', () => {
const result = buildChartGroupByFieldConfigUpdate({
configuration: {
__typename: 'BarChartConfiguration',
} as BarChartConfiguration,
fieldMetadataIdKey: 'secondaryAxisGroupByFieldMetadataId',
subFieldNameKey: 'secondaryAxisGroupBySubFieldName',
fieldId: 'field',
subFieldName: null,
});
expect(result).toMatchObject({
groupMode: BarChartGroupMode.STACKED,
});
});
it('sets orderBy and dateGranularity for pie chart groupBy', () => {
const result = buildChartGroupByFieldConfigUpdate({
configuration: {
__typename: 'PieChartConfiguration',
} as PieChartConfiguration,
fieldMetadataIdKey: 'groupByFieldMetadataId',
subFieldNameKey: 'groupBySubFieldName',
fieldId: 'field',
subFieldName: null,
});
expect(result).toMatchObject({
orderBy: GraphOrderBy.FIELD_ASC,
dateGranularity: ObjectRecordGroupByDateGranularity.DAY,
});
});
});
@@ -0,0 +1,111 @@
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
import { ObjectRecordGroupByDateGranularity } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
import { BarChartGroupMode, GraphOrderBy } from '~/generated/graphql';
type BuildChartGroupByFieldConfigUpdateArgs<T extends ChartConfiguration> = {
configuration: T;
fieldMetadataIdKey: keyof T;
subFieldNameKey: keyof T;
fieldId: string | null;
subFieldName: string | null;
};
export const buildChartGroupByFieldConfigUpdate = <
T extends ChartConfiguration,
>({
configuration,
fieldMetadataIdKey,
subFieldNameKey,
fieldId,
subFieldName,
}: BuildChartGroupByFieldConfigUpdateArgs<T>) => {
const isPrimaryAxis =
fieldMetadataIdKey === 'primaryAxisGroupByFieldMetadataId';
const isSecondaryAxis =
fieldMetadataIdKey === 'secondaryAxisGroupByFieldMetadataId';
const isPieChartGroupBy = fieldMetadataIdKey === 'groupByFieldMetadataId';
const baseConfig = {
[fieldMetadataIdKey]: fieldId,
[subFieldNameKey]: subFieldName,
};
const isBarChart = configuration.__typename === 'BarChartConfiguration';
const isLineChart = configuration.__typename === 'LineChartConfiguration';
const isPieChart = configuration.__typename === 'PieChartConfiguration';
if (isPrimaryAxis) {
const existingOrderBy =
isBarChart || isLineChart ? configuration.primaryAxisOrderBy : null;
const existingDateGranularity =
isBarChart || isLineChart
? configuration.primaryAxisDateGranularity
: null;
return {
...baseConfig,
primaryAxisOrderBy: isDefined(fieldId)
? (existingOrderBy ?? GraphOrderBy.FIELD_ASC)
: null,
primaryAxisDateGranularity: isDefined(fieldId)
? (existingDateGranularity ?? ObjectRecordGroupByDateGranularity.DAY)
: null,
};
}
if (isPieChartGroupBy) {
const existingOrderBy = isPieChart ? configuration.orderBy : null;
const existingDateGranularity = isPieChart
? configuration.dateGranularity
: null;
return {
...baseConfig,
orderBy: isDefined(fieldId)
? (existingOrderBy ?? GraphOrderBy.FIELD_ASC)
: null,
dateGranularity: isDefined(fieldId)
? (existingDateGranularity ?? ObjectRecordGroupByDateGranularity.DAY)
: null,
};
}
if (!isSecondaryAxis) {
return baseConfig;
}
if (isBarChart) {
return {
...baseConfig,
secondaryAxisOrderBy: isDefined(fieldId)
? (configuration.secondaryAxisOrderBy ?? GraphOrderBy.FIELD_ASC)
: null,
secondaryAxisGroupByDateGranularity: isDefined(fieldId)
? (configuration.secondaryAxisGroupByDateGranularity ??
ObjectRecordGroupByDateGranularity.DAY)
: null,
groupMode: isDefined(fieldId)
? (configuration.groupMode ?? BarChartGroupMode.STACKED)
: null,
};
}
if (isLineChart) {
return {
...baseConfig,
secondaryAxisOrderBy: isDefined(fieldId)
? (configuration.secondaryAxisOrderBy ?? GraphOrderBy.FIELD_ASC)
: null,
secondaryAxisGroupByDateGranularity: isDefined(fieldId)
? (configuration.secondaryAxisGroupByDateGranularity ??
ObjectRecordGroupByDateGranularity.DAY)
: null,
isStacked: isDefined(fieldId) ? (configuration.isStacked ?? true) : null,
};
}
return baseConfig;
};