diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/constants/ExtraItemToDetectTooManyGroups.constant.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/constants/ExtraItemToDetectTooManyGroups.constant.ts new file mode 100644 index 0000000000..c3f26caef0 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/constants/ExtraItemToDetectTooManyGroups.constant.ts @@ -0,0 +1,2 @@ +// TODO: Remove this once backend returns total group count +export const EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS = 1; diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/constants/BarChartMaximumNumberOfGroupsPerBar.constant.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/constants/BarChartMaximumNumberOfGroupsPerBar.constant.ts new file mode 100644 index 0000000000..0cd5c735b9 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/constants/BarChartMaximumNumberOfGroupsPerBar.constant.ts @@ -0,0 +1 @@ +export const BAR_CHART_MAXIMUM_NUMBER_OF_GROUPS_PER_BAR = 50; diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/hooks/useGraphBarChartWidgetData.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/hooks/useGraphBarChartWidgetData.ts index 6f50ffbc56..3a64ff8b2e 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/hooks/useGraphBarChartWidgetData.ts +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/hooks/useGraphBarChartWidgetData.ts @@ -1,7 +1,7 @@ import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById'; -import { BAR_CHART_MAXIMUM_NUMBER_OF_BARS } from '@/page-layout/widgets/graph/graphWidgetBarChart/constants/BarChartMaximumNumberOfBars.constant'; import { type BarChartLayout } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartLayout'; import { type BarChartSeries } from '@/page-layout/widgets/graph/graphWidgetBarChart/types/BarChartSeries'; +import { getBarChartQueryLimit } from '@/page-layout/widgets/graph/graphWidgetBarChart/utils/getBarChartQueryLimit'; import { transformGroupByDataToBarChartData } from '@/page-layout/widgets/graph/graphWidgetBarChart/utils/transformGroupByDataToBarChartData'; import { useGraphWidgetGroupByQuery } from '@/page-layout/widgets/graph/hooks/useGraphWidgetGroupByQuery'; import { type RawDimensionValue } from '@/page-layout/widgets/graph/types/RawDimensionValue'; @@ -32,9 +32,6 @@ type UseGraphBarChartWidgetDataResult = { >['objectMetadataItem']; }; -// TODO: Remove this once backend returns total group count -const EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS = 1; - export const useGraphBarChartWidgetData = ({ objectMetadataItemId, configuration, @@ -43,6 +40,8 @@ export const useGraphBarChartWidgetData = ({ objectId: objectMetadataItemId, }); + const limit = getBarChartQueryLimit(configuration); + const { data: groupByData, loading, @@ -51,8 +50,7 @@ export const useGraphBarChartWidgetData = ({ } = useGraphWidgetGroupByQuery({ objectMetadataItemId, configuration, - limit: - BAR_CHART_MAXIMUM_NUMBER_OF_BARS + EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS, + limit, }); const transformedData = useMemo( diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/utils/__tests__/getBarChartQueryLimit.test.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/utils/__tests__/getBarChartQueryLimit.test.ts new file mode 100644 index 0000000000..8b3a299921 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/utils/__tests__/getBarChartQueryLimit.test.ts @@ -0,0 +1,48 @@ +import { EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS } from '@/page-layout/widgets/graph/constants/ExtraItemToDetectTooManyGroups.constant'; +import { BAR_CHART_MAXIMUM_NUMBER_OF_BARS } from '@/page-layout/widgets/graph/graphWidgetBarChart/constants/BarChartMaximumNumberOfBars.constant'; +import { BAR_CHART_MAXIMUM_NUMBER_OF_GROUPS_PER_BAR } from '@/page-layout/widgets/graph/graphWidgetBarChart/constants/BarChartMaximumNumberOfGroupsPerBar.constant'; +import { + type BarChartConfiguration, + BarChartGroupMode, +} from '~/generated-metadata/graphql'; +import { getBarChartQueryLimit } from '../getBarChartQueryLimit'; + +describe('getBarChartQueryLimit', () => { + it('should return one-dimensional limit for bar chart without secondary axis', () => { + const result = getBarChartQueryLimit({ + __typename: 'BarChartConfiguration', + secondaryAxisGroupByFieldMetadataId: null, + groupMode: BarChartGroupMode.STACKED, + } as BarChartConfiguration); + + expect(result).toBe( + BAR_CHART_MAXIMUM_NUMBER_OF_BARS + EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS, + ); + }); + + it('should return two-dimensional stacked limit for bar chart with secondary axis and stacked mode', () => { + const result = getBarChartQueryLimit({ + __typename: 'BarChartConfiguration', + secondaryAxisGroupByFieldMetadataId: 'some-field-id', + groupMode: BarChartGroupMode.STACKED, + } as BarChartConfiguration); + + expect(result).toBe( + BAR_CHART_MAXIMUM_NUMBER_OF_BARS * + BAR_CHART_MAXIMUM_NUMBER_OF_GROUPS_PER_BAR + + EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS, + ); + }); + + it('should return one-dimensional limit for bar chart with secondary axis and grouped mode', () => { + const result = getBarChartQueryLimit({ + __typename: 'BarChartConfiguration', + secondaryAxisGroupByFieldMetadataId: 'some-field-id', + groupMode: BarChartGroupMode.GROUPED, + } as BarChartConfiguration); + + expect(result).toBe( + BAR_CHART_MAXIMUM_NUMBER_OF_BARS + EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS, + ); + }); +}); diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/utils/getBarChartQueryLimit.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/utils/getBarChartQueryLimit.ts new file mode 100644 index 0000000000..e79c9626b2 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/utils/getBarChartQueryLimit.ts @@ -0,0 +1,27 @@ +import { EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS } from '@/page-layout/widgets/graph/constants/ExtraItemToDetectTooManyGroups.constant'; +import { BAR_CHART_MAXIMUM_NUMBER_OF_BARS } from '@/page-layout/widgets/graph/graphWidgetBarChart/constants/BarChartMaximumNumberOfBars.constant'; +import { BAR_CHART_MAXIMUM_NUMBER_OF_GROUPS_PER_BAR } from '@/page-layout/widgets/graph/graphWidgetBarChart/constants/BarChartMaximumNumberOfGroupsPerBar.constant'; +import { isChartConfigurationTwoDimensional } from '@/page-layout/widgets/graph/utils/isChartConfigurationTwoDimensional'; +import { + BarChartGroupMode, + type BarChartConfiguration, +} from '~/generated/graphql'; + +export const getBarChartQueryLimit = ( + configuration: BarChartConfiguration, +): number => { + if ( + isChartConfigurationTwoDimensional(configuration) && + configuration.groupMode === BarChartGroupMode.STACKED + ) { + return ( + BAR_CHART_MAXIMUM_NUMBER_OF_BARS * + BAR_CHART_MAXIMUM_NUMBER_OF_GROUPS_PER_BAR + + EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS + ); + } + + return ( + BAR_CHART_MAXIMUM_NUMBER_OF_BARS + EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS + ); +}; diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/constants/LineChartMaximumNumberOfNonStackedSeries.constant.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/constants/LineChartMaximumNumberOfNonStackedSeries.constant.ts new file mode 100644 index 0000000000..887acb7ee9 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/constants/LineChartMaximumNumberOfNonStackedSeries.constant.ts @@ -0,0 +1 @@ +export const LINE_CHART_MAXIMUM_NUMBER_OF_NON_STACKED_SERIES = 50; diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/constants/LineChartMaximumNumberOfStackedSeries.constant.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/constants/LineChartMaximumNumberOfStackedSeries.constant.ts new file mode 100644 index 0000000000..ba21a01d03 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/constants/LineChartMaximumNumberOfStackedSeries.constant.ts @@ -0,0 +1 @@ +export const LINE_CHART_MAXIMUM_NUMBER_OF_STACKED_SERIES = 50; diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/hooks/useGraphLineChartWidgetData.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/hooks/useGraphLineChartWidgetData.ts index e8aa0d6116..655176cda5 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/hooks/useGraphLineChartWidgetData.ts +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/hooks/useGraphLineChartWidgetData.ts @@ -1,5 +1,6 @@ import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById'; import { type LineChartSeries } from '@/page-layout/widgets/graph/graphWidgetLineChart/types/LineChartSeries'; +import { getLineChartQueryLimit } from '@/page-layout/widgets/graph/graphWidgetLineChart/utils/getLineChartQueryLimit'; import { useGraphWidgetGroupByQuery } from '@/page-layout/widgets/graph/hooks/useGraphWidgetGroupByQuery'; import { type RawDimensionValue } from '@/page-layout/widgets/graph/types/RawDimensionValue'; import { transformGroupByDataToLineChartData } from '@/page-layout/widgets/graph/utils/transformGroupByDataToLineChartData'; @@ -33,6 +34,8 @@ export const useGraphLineChartWidgetData = ({ objectId: objectMetadataItemId, }); + const limit = getLineChartQueryLimit(configuration); + const { data: groupByData, loading, @@ -41,6 +44,7 @@ export const useGraphLineChartWidgetData = ({ } = useGraphWidgetGroupByQuery({ objectMetadataItemId, configuration, + limit, }); const transformedData = useMemo( diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/utils/__tests__/getLineChartQueryLimit.test.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/utils/__tests__/getLineChartQueryLimit.test.ts new file mode 100644 index 0000000000..4fdebe13b0 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/utils/__tests__/getLineChartQueryLimit.test.ts @@ -0,0 +1,49 @@ +import { EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS } from '@/page-layout/widgets/graph/constants/ExtraItemToDetectTooManyGroups.constant'; +import { LINE_CHART_MAXIMUM_NUMBER_OF_DATA_POINTS } from '@/page-layout/widgets/graph/graphWidgetLineChart/constants/LineChartMaximumNumberOfDataPoints.constant'; +import { LINE_CHART_MAXIMUM_NUMBER_OF_NON_STACKED_SERIES } from '@/page-layout/widgets/graph/graphWidgetLineChart/constants/LineChartMaximumNumberOfNonStackedSeries.constant'; +import { LINE_CHART_MAXIMUM_NUMBER_OF_STACKED_SERIES } from '@/page-layout/widgets/graph/graphWidgetLineChart/constants/LineChartMaximumNumberOfStackedSeries.constant'; +import { type LineChartConfiguration } from '~/generated-metadata/graphql'; +import { getLineChartQueryLimit } from '../getLineChartQueryLimit'; + +describe('getLineChartQueryLimit', () => { + it('should return one-dimensional limit for line chart without secondary axis', () => { + const result = getLineChartQueryLimit({ + __typename: 'LineChartConfiguration', + secondaryAxisGroupByFieldMetadataId: null, + isStacked: false, + } as LineChartConfiguration); + + expect(result).toBe( + LINE_CHART_MAXIMUM_NUMBER_OF_DATA_POINTS + + EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS, + ); + }); + + it('should return two-dimensional stacked limit for line chart with secondary axis and stacked mode', () => { + const result = getLineChartQueryLimit({ + __typename: 'LineChartConfiguration', + secondaryAxisGroupByFieldMetadataId: 'some-field-id', + isStacked: true, + } as LineChartConfiguration); + + expect(result).toBe( + LINE_CHART_MAXIMUM_NUMBER_OF_DATA_POINTS * + LINE_CHART_MAXIMUM_NUMBER_OF_STACKED_SERIES + + EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS, + ); + }); + + it('should return two-dimensional non-stacked limit for line chart with secondary axis and non-stacked mode', () => { + const result = getLineChartQueryLimit({ + __typename: 'LineChartConfiguration', + secondaryAxisGroupByFieldMetadataId: 'some-field-id', + isStacked: false, + } as LineChartConfiguration); + + expect(result).toBe( + LINE_CHART_MAXIMUM_NUMBER_OF_DATA_POINTS * + LINE_CHART_MAXIMUM_NUMBER_OF_NON_STACKED_SERIES + + EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS, + ); + }); +}); diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/utils/getLineChartQueryLimit.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/utils/getLineChartQueryLimit.ts new file mode 100644 index 0000000000..c270a93677 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetLineChart/utils/getLineChartQueryLimit.ts @@ -0,0 +1,33 @@ +import { EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS } from '@/page-layout/widgets/graph/constants/ExtraItemToDetectTooManyGroups.constant'; +import { LINE_CHART_MAXIMUM_NUMBER_OF_DATA_POINTS } from '@/page-layout/widgets/graph/graphWidgetLineChart/constants/LineChartMaximumNumberOfDataPoints.constant'; +import { LINE_CHART_MAXIMUM_NUMBER_OF_NON_STACKED_SERIES } from '@/page-layout/widgets/graph/graphWidgetLineChart/constants/LineChartMaximumNumberOfNonStackedSeries.constant'; +import { LINE_CHART_MAXIMUM_NUMBER_OF_STACKED_SERIES } from '@/page-layout/widgets/graph/graphWidgetLineChart/constants/LineChartMaximumNumberOfStackedSeries.constant'; +import { isChartConfigurationTwoDimensional } from '@/page-layout/widgets/graph/utils/isChartConfigurationTwoDimensional'; +import { type LineChartConfiguration } from '~/generated/graphql'; + +export const getLineChartQueryLimit = ( + configuration: LineChartConfiguration, +): number => { + const isTwoDimensional = isChartConfigurationTwoDimensional(configuration); + + if (!isTwoDimensional) { + return ( + LINE_CHART_MAXIMUM_NUMBER_OF_DATA_POINTS + + EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS + ); + } + + if (configuration.isStacked === true) { + return ( + LINE_CHART_MAXIMUM_NUMBER_OF_DATA_POINTS * + LINE_CHART_MAXIMUM_NUMBER_OF_STACKED_SERIES + + EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS + ); + } + + return ( + LINE_CHART_MAXIMUM_NUMBER_OF_DATA_POINTS * + LINE_CHART_MAXIMUM_NUMBER_OF_NON_STACKED_SERIES + + EXTRA_ITEM_TO_DETECT_TOO_MANY_GROUPS + ); +}; diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/utils/__tests__/isChartConfigurationTwoDimensional.test.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/utils/__tests__/isChartConfigurationTwoDimensional.test.ts new file mode 100644 index 0000000000..ece53cb5be --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/utils/__tests__/isChartConfigurationTwoDimensional.test.ts @@ -0,0 +1,65 @@ +import { + type BarChartConfiguration, + type LineChartConfiguration, +} from '~/generated-metadata/graphql'; +import { isChartConfigurationTwoDimensional } from '../isChartConfigurationTwoDimensional'; + +describe('isChartConfigurationTwoDimensional', () => { + describe('BarChartConfiguration', () => { + it('should return true for bar chart with secondary axis', () => { + const result = isChartConfigurationTwoDimensional({ + __typename: 'BarChartConfiguration', + secondaryAxisGroupByFieldMetadataId: 'some-field-id', + } as BarChartConfiguration); + + expect(result).toBe(true); + }); + + it('should return false for bar chart without secondary axis', () => { + const result = isChartConfigurationTwoDimensional({ + __typename: 'BarChartConfiguration', + secondaryAxisGroupByFieldMetadataId: null, + } as BarChartConfiguration); + + expect(result).toBe(false); + }); + + it('should return false for bar chart with undefined secondary axis', () => { + const result = isChartConfigurationTwoDimensional({ + __typename: 'BarChartConfiguration', + secondaryAxisGroupByFieldMetadataId: undefined, + } as BarChartConfiguration); + + expect(result).toBe(false); + }); + }); + + describe('LineChartConfiguration', () => { + it('should return true for line chart with secondary axis', () => { + const result = isChartConfigurationTwoDimensional({ + __typename: 'LineChartConfiguration', + secondaryAxisGroupByFieldMetadataId: 'some-field-id', + } as LineChartConfiguration); + + expect(result).toBe(true); + }); + + it('should return false for line chart without secondary axis', () => { + const result = isChartConfigurationTwoDimensional({ + __typename: 'LineChartConfiguration', + secondaryAxisGroupByFieldMetadataId: null, + } as LineChartConfiguration); + + expect(result).toBe(false); + }); + + it('should return false for line chart with undefined secondary axis', () => { + const result = isChartConfigurationTwoDimensional({ + __typename: 'LineChartConfiguration', + secondaryAxisGroupByFieldMetadataId: undefined, + } as LineChartConfiguration); + + expect(result).toBe(false); + }); + }); +}); diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/utils/isChartConfigurationTwoDimensional.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/utils/isChartConfigurationTwoDimensional.ts new file mode 100644 index 0000000000..2868b2cdb4 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/utils/isChartConfigurationTwoDimensional.ts @@ -0,0 +1,11 @@ +import { isDefined } from 'twenty-shared/utils'; +import { + type BarChartConfiguration, + type LineChartConfiguration, +} from '~/generated/graphql'; + +export const isChartConfigurationTwoDimensional = ( + configuration: BarChartConfiguration | LineChartConfiguration, +): boolean => { + return isDefined(configuration.secondaryAxisGroupByFieldMetadataId); +};