diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/utils/transformGroupByDataToBarChartData.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/utils/transformGroupByDataToBarChartData.ts index 19e6dd9f47..ed61a02bcf 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/utils/transformGroupByDataToBarChartData.ts +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetBarChart/utils/transformGroupByDataToBarChartData.ts @@ -151,16 +151,19 @@ export const transformGroupByDataToBarChartData = ({ groupByFieldX.type === FieldMetadataType.DATE || groupByFieldX.type === FieldMetadataType.DATE_TIME; - const dateGapFillResult = isDateField - ? fillDateGapsInBarChartData({ - data: filteredResults, - keys: [aggregateField.name], - dateGranularity: - configuration.primaryAxisDateGranularity ?? - GRAPH_DEFAULT_DATE_GRANULARITY, - hasSecondDimension: isDefined(groupByFieldY), - }) - : { data: filteredResults, wasTruncated: false }; + const omitNullValues = configuration.omitNullValues ?? false; + + const dateGapFillResult = + isDateField && !omitNullValues + ? fillDateGapsInBarChartData({ + data: filteredResults, + keys: [aggregateField.name], + dateGranularity: + configuration.primaryAxisDateGranularity ?? + GRAPH_DEFAULT_DATE_GRANULARITY, + hasSecondDimension: isDefined(groupByFieldY), + }) + : { data: filteredResults, wasTruncated: false }; const filteredResultsWithDateGaps = dateGapFillResult.data; const dateRangeWasTruncated = dateGapFillResult.wasTruncated; diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/components/GraphWidgetPieChart.tsx b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/components/GraphWidgetPieChart.tsx index 80f5cfb750..2c4ee3caa8 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/components/GraphWidgetPieChart.tsx +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/components/GraphWidgetPieChart.tsx @@ -2,6 +2,7 @@ import { GraphWidgetChartContainer } from '@/page-layout/widgets/graph/component import { GraphWidgetLegend } from '@/page-layout/widgets/graph/components/GraphWidgetLegend'; import { GraphWidgetTooltip } from '@/page-layout/widgets/graph/components/GraphWidgetTooltip'; import { PIE_CHART_HOVER_BRIGHTNESS } from '@/page-layout/widgets/graph/graphWidgetPieChart/constants/PieChartHoverBrightness'; +import { PIE_CHART_MARGINS } from '@/page-layout/widgets/graph/graphWidgetPieChart/constants/PieChartMargins'; import { usePieChartData } from '@/page-layout/widgets/graph/graphWidgetPieChart/hooks/usePieChartData'; import { usePieChartHandlers } from '@/page-layout/widgets/graph/graphWidgetPieChart/hooks/usePieChartHandlers'; import { usePieChartTooltip } from '@/page-layout/widgets/graph/graphWidgetPieChart/hooks/usePieChartTooltip'; @@ -10,7 +11,11 @@ import { createGraphColorRegistry } from '@/page-layout/widgets/graph/utils/crea import { type GraphValueFormatOptions } from '@/page-layout/widgets/graph/utils/graphFormatters'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; -import { ResponsivePie, type PieTooltipProps } from '@nivo/pie'; +import { + ResponsivePie, + type ComputedDatum, + type PieTooltipProps, +} from '@nivo/pie'; import { isDefined } from 'twenty-shared/utils'; type GraphWidgetPieChartProps = { @@ -18,6 +23,7 @@ type GraphWidgetPieChartProps = { showLegend?: boolean; id: string; onSliceClick?: (datum: PieChartDataItem) => void; + showDataLabels?: boolean; } & GraphValueFormatOptions; const StyledContainer = styled.div` @@ -52,6 +58,7 @@ export const GraphWidgetPieChart = ({ suffix, customFormatter, onSliceClick, + showDataLabels = false, }: GraphWidgetPieChartProps) => { const theme = useTheme(); const colorRegistry = createGraphColorRegistry(theme); @@ -87,7 +94,12 @@ export const GraphWidgetPieChart = ({ const tooltipData = createTooltipData(datum); if (!isDefined(tooltipData)) return null; - return ; + return ( + handleSliceClick(datum)} + /> + ); }; return ( @@ -99,16 +111,29 @@ export const GraphWidgetPieChart = ({ item.colorScheme.solid)} borderWidth={0} - enableArcLinkLabels={false} + enableArcLinkLabels={showDataLabels} enableArcLabels={false} tooltip={renderTooltip} onClick={handleSliceClick} onMouseEnter={(datum) => setHoveredSliceId(datum.id)} onMouseLeave={() => setHoveredSliceId(null)} - layers={['arcs']} + layers={['arcs', 'arcLinkLabels']} + arcLinkLabel={(datum: ComputedDatum) => { + const tooltipData = createTooltipData(datum); + return ( + tooltipData?.tooltipItem.formattedValue || + datum.data.value.toString() + ); + }} + arcLinkLabelsDiagonalLength={10} + arcLinkLabelsStraightLength={10} + arcLinkLabelsTextColor={theme.font.color.light} + arcLinkLabelsColor={theme.font.color.extraLight} /> diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/components/GraphWidgetPieChartRenderer.tsx b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/components/GraphWidgetPieChartRenderer.tsx index f7ba00cb27..7f234d41ba 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/components/GraphWidgetPieChartRenderer.tsx +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/components/GraphWidgetPieChartRenderer.tsx @@ -26,11 +26,16 @@ export const GraphWidgetPieChartRenderer = ({ }: { widget: PageLayoutWidget; }) => { - const { data, loading, hasTooManyGroups, objectMetadataItem } = - useGraphPieChartWidgetData({ - objectMetadataItemId: widget.objectMetadataId, - configuration: widget.configuration as PieChartConfiguration, - }); + const { + data, + loading, + hasTooManyGroups, + objectMetadataItem, + showDataLabels, + } = useGraphPieChartWidgetData({ + objectMetadataItemId: widget.objectMetadataId, + configuration: widget.configuration as PieChartConfiguration, + }); const navigate = useNavigate(); @@ -66,6 +71,7 @@ export const GraphWidgetPieChartRenderer = ({ id={widget.id} displayType="shortNumber" onSliceClick={handleSliceClick} + showDataLabels={showDataLabels} /> ); diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/constants/PieChartMargins.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/constants/PieChartMargins.ts new file mode 100644 index 0000000000..7dd9b64b45 --- /dev/null +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/constants/PieChartMargins.ts @@ -0,0 +1,6 @@ +export const PIE_CHART_MARGINS = { + top: 40, + right: 80, + bottom: 40, + left: 80, +} as const; diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/hooks/useGraphPieChartWidgetData.ts b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/hooks/useGraphPieChartWidgetData.ts index 45e9337f7f..9df1a4e08d 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/hooks/useGraphPieChartWidgetData.ts +++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/graphWidgetPieChart/hooks/useGraphPieChartWidgetData.ts @@ -18,6 +18,7 @@ type UseGraphPieChartWidgetDataResult = { error?: Error; hasTooManyGroups: boolean; objectMetadataItem: ObjectMetadataItem; + showDataLabels: boolean; }; // TODO: Remove this once backend returns total group count @@ -57,6 +58,7 @@ export const useGraphPieChartWidgetData = ({ return { ...transformedData, objectMetadataItem, + showDataLabels: configuration.displayDataLabel ?? false, loading, error, }; diff --git a/packages/twenty-front/src/modules/page-layout/widgets/widget-card/components/WidgetCardHeader.tsx b/packages/twenty-front/src/modules/page-layout/widgets/widget-card/components/WidgetCardHeader.tsx index 59f1b7a89b..d1365bd69a 100644 --- a/packages/twenty-front/src/modules/page-layout/widgets/widget-card/components/WidgetCardHeader.tsx +++ b/packages/twenty-front/src/modules/page-layout/widgets/widget-card/components/WidgetCardHeader.tsx @@ -70,7 +70,7 @@ export const WidgetCardHeader = ({ return ( - + {!isEmpty && isInEditMode && ( {isDefined(forbiddenDisplay) && forbiddenDisplay} - + {!isResizing && !isEmpty && isInEditMode &&