Convert number chart to aggregate chart allowing date aggregates (#15294)
- Convert number chart to aggregate chart - Allow date aggregates on all charts - Only allow `EARLIEST` and `LATEST` on Aggregate chart and Gauge chart - Various design fixes https://github.com/user-attachments/assets/b5a2239d-7b11-48b5-93e6-98ceffae5cab
This commit is contained in:
+3
-3
@@ -2,8 +2,8 @@ import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMeta
|
||||
import { getDefaultWidgetData } from '@/page-layout/utils/getDefaultWidgetData';
|
||||
import { PageLayoutWidgetNoDataDisplay } from '@/page-layout/widgets/components/PageLayoutWidgetNoDataDisplay';
|
||||
import { ChartSkeletonLoader } from '@/page-layout/widgets/graph/components/ChartSkeletonLoader';
|
||||
import { GraphWidgetAggregateChartRenderer } from '@/page-layout/widgets/graph/graphWidgetAggregateChart/components/GraphWidgetAggregateChartRenderer';
|
||||
import { GraphWidgetBarChartRenderer } from '@/page-layout/widgets/graph/graphWidgetBarChart/components/GraphWidgetBarChartRenderer';
|
||||
import { GraphWidgetNumberChartRenderer } from '@/page-layout/widgets/graph/graphWidgetNumberChart/components/GraphWidgetNumberChartRenderer';
|
||||
import { areChartConfigurationFieldsValidForQuery } from '@/page-layout/widgets/graph/utils/areChartConfigurationFieldsValidForQuery';
|
||||
import { lazy, Suspense } from 'react';
|
||||
import { GraphType, type PageLayoutWidget } from '~/generated/graphql';
|
||||
@@ -63,8 +63,8 @@ export const GraphWidget = ({
|
||||
}
|
||||
|
||||
switch (graphType) {
|
||||
case GraphType.NUMBER:
|
||||
return <GraphWidgetNumberChartRenderer widget={widget} />;
|
||||
case GraphType.AGGREGATE:
|
||||
return <GraphWidgetAggregateChartRenderer widget={widget} />;
|
||||
|
||||
case GraphType.GAUGE:
|
||||
return (
|
||||
|
||||
+5
-5
@@ -1,16 +1,16 @@
|
||||
import { type Meta, type StoryObj } from '@storybook/react';
|
||||
|
||||
import { GraphWidgetAggregateChart } from '@/page-layout/widgets/graph/graphWidgetAggregateChart/components/GraphWidgetAggregateChart';
|
||||
import { ComponentDecorator } from 'twenty-ui/testing';
|
||||
import { GraphWidgetNumberChart } from '@/page-layout/widgets/graph/graphWidgetNumberChart/components/GraphWidgetNumberChart';
|
||||
|
||||
const meta: Meta<typeof GraphWidgetNumberChart> = {
|
||||
title: 'Modules/PageLayout/Widgets/GraphWidgetNumberChart',
|
||||
component: GraphWidgetNumberChart,
|
||||
const meta: Meta<typeof GraphWidgetAggregateChart> = {
|
||||
title: 'Modules/PageLayout/Widgets/GraphWidgetAggregateChart',
|
||||
component: GraphWidgetAggregateChart,
|
||||
decorators: [ComponentDecorator],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof GraphWidgetNumberChart>;
|
||||
type Story = StoryObj<typeof GraphWidgetAggregateChart>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
+5
-4
@@ -1,4 +1,4 @@
|
||||
import { formatNumberChartTrend } from '@/page-layout/widgets/graph/graphWidgetNumberChart/utils/formatNumberChartTrend';
|
||||
import { formatNumberChartTrend } from '@/page-layout/widgets/graph/graphWidgetAggregateChart/utils/formatNumberChartTrend';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
IconTrendingUp,
|
||||
} from 'twenty-ui/display';
|
||||
|
||||
type GraphWidgetNumberChartProps = {
|
||||
type GraphWidgetAggregateChartProps = {
|
||||
value: string | number;
|
||||
trendPercentage?: number;
|
||||
};
|
||||
@@ -36,13 +36,14 @@ const StyledTrendIconContainer = styled.div`
|
||||
`;
|
||||
|
||||
const StyledH1Title = styled(H1Title)`
|
||||
font-size: ${({ theme }) => theme.font.size.xxl};
|
||||
margin: 0;
|
||||
`;
|
||||
|
||||
export const GraphWidgetNumberChart = ({
|
||||
export const GraphWidgetAggregateChart = ({
|
||||
value,
|
||||
trendPercentage,
|
||||
}: GraphWidgetNumberChartProps) => {
|
||||
}: GraphWidgetAggregateChartProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const formattedPercentage = isDefined(trendPercentage)
|
||||
+7
-7
@@ -2,26 +2,26 @@ import { ChartSkeletonLoader } from '@/page-layout/widgets/graph/components/Char
|
||||
import { useGraphWidgetAggregateQuery } from '@/page-layout/widgets/graph/hooks/useGraphWidgetAggregateQuery';
|
||||
import { lazy, Suspense } from 'react';
|
||||
import {
|
||||
type NumberChartConfiguration,
|
||||
type AggregateChartConfiguration,
|
||||
type PageLayoutWidget,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
const GraphWidgetNumberChart = lazy(() =>
|
||||
const GraphWidgetAggregateChart = lazy(() =>
|
||||
import(
|
||||
'@/page-layout/widgets/graph/graphWidgetNumberChart/components/GraphWidgetNumberChart'
|
||||
'@/page-layout/widgets/graph/graphWidgetAggregateChart/components/GraphWidgetAggregateChart'
|
||||
).then((module) => ({
|
||||
default: module.GraphWidgetNumberChart,
|
||||
default: module.GraphWidgetAggregateChart,
|
||||
})),
|
||||
);
|
||||
|
||||
export const GraphWidgetNumberChartRenderer = ({
|
||||
export const GraphWidgetAggregateChartRenderer = ({
|
||||
widget,
|
||||
}: {
|
||||
widget: PageLayoutWidget;
|
||||
}) => {
|
||||
const { value, loading } = useGraphWidgetAggregateQuery({
|
||||
objectMetadataItemId: widget.objectMetadataId,
|
||||
configuration: widget.configuration as NumberChartConfiguration,
|
||||
configuration: widget.configuration as AggregateChartConfiguration,
|
||||
});
|
||||
|
||||
if (loading) {
|
||||
@@ -30,7 +30,7 @@ export const GraphWidgetNumberChartRenderer = ({
|
||||
|
||||
return (
|
||||
<Suspense fallback={<ChartSkeletonLoader />}>
|
||||
<GraphWidgetNumberChart value={value ?? 0} />
|
||||
<GraphWidgetAggregateChart value={value ?? '-'} />
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
+12
-8
@@ -1,11 +1,11 @@
|
||||
import { useAggregateRecords } from '@/object-record/hooks/useAggregateRecords';
|
||||
import { computeAggregateValueAndLabel } from '@/object-record/record-board/record-board-column/utils/computeAggregateValueAndLabel';
|
||||
import { type ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
|
||||
import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation';
|
||||
import { useGraphWidgetQueryCommon } from '@/page-layout/widgets/graph/hooks/useGraphWidgetQueryCommon';
|
||||
import { UserContext } from '@/users/contexts/UserContext';
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { type NumberChartConfiguration } from '~/generated/graphql';
|
||||
import { type AggregateChartConfiguration } from '~/generated/graphql';
|
||||
import { dateLocaleState } from '~/localization/states/dateLocaleState';
|
||||
|
||||
export const useGraphWidgetAggregateQuery = ({
|
||||
@@ -13,7 +13,7 @@ export const useGraphWidgetAggregateQuery = ({
|
||||
configuration,
|
||||
}: {
|
||||
objectMetadataItemId: string;
|
||||
configuration: NumberChartConfiguration;
|
||||
configuration: AggregateChartConfiguration;
|
||||
}) => {
|
||||
const { objectMetadataItem, gqlOperationFilter, aggregateField } =
|
||||
useGraphWidgetQueryCommon({
|
||||
@@ -21,14 +21,18 @@ export const useGraphWidgetAggregateQuery = ({
|
||||
configuration,
|
||||
});
|
||||
|
||||
// TODO: Move this enum to shared
|
||||
const aggregateOperation =
|
||||
configuration.aggregateOperation as unknown as ExtendedAggregateOperations;
|
||||
const aggregateOperation = configuration.aggregateOperation;
|
||||
|
||||
const extendedAggregateOperation =
|
||||
convertAggregateOperationToExtendedAggregateOperation(
|
||||
aggregateOperation,
|
||||
aggregateField.type,
|
||||
);
|
||||
|
||||
const { data, loading, error } = useAggregateRecords({
|
||||
objectNameSingular: objectMetadataItem.nameSingular,
|
||||
recordGqlFieldsAggregate: {
|
||||
[aggregateField.name]: [aggregateOperation],
|
||||
[aggregateField.name]: [extendedAggregateOperation],
|
||||
},
|
||||
filter: gqlOperationFilter,
|
||||
});
|
||||
@@ -40,7 +44,7 @@ export const useGraphWidgetAggregateQuery = ({
|
||||
data,
|
||||
objectMetadataItem,
|
||||
fieldMetadataId: configuration.aggregateFieldMetadataId,
|
||||
aggregateOperation,
|
||||
aggregateOperation: extendedAggregateOperation,
|
||||
dateFormat,
|
||||
timeFormat,
|
||||
timeZone,
|
||||
|
||||
+2
-2
@@ -4,8 +4,8 @@ import {
|
||||
isDefined,
|
||||
} from 'twenty-shared/utils';
|
||||
import {
|
||||
type AggregateChartConfiguration,
|
||||
type BarChartConfiguration,
|
||||
type NumberChartConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
export const useGraphWidgetQueryCommon = ({
|
||||
@@ -13,7 +13,7 @@ export const useGraphWidgetQueryCommon = ({
|
||||
configuration,
|
||||
}: {
|
||||
objectMetadataItemId: string;
|
||||
configuration: BarChartConfiguration | NumberChartConfiguration;
|
||||
configuration: BarChartConfiguration | AggregateChartConfiguration;
|
||||
}) => {
|
||||
const { objectMetadataItem } = useObjectMetadataItemById({
|
||||
objectId: objectMetadataItemId,
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ export const areChartConfigurationFieldsValidForQuery = (
|
||||
fieldExists(configuration.groupByFieldMetadataId, objectMetadataItem)
|
||||
);
|
||||
|
||||
case 'NumberChartConfiguration':
|
||||
case 'AggregateChartConfiguration':
|
||||
case 'GaugeChartConfiguration':
|
||||
return fieldExists(
|
||||
configuration.aggregateFieldMetadataId,
|
||||
|
||||
Reference in New Issue
Block a user