[Dashboards] Remove gauge chart types and code (#20410)

Follow-up cleanup to #20172.
This commit is contained in:
nitin
2026-05-29 14:38:50 +05:30
committed by GitHub
parent 961745e9ba
commit 13f09d8946
68 changed files with 607 additions and 2326 deletions
@@ -1100,7 +1100,7 @@ type PageLayoutWidgetCanvasPosition {
layoutMode: PageLayoutTabLayoutMode!
}
union WidgetConfiguration = AggregateChartConfiguration | StandaloneRichTextConfiguration | PieChartConfiguration | LineChartConfiguration | IframeConfiguration | GaugeChartConfiguration | BarChartConfiguration | CalendarConfiguration | FrontComponentConfiguration | EmailsConfiguration | EmailThreadConfiguration | FieldConfiguration | FieldRichTextConfiguration | FieldsConfiguration | FilesConfiguration | NotesConfiguration | TasksConfiguration | TimelineConfiguration | ViewConfiguration | RecordTableConfiguration | WorkflowConfiguration | WorkflowRunConfiguration | WorkflowVersionConfiguration
union WidgetConfiguration = AggregateChartConfiguration | StandaloneRichTextConfiguration | PieChartConfiguration | LineChartConfiguration | IframeConfiguration | BarChartConfiguration | CalendarConfiguration | FrontComponentConfiguration | EmailsConfiguration | EmailThreadConfiguration | FieldConfiguration | FieldRichTextConfiguration | FieldsConfiguration | FilesConfiguration | NotesConfiguration | TasksConfiguration | TimelineConfiguration | ViewConfiguration | RecordTableConfiguration | WorkflowConfiguration | WorkflowRunConfiguration | WorkflowVersionConfiguration
type AggregateChartConfiguration {
configurationType: WidgetConfigurationType!
@@ -1120,7 +1120,6 @@ type AggregateChartConfiguration {
enum WidgetConfigurationType {
AGGREGATE_CHART
GAUGE_CHART
PIE_CHART
BAR_CHART
LINE_CHART
@@ -1239,18 +1238,6 @@ type IframeConfiguration {
url: String
}
type GaugeChartConfiguration {
configurationType: WidgetConfigurationType!
aggregateFieldMetadataId: UUID!
aggregateOperation: AggregateOperations!
displayDataLabel: Boolean
color: String
description: String
filter: JSON
timezone: String
firstDayOfTheWeek: Int
}
type BarChartConfiguration {
configurationType: WidgetConfigurationType!
aggregateFieldMetadataId: UUID!
@@ -790,7 +790,7 @@ export interface PageLayoutWidgetCanvasPosition {
__typename: 'PageLayoutWidgetCanvasPosition'
}
export type WidgetConfiguration = (AggregateChartConfiguration | StandaloneRichTextConfiguration | PieChartConfiguration | LineChartConfiguration | IframeConfiguration | GaugeChartConfiguration | BarChartConfiguration | CalendarConfiguration | FrontComponentConfiguration | EmailsConfiguration | EmailThreadConfiguration | FieldConfiguration | FieldRichTextConfiguration | FieldsConfiguration | FilesConfiguration | NotesConfiguration | TasksConfiguration | TimelineConfiguration | ViewConfiguration | RecordTableConfiguration | WorkflowConfiguration | WorkflowRunConfiguration | WorkflowVersionConfiguration) & { __isUnion?: true }
export type WidgetConfiguration = (AggregateChartConfiguration | StandaloneRichTextConfiguration | PieChartConfiguration | LineChartConfiguration | IframeConfiguration | BarChartConfiguration | CalendarConfiguration | FrontComponentConfiguration | EmailsConfiguration | EmailThreadConfiguration | FieldConfiguration | FieldRichTextConfiguration | FieldsConfiguration | FilesConfiguration | NotesConfiguration | TasksConfiguration | TimelineConfiguration | ViewConfiguration | RecordTableConfiguration | WorkflowConfiguration | WorkflowRunConfiguration | WorkflowVersionConfiguration) & { __isUnion?: true }
export interface AggregateChartConfiguration {
configurationType: WidgetConfigurationType
@@ -809,7 +809,7 @@ export interface AggregateChartConfiguration {
__typename: 'AggregateChartConfiguration'
}
export type WidgetConfigurationType = 'AGGREGATE_CHART' | 'GAUGE_CHART' | 'PIE_CHART' | 'BAR_CHART' | 'LINE_CHART' | 'IFRAME' | 'STANDALONE_RICH_TEXT' | 'VIEW' | 'FIELD' | 'FIELDS' | 'TIMELINE' | 'TASKS' | 'NOTES' | 'FILES' | 'EMAILS' | 'CALENDAR' | 'FIELD_RICH_TEXT' | 'WORKFLOW' | 'WORKFLOW_VERSION' | 'WORKFLOW_RUN' | 'FRONT_COMPONENT' | 'RECORD_TABLE' | 'EMAIL_THREAD'
export type WidgetConfigurationType = 'AGGREGATE_CHART' | 'PIE_CHART' | 'BAR_CHART' | 'LINE_CHART' | 'IFRAME' | 'STANDALONE_RICH_TEXT' | 'VIEW' | 'FIELD' | 'FIELDS' | 'TIMELINE' | 'TASKS' | 'NOTES' | 'FILES' | 'EMAILS' | 'CALENDAR' | 'FIELD_RICH_TEXT' | 'WORKFLOW' | 'WORKFLOW_VERSION' | 'WORKFLOW_RUN' | 'FRONT_COMPONENT' | 'RECORD_TABLE' | 'EMAIL_THREAD'
export interface StandaloneRichTextConfiguration {
configurationType: WidgetConfigurationType
@@ -888,19 +888,6 @@ export interface IframeConfiguration {
__typename: 'IframeConfiguration'
}
export interface GaugeChartConfiguration {
configurationType: WidgetConfigurationType
aggregateFieldMetadataId: Scalars['UUID']
aggregateOperation: AggregateOperations
displayDataLabel?: Scalars['Boolean']
color?: Scalars['String']
description?: Scalars['String']
filter?: Scalars['JSON']
timezone?: Scalars['String']
firstDayOfTheWeek?: Scalars['Int']
__typename: 'GaugeChartConfiguration'
}
export interface BarChartConfiguration {
configurationType: WidgetConfigurationType
aggregateFieldMetadataId: Scalars['UUID']
@@ -3710,7 +3697,6 @@ export interface WidgetConfigurationGenqlSelection{
on_PieChartConfiguration?:PieChartConfigurationGenqlSelection,
on_LineChartConfiguration?:LineChartConfigurationGenqlSelection,
on_IframeConfiguration?:IframeConfigurationGenqlSelection,
on_GaugeChartConfiguration?:GaugeChartConfigurationGenqlSelection,
on_BarChartConfiguration?:BarChartConfigurationGenqlSelection,
on_CalendarConfiguration?:CalendarConfigurationGenqlSelection,
on_FrontComponentConfiguration?:FrontComponentConfigurationGenqlSelection,
@@ -3818,20 +3804,6 @@ export interface IframeConfigurationGenqlSelection{
__scalar?: boolean | number
}
export interface GaugeChartConfigurationGenqlSelection{
configurationType?: boolean | number
aggregateFieldMetadataId?: boolean | number
aggregateOperation?: boolean | number
displayDataLabel?: boolean | number
color?: boolean | number
description?: boolean | number
filter?: boolean | number
timezone?: boolean | number
firstDayOfTheWeek?: boolean | number
__typename?: boolean | number
__scalar?: boolean | number
}
export interface BarChartConfigurationGenqlSelection{
configurationType?: boolean | number
aggregateFieldMetadataId?: boolean | number
@@ -6724,7 +6696,7 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
const WidgetConfiguration_possibleTypes: string[] = ['AggregateChartConfiguration','StandaloneRichTextConfiguration','PieChartConfiguration','LineChartConfiguration','IframeConfiguration','GaugeChartConfiguration','BarChartConfiguration','CalendarConfiguration','FrontComponentConfiguration','EmailsConfiguration','EmailThreadConfiguration','FieldConfiguration','FieldRichTextConfiguration','FieldsConfiguration','FilesConfiguration','NotesConfiguration','TasksConfiguration','TimelineConfiguration','ViewConfiguration','RecordTableConfiguration','WorkflowConfiguration','WorkflowRunConfiguration','WorkflowVersionConfiguration']
const WidgetConfiguration_possibleTypes: string[] = ['AggregateChartConfiguration','StandaloneRichTextConfiguration','PieChartConfiguration','LineChartConfiguration','IframeConfiguration','BarChartConfiguration','CalendarConfiguration','FrontComponentConfiguration','EmailsConfiguration','EmailThreadConfiguration','FieldConfiguration','FieldRichTextConfiguration','FieldsConfiguration','FilesConfiguration','NotesConfiguration','TasksConfiguration','TimelineConfiguration','ViewConfiguration','RecordTableConfiguration','WorkflowConfiguration','WorkflowRunConfiguration','WorkflowVersionConfiguration']
export const isWidgetConfiguration = (obj?: { __typename?: any } | null): obj is WidgetConfiguration => {
if (!obj?.__typename) throw new Error('__typename is missing in "isWidgetConfiguration"')
return WidgetConfiguration_possibleTypes.includes(obj.__typename)
@@ -6772,14 +6744,6 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null
const GaugeChartConfiguration_possibleTypes: string[] = ['GaugeChartConfiguration']
export const isGaugeChartConfiguration = (obj?: { __typename?: any } | null): obj is GaugeChartConfiguration => {
if (!obj?.__typename) throw new Error('__typename is missing in "isGaugeChartConfiguration"')
return GaugeChartConfiguration_possibleTypes.includes(obj.__typename)
}
const BarChartConfiguration_possibleTypes: string[] = ['BarChartConfiguration']
export const isBarChartConfiguration = (obj?: { __typename?: any } | null): obj is BarChartConfiguration => {
if (!obj?.__typename) throw new Error('__typename is missing in "isBarChartConfiguration"')
@@ -8585,7 +8549,6 @@ export const enumPageLayoutTabLayoutMode = {
export const enumWidgetConfigurationType = {
AGGREGATE_CHART: 'AGGREGATE_CHART' as const,
GAUGE_CHART: 'GAUGE_CHART' as const,
PIE_CHART: 'PIE_CHART' as const,
BAR_CHART: 'BAR_CHART' as const,
LINE_CHART: 'LINE_CHART' as const,
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
@@ -47,7 +47,6 @@ const validatePageLayoutContent = async (canvasElement: HTMLElement) => {
const canvas = within(canvasElement);
await expect(await canvas.findByText('Revenue')).toBeVisible();
await expect(await canvas.findByText('Goal Progress')).toBeVisible();
await expect(await canvas.findByText('Revenue Sources')).toBeVisible();
await expect(await canvas.findByText('Quarterly Comparison')).toBeVisible();
};
@@ -99,33 +98,6 @@ const mixedGraphsPageLayoutMocks = {
updatedAt: '2024-01-01T00:00:00Z',
deletedAt: null,
} satisfies PageLayoutWidget,
{
__typename: 'PageLayoutWidget',
applicationId: '',
isActive: true,
id: 'gauge-widget',
pageLayoutTabId: 'mixed-tab',
type: WidgetType.GRAPH,
title: 'Goal Progress',
objectMetadataId: mockPersonObjectMetadataItem.id,
gridPosition: {
__typename: 'GridPosition',
row: 0,
column: 3,
rowSpan: 4,
columnSpan: 3,
},
configuration: {
__typename: 'GaugeChartConfiguration',
configurationType: WidgetConfigurationType.GAUGE_CHART,
aggregateOperation: AggregateOperations.COUNT,
aggregateFieldMetadataId: idField.id,
displayDataLabel: false,
},
createdAt: '2024-01-01T00:00:00Z',
updatedAt: '2024-01-01T00:00:00Z',
deletedAt: null,
} satisfies PageLayoutWidget,
{
__typename: 'PageLayoutWidget',
applicationId: '',
@@ -8,10 +8,6 @@ export const GRAPH_WIDGET_SIZES: Partial<
default: { w: 2, h: 2 },
minimum: { w: 2, h: 2 },
},
[WidgetConfigurationType.GAUGE_CHART]: {
default: { w: 3, h: 4 },
minimum: { w: 3, h: 4 },
},
[WidgetConfigurationType.PIE_CHART]: {
default: { w: 4, h: 4 },
minimum: { w: 3, h: 4 },
@@ -133,17 +133,6 @@ export const PAGE_LAYOUT_WIDGET_FRAGMENT = gql`
optionValue
}
}
... on GaugeChartConfiguration {
configurationType
aggregateFieldMetadataId
aggregateOperation
displayDataLabel
color
description
filter
timezone
firstDayOfTheWeek
}
... on IframeConfiguration {
configurationType
url
@@ -178,7 +178,6 @@ describe('useCreatePageLayoutGraphWidget', () => {
const widgetConfigurationTypes = [
WidgetConfigurationType.AGGREGATE_CHART,
WidgetConfigurationType.GAUGE_CHART,
WidgetConfigurationType.PIE_CHART,
WidgetConfigurationType.BAR_CHART,
];
@@ -209,7 +208,7 @@ describe('useCreatePageLayoutGraphWidget', () => {
});
});
expect(result.current.allWidgets).toHaveLength(4);
expect(result.current.allWidgets).toHaveLength(3);
widgetConfigurationTypes.forEach((widgetConfigurationType, index) => {
const widget = result.current.allWidgets[index];
@@ -231,12 +230,12 @@ describe('useCreatePageLayoutGraphWidget', () => {
expect(result.current.pageLayoutCurrentLayouts['tab-1']).toBeDefined();
expect(
result.current.pageLayoutCurrentLayouts['tab-1'].desktop,
).toHaveLength(4);
).toHaveLength(3);
expect(
result.current.pageLayoutCurrentLayouts['tab-1'].mobile,
).toHaveLength(4);
).toHaveLength(3);
expect(result.current.pageLayoutDraft.tabs[0].widgets).toHaveLength(4);
expect(result.current.pageLayoutDraft.tabs[0].widgets).toHaveLength(3);
});
it('should throw an error when activeTabId is null', () => {
@@ -10,7 +10,6 @@ import {
TEST_FIELD_METADATA_ID_1,
TEST_FIELD_METADATA_ID_2,
TEST_FIELD_METADATA_ID_3,
TEST_GAUGE_CHART_CONFIGURATION,
TEST_IFRAME_CONFIGURATION,
TEST_LINE_CHART_CONFIGURATION,
TEST_OBJECT_METADATA_ID,
@@ -113,18 +112,6 @@ describe('extractFieldMetadataIdsFromWidget', () => {
expect(result).toContain(TEST_FIELD_METADATA_ID_1);
});
it('should extract field IDs from GaugeChartConfiguration', () => {
const widget = createMockWidget({
configuration: TEST_GAUGE_CHART_CONFIGURATION,
objectMetadataId: TEST_OBJECT_METADATA_ID,
});
const result = extractFieldMetadataIdsFromWidget(widget);
expect(result).toHaveLength(1);
expect(result).toContain(TEST_FIELD_METADATA_ID_1);
});
it('should not include undefined optional fields', () => {
const widget = createMockWidget({
configuration: {
@@ -21,24 +21,6 @@ describe('getWidgetSize', () => {
expect(result).toEqual({ w: 2, h: 2 });
});
it('returns correct default size for GAUGE_CHART', () => {
const result = getWidgetSize(
WidgetConfigurationType.GAUGE_CHART,
'default',
);
expect(result).toEqual({ w: 3, h: 4 });
});
it('returns correct minimum size for GAUGE_CHART', () => {
const result = getWidgetSize(
WidgetConfigurationType.GAUGE_CHART,
'minimum',
);
expect(result).toEqual({ w: 3, h: 4 });
});
it('returns correct default size for PIE_CHART', () => {
const result = getWidgetSize(
WidgetConfigurationType.PIE_CHART,
@@ -3,7 +3,6 @@ import {
TEST_AGGREGATE_CHART_CONFIGURATION,
TEST_BAR_CHART_CONFIGURATION,
TEST_BAR_CHART_CONFIGURATION_HORIZONTAL,
TEST_GAUGE_CHART_CONFIGURATION,
TEST_IFRAME_CONFIGURATION,
TEST_LINE_CHART_CONFIGURATION,
TEST_PIE_CHART_CONFIGURATION,
@@ -17,12 +16,6 @@ describe('getWidgetTitle', () => {
expect(result).toBe('Aggregate Chart 1');
});
it('returns correct title for gauge chart', () => {
const result = getWidgetTitle(TEST_GAUGE_CHART_CONFIGURATION, 2);
expect(result).toBe('Gauge Chart 3');
});
it('returns correct title for pie chart', () => {
const result = getWidgetTitle(TEST_PIE_CHART_CONFIGURATION, 0);
@@ -83,7 +83,6 @@ describe('updateWidgetMinimumSizeForGraphType', () => {
const configurationTypes = [
WidgetConfigurationType.AGGREGATE_CHART,
WidgetConfigurationType.GAUGE_CHART,
WidgetConfigurationType.PIE_CHART,
WidgetConfigurationType.BAR_CHART,
WidgetConfigurationType.LINE_CHART,
@@ -192,7 +191,7 @@ describe('updateWidgetMinimumSizeForGraphType', () => {
(updateLayoutItemConstraints as jest.Mock).mockReturnValue(updatedLayouts);
const result = updateWidgetMinimumSizeForGraphType({
configurationType: WidgetConfigurationType.GAUGE_CHART,
configurationType: WidgetConfigurationType.BAR_CHART,
widgetId: 'widget-1',
tabId: 'tab-1',
currentLayouts: mockLayouts,
@@ -35,9 +35,6 @@ export const extractFieldMetadataIdsFromWidget = (
case 'AggregateChartConfiguration':
return [config.aggregateFieldMetadataId].filter(isDefined);
case 'GaugeChartConfiguration':
return [config.aggregateFieldMetadataId].filter(isDefined);
case 'IframeConfiguration':
return [];
@@ -15,8 +15,6 @@ export const getWidgetTitle = (
switch (configuration.configurationType) {
case WidgetConfigurationType.AGGREGATE_CHART:
return `${t`Aggregate Chart`} ${index + 1}`;
case WidgetConfigurationType.GAUGE_CHART:
return `${t`Gauge Chart`} ${index + 1}`;
case WidgetConfigurationType.PIE_CHART:
return `${t`Pie Chart`} ${index + 1}`;
case WidgetConfigurationType.BAR_CHART:
@@ -76,7 +76,6 @@ const TEST_PERSON_RECORD_ID = 'test-person-456';
// Widget ID constants for stories
const WIDGET_ID_NUMBER_CHART = 'widget-number-chart';
const WIDGET_ID_GAUGE_CHART = 'widget-gauge-chart';
const WIDGET_ID_BAR_CHART = 'widget-bar-chart';
const WIDGET_ID_SMALL = 'widget-small';
const WIDGET_ID_MEDIUM = 'widget-medium';
@@ -338,94 +337,6 @@ export const WithNumberChart: Story = {
},
};
export const WithGaugeChart: Story = {
render: () => {
const widget: PageLayoutWidget = {
__typename: 'PageLayoutWidget',
applicationId: '',
isActive: true,
id: WIDGET_ID_GAUGE_CHART,
pageLayoutTabId: TAB_ID_OVERVIEW,
type: WidgetType.GRAPH,
title: 'Conversion Rate',
objectMetadataId: companyObjectMetadataItem.id,
gridPosition: {
__typename: 'GridPosition',
row: 0,
column: 0,
rowSpan: 5,
columnSpan: 3,
},
configuration: {
__typename: 'GaugeChartConfiguration',
configurationType: WidgetConfigurationType.GAUGE_CHART,
aggregateOperation: AggregateOperations.COUNT,
aggregateFieldMetadataId: idField.id,
displayDataLabel: false,
},
createdAt: '2024-01-01T00:00:00Z',
updatedAt: '2024-01-01T00:00:00Z',
deletedAt: null,
};
setTestObjectMetadataItemsInMetadataStore(
jotaiStore,
getTestEnrichedObjectMetadataItemsMock(),
);
jotaiStore.set(isMinimalMetadataReadyState.atom, true);
const pageLayoutData = createPageLayoutWithWidget(widget);
jotaiStore.set(
pageLayoutPersistedComponentState.atomFamily({
instanceId: PAGE_LAYOUT_TEST_INSTANCE_ID,
}),
pageLayoutData,
);
jotaiStore.set(
pageLayoutDraftComponentState.atomFamily({
instanceId: PAGE_LAYOUT_TEST_INSTANCE_ID,
}),
pageLayoutData,
);
return (
<div style={{ width: '300px', height: '400px' }}>
<JestMetadataAndApolloMocksWrapper>
<CoreClientProviderWrapper>
<PageLayoutTestWrapper store={jotaiStore}>
<LayoutRenderingProvider
value={{
isInSidePanel: false,
layoutType: PageLayoutType.DASHBOARD,
targetRecordIdentifier: {
id: companyObjectMetadataItem.id,
targetObjectNameSingular:
companyObjectMetadataItem.nameSingular,
},
}}
>
<PageLayoutContentProvider
value={{
layoutMode: PageLayoutTabLayoutMode.GRID,
tabId: TAB_ID_OVERVIEW,
}}
>
<WidgetComponentInstanceContext.Provider
value={{
instanceId: WIDGET_ID_GAUGE_CHART,
}}
>
<WidgetRenderer widget={widget} />
</WidgetComponentInstanceContext.Provider>
</PageLayoutContentProvider>
</LayoutRenderingProvider>
</PageLayoutTestWrapper>
</CoreClientProviderWrapper>
</JestMetadataAndApolloMocksWrapper>
</div>
);
},
};
export const WithBarChart: Story = {
render: () => {
const widget: PageLayoutWidget = {
@@ -1,4 +1,3 @@
import { PageLayoutWidgetInvalidConfigDisplay } from '@/page-layout/widgets/components/PageLayoutWidgetInvalidConfigDisplay';
import { GraphWidgetAggregateChartRenderer } from '@/page-layout/widgets/graph/graph-widget-aggregate-chart/components/GraphWidgetAggregateChartRenderer';
import { GraphWidgetBarChartRenderer } from '@/page-layout/widgets/graph/graph-widget-bar-chart/components/GraphWidgetBarChartRenderer';
import { GraphWidgetLineChartRenderer } from '@/page-layout/widgets/graph/graph-widget-line-chart/components/GraphWidgetLineChartRenderer';
@@ -24,9 +23,6 @@ export const GraphWidget = () => {
case WidgetConfigurationType.LINE_CHART:
return <GraphWidgetLineChartRenderer />;
case WidgetConfigurationType.GAUGE_CHART:
return <PageLayoutWidgetInvalidConfigDisplay />;
default:
return null;
}
@@ -1,326 +0,0 @@
import { type Meta, type StoryObj } from '@storybook/react-vite';
import { GraphWidgetTestWrapper } from '@/page-layout/widgets/graph/__tests__/GraphWidgetTestWrapper';
import { GraphWidgetGaugeChart } from '@/page-layout/widgets/graph/graph-widget-gauge-chart/components/GraphWidgetGaugeChart';
import { CatalogDecorator, ComponentDecorator } from 'twenty-ui/testing';
const meta: Meta<typeof GraphWidgetGaugeChart> = {
title: 'Modules/PageLayout/Widgets/GraphWidgetGaugeChart',
component: GraphWidgetGaugeChart,
decorators: [
(Story) => (
<GraphWidgetTestWrapper>
<Story />
</GraphWidgetTestWrapper>
),
ComponentDecorator,
],
parameters: {
layout: 'centered',
},
argTypes: {
data: {
control: 'object',
},
displayType: {
control: 'select',
options: ['percentage', 'number', 'shortNumber', 'currency', 'custom'],
},
prefix: {
control: 'text',
},
suffix: {
control: 'text',
},
decimals: {
control: 'number',
},
showValue: {
control: 'boolean',
},
showLegend: {
control: 'boolean',
},
id: {
control: 'text',
},
},
};
export default meta;
type Story = StoryObj<typeof GraphWidgetGaugeChart>;
const Container = ({ children }: { children: React.ReactNode }) => (
<div style={{ width: '250px', height: '200px' }}>{children}</div>
);
export const WithCustomColors: Story = {
args: {
data: {
value: 75,
min: 0,
max: 100,
color: 'purple',
label: 'Progress',
},
displayType: 'number',
suffix: '%',
showValue: true,
id: 'gauge-chart-purple',
},
render: (args) => (
<Container>
<GraphWidgetGaugeChart
data={args.data}
displayType={args.displayType}
decimals={args.decimals}
prefix={args.prefix}
suffix={args.suffix}
showValue={args.showValue}
showLegend={args.showLegend}
id={args.id}
/>
</Container>
),
};
export const Default: Story = {
args: {
data: {
value: 0.5,
min: 0,
max: 1,
label: 'Conversion rate',
},
displayType: 'percentage',
showValue: true,
id: 'gauge-chart-default',
},
render: (args) => (
<Container>
<GraphWidgetGaugeChart
data={args.data}
displayType={args.displayType}
decimals={args.decimals}
prefix={args.prefix}
suffix={args.suffix}
showValue={args.showValue}
showLegend={args.showLegend}
id={args.id}
/>
</Container>
),
};
export const Catalog: Story = {
decorators: [CatalogDecorator],
parameters: {
catalog: {
dimensions: [
{
name: 'value',
values: [0, 25, 50, 75, 100],
props: (value: number) => ({
data: {
value: value / 100,
min: 0,
max: 1,
label: 'Percentage',
},
displayType: 'percentage' as const,
id: `gauge-chart-catalog-${value}`,
}),
labels: (value: number) => {
const labelMap: Record<number, string> = {
0: 'Empty',
25: 'Quarter',
50: 'Half',
75: 'Three Quarters',
100: 'Full',
};
return labelMap[value] ?? `${value}%`;
},
},
],
},
},
render: (args) => (
<Container>
<GraphWidgetGaugeChart
data={args.data}
displayType={args.displayType}
showValue={true}
id="gauge-chart-catalog"
/>
</Container>
),
};
export const WithoutValue: Story = {
args: {
data: {
value: 65,
min: 0,
max: 100,
label: 'Conversion rate',
},
displayType: 'percentage',
showValue: false,
id: 'gauge-chart-without-value',
},
render: (args) => (
<Container>
<GraphWidgetGaugeChart
data={args.data}
displayType={args.displayType}
decimals={args.decimals}
prefix={args.prefix}
suffix={args.suffix}
showValue={args.showValue}
showLegend={args.showLegend}
id={args.id}
/>
</Container>
),
};
export const Revenue: Story = {
args: {
data: {
value: 750,
min: 0,
max: 1000,
label: 'Revenue',
},
displayType: 'shortNumber',
showValue: true,
id: 'gauge-chart-revenue',
},
render: (args) => (
<Container>
<GraphWidgetGaugeChart
data={args.data}
displayType={args.displayType}
decimals={args.decimals}
prefix={args.prefix}
suffix={args.suffix}
showValue={args.showValue}
showLegend={args.showLegend}
id={args.id}
/>
</Container>
),
};
export const Temperature: Story = {
args: {
data: {
value: 22,
min: -10,
max: 40,
label: 'Temperature',
},
suffix: '°C',
showValue: true,
id: 'gauge-chart-temperature',
},
render: (args) => (
<Container>
<GraphWidgetGaugeChart
data={args.data}
displayType={args.displayType}
decimals={args.decimals}
prefix={args.prefix}
suffix={args.suffix}
showValue={args.showValue}
showLegend={args.showLegend}
id={args.id}
/>
</Container>
),
};
export const Storage: Story = {
args: {
data: {
value: 384,
min: 0,
max: 512,
label: 'Storage Used',
},
suffix: ' GB',
showValue: true,
id: 'gauge-chart-storage',
},
render: (args) => (
<Container>
<GraphWidgetGaugeChart
data={args.data}
displayType={args.displayType}
decimals={args.decimals}
prefix={args.prefix}
suffix={args.suffix}
showValue={args.showValue}
showLegend={args.showLegend}
id={args.id}
/>
</Container>
),
};
export const Rating: Story = {
args: {
data: {
value: 4.2,
min: 0,
max: 5,
label: 'Average Rating',
},
suffix: ' ⭐',
decimals: 1,
showValue: true,
id: 'gauge-chart-rating',
},
render: (args) => (
<Container>
<GraphWidgetGaugeChart
data={args.data}
displayType={args.displayType}
decimals={args.decimals}
prefix={args.prefix}
suffix={args.suffix}
showValue={args.showValue}
showLegend={args.showLegend}
id={args.id}
/>
</Container>
),
};
export const WithoutLegend: Story = {
args: {
data: {
value: 65,
min: 0,
max: 100,
label: 'Conversion rate',
},
displayType: 'percentage',
showValue: true,
id: 'gauge-chart-without-legend',
},
render: (args) => (
<Container>
<GraphWidgetGaugeChart
data={args.data}
displayType={args.displayType}
decimals={args.decimals}
prefix={args.prefix}
suffix={args.suffix}
showValue={args.showValue}
showLegend={false}
id={args.id}
/>
</Container>
),
};
@@ -1,49 +0,0 @@
import { type GraphColorScheme } from '@/page-layout/widgets/graph/types/GraphColorScheme';
import { calculateGaugeChartEndLineCoordinates } from '@/page-layout/widgets/graph/graph-widget-gauge-chart/utils/calculateGaugeChartEndLineCoordinates';
import { type RadialBarCustomLayerProps } from '@nivo/radial-bar';
import { isDefined } from 'twenty-shared/utils';
type GaugeChartEndLineProps = {
center: RadialBarCustomLayerProps['center'];
bars: RadialBarCustomLayerProps['bars'];
clampedNormalizedValue: number;
colorScheme: GraphColorScheme;
};
export const GaugeChartEndLine = ({
center,
bars,
clampedNormalizedValue,
colorScheme,
}: GaugeChartEndLineProps) => {
if (clampedNormalizedValue === 0) {
return null;
}
const valueBar = bars?.find((bar) => bar.data.x === 'value');
if (!isDefined(valueBar)) {
return null;
}
const [centerX, centerY] = center;
const { x1, y1, x2, y2 } = calculateGaugeChartEndLineCoordinates(
valueBar.arc.endAngle,
centerX,
centerY,
valueBar.arc.innerRadius,
valueBar.arc.outerRadius,
);
return (
<g>
<line
x1={x1}
y1={y1}
x2={x2}
y2={y2}
stroke={colorScheme.solid}
strokeWidth={1}
/>
</g>
);
};
@@ -1,163 +0,0 @@
import { CHART_MOTION_CONFIG } from '@/page-layout/widgets/graph/constants/ChartMotionConfig';
import { GraphWidgetLegend } from '@/page-layout/widgets/graph/components/GraphWidgetLegend';
import { GraphWidgetTooltip } from '@/page-layout/widgets/graph/components/GraphWidgetTooltip';
import { GaugeChartEndLine } from '@/page-layout/widgets/graph/graph-widget-gauge-chart/components/GaugeChartEndLine';
import { useGaugeChartData } from '@/page-layout/widgets/graph/graph-widget-gauge-chart/hooks/useGaugeChartData';
import { useGaugeChartTooltip } from '@/page-layout/widgets/graph/graph-widget-gauge-chart/hooks/useGaugeChartTooltip';
import { type GaugeChartData } from '@/page-layout/widgets/graph/graph-widget-gauge-chart/types/GaugeChartData';
import { createGraphColorRegistry } from '@/page-layout/widgets/graph/utils/createGraphColorRegistry';
import {
formatGraphValue,
type GraphValueFormatOptions,
} from '@/page-layout/widgets/graph/utils/graphFormatters';
import { styled } from '@linaria/react';
import { t } from '@lingui/core/macro';
import {
type RadialBarCustomLayerProps,
ResponsiveRadialBar,
} from '@nivo/radial-bar';
import { useContext } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { ThemeContext } from 'twenty-ui/theme-constants';
import { H1Title, H1TitleFontColor } from 'twenty-ui/display';
type GraphWidgetGaugeChartProps = {
data: GaugeChartData;
showValue?: boolean;
showLegend?: boolean;
id: string;
onGaugeClick?: (data: GaugeChartData) => void;
} & GraphValueFormatOptions;
const StyledContainer = styled.div`
align-items: center;
display: flex;
flex-direction: column;
height: 100%;
justify-content: center;
width: 100%;
`;
const StyledChartContainer = styled.div<{ $isClickable?: boolean }>`
flex: 1;
position: relative;
width: 100%;
${({ $isClickable }) =>
$isClickable
? `
svg g path[fill^="url(#"] {
cursor: pointer;
}
`
: ''}
`;
const StyledH1TitleWrapper = styled.div`
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -150%);
`;
export const GraphWidgetGaugeChart = ({
data,
showValue = true,
showLegend = true,
displayType,
decimals,
prefix,
suffix,
customFormatter,
onGaugeClick,
}: GraphWidgetGaugeChartProps) => {
const { theme } = useContext(ThemeContext);
const colorRegistry = createGraphColorRegistry(theme.color);
const formatOptions: GraphValueFormatOptions = {
displayType,
decimals,
prefix,
suffix,
customFormatter,
};
const handleClick = () => {
onGaugeClick?.(data);
};
const hasClickableItems = isDefined(onGaugeClick);
const { colorScheme, normalizedValue, clampedNormalizedValue, chartData } =
useGaugeChartData({
data,
colorRegistry,
});
const { createTooltipData } = useGaugeChartTooltip({
value: data.value,
normalizedValue,
label: data.label || t`Value`,
colorScheme,
formatOptions,
});
const formattedValue = formatGraphValue(data.value, formatOptions);
const renderValueEndLine = (props: RadialBarCustomLayerProps) => (
<GaugeChartEndLine
center={props.center}
bars={props.bars}
clampedNormalizedValue={clampedNormalizedValue}
colorScheme={colorScheme}
/>
);
const renderTooltip = () => {
const tooltipData = createTooltipData();
return <GraphWidgetTooltip items={[tooltipData.tooltipItem]} />;
};
return (
<StyledContainer>
<StyledChartContainer $isClickable={hasClickableItems}>
<ResponsiveRadialBar
data={chartData}
startAngle={-90}
endAngle={90}
innerRadius={0.7}
padding={0.2}
animate
motionConfig={CHART_MOTION_CONFIG}
enableTracks={false}
enableRadialGrid={false}
enableCircularGrid={false}
enableLabels={false}
isInteractive={true}
tooltip={renderTooltip}
onClick={hasClickableItems ? handleClick : undefined}
layers={['bars', renderValueEndLine]}
/>
{showValue && (
<StyledH1TitleWrapper>
<H1Title
title={formattedValue}
fontColor={H1TitleFontColor.Primary}
/>
</StyledH1TitleWrapper>
)}
</StyledChartContainer>
{showLegend && (
<GraphWidgetLegend
show
items={[
{
id: 'gauge',
label: data.label || t`Value`,
color: colorScheme.solid,
},
]}
/>
)}
</StyledContainer>
);
};
@@ -1,216 +0,0 @@
import { type GaugeChartData } from '@/page-layout/widgets/graph/graph-widget-gauge-chart/types/GaugeChartData';
import { type GraphColorRegistry } from '@/page-layout/widgets/graph/types/GraphColorRegistry';
import { renderHook } from '@testing-library/react';
import { useGaugeChartData } from '@/page-layout/widgets/graph/graph-widget-gauge-chart/hooks/useGaugeChartData';
describe('useGaugeChartData', () => {
const mockColorRegistry: GraphColorRegistry = {
blue: {
name: 'blue',
solid: 'blueSolid',
variations: [
'blue1',
'blue2',
'blue3',
'blue4',
'blue5',
'blue6',
'blue7',
'blue8',
'blue9',
'blue10',
'blue11',
'blue12',
],
},
green: {
name: 'green',
solid: 'greenSolid',
variations: [
'green1',
'green2',
'green3',
'green4',
'green5',
'green6',
'green7',
'green8',
'green9',
'green10',
'green11',
'green12',
],
},
};
it('should calculate normalized value correctly', () => {
const data: GaugeChartData = {
value: 75,
min: 0,
max: 100,
};
const { result } = renderHook(() =>
useGaugeChartData({
data,
colorRegistry: mockColorRegistry,
}),
);
expect(result.current.normalizedValue).toBe(75);
expect(result.current.clampedNormalizedValue).toBe(75);
});
it('should handle min and max with non-zero min', () => {
const data: GaugeChartData = {
value: 150,
min: 100,
max: 200,
};
const { result } = renderHook(() =>
useGaugeChartData({
data,
colorRegistry: mockColorRegistry,
}),
);
expect(result.current.normalizedValue).toBe(50);
expect(result.current.clampedNormalizedValue).toBe(50);
});
it('should clamp values above 100', () => {
const data: GaugeChartData = {
value: 150,
min: 0,
max: 100,
};
const { result } = renderHook(() =>
useGaugeChartData({
data,
colorRegistry: mockColorRegistry,
}),
);
expect(result.current.normalizedValue).toBe(150);
expect(result.current.clampedNormalizedValue).toBe(100);
});
it('should clamp values below 0', () => {
const data: GaugeChartData = {
value: -25,
min: 0,
max: 100,
};
const { result } = renderHook(() =>
useGaugeChartData({
data,
colorRegistry: mockColorRegistry,
}),
);
expect(result.current.normalizedValue).toBe(-25);
expect(result.current.clampedNormalizedValue).toBe(0);
});
it('should handle equal min and max', () => {
const data: GaugeChartData = {
value: 50,
min: 100,
max: 100,
};
const { result } = renderHook(() =>
useGaugeChartData({
data,
colorRegistry: mockColorRegistry,
}),
);
expect(result.current.normalizedValue).toBe(0);
expect(result.current.clampedNormalizedValue).toBe(0);
});
it('should use custom color when provided', () => {
const data: GaugeChartData = {
value: 50,
min: 0,
max: 100,
color: 'green',
};
const { result } = renderHook(() =>
useGaugeChartData({
data,
colorRegistry: mockColorRegistry,
}),
);
expect(result.current.colorScheme).toBe(mockColorRegistry.green);
});
it('should default to blue color when not provided', () => {
const data: GaugeChartData = {
value: 50,
min: 0,
max: 100,
};
const { result } = renderHook(() =>
useGaugeChartData({
data,
colorRegistry: mockColorRegistry,
}),
);
expect(result.current.colorScheme).toBe(mockColorRegistry.blue);
});
it('should generate correct chart data structure', () => {
const data: GaugeChartData = {
value: 30,
min: 0,
max: 100,
};
const { result } = renderHook(() =>
useGaugeChartData({
data,
colorRegistry: mockColorRegistry,
}),
);
expect(result.current.chartData).toEqual([
{
id: 'gauge',
data: [
{ x: 'value', y: 30 },
{ x: 'empty', y: 70 },
],
},
]);
});
it('should memoize calculations', () => {
const data: GaugeChartData = {
value: 50,
min: 0,
max: 100,
};
const { result } = renderHook(() =>
useGaugeChartData({
data,
colorRegistry: mockColorRegistry,
}),
);
const firstColorScheme = result.current.colorScheme;
const firstChartData = result.current.chartData;
expect(result.current.colorScheme).toBe(firstColorScheme);
expect(result.current.chartData).toBe(firstChartData);
});
});
@@ -1,55 +0,0 @@
import { type GaugeChartData } from '@/page-layout/widgets/graph/graph-widget-gauge-chart/types/GaugeChartData';
import { type GraphColorRegistry } from '@/page-layout/widgets/graph/types/GraphColorRegistry';
import { getColorScheme } from '@/page-layout/widgets/graph/utils/getColorScheme';
import { useMemo } from 'react';
type UseGaugeChartDataProps = {
data: GaugeChartData;
colorRegistry: GraphColorRegistry;
};
export const useGaugeChartData = ({
data,
colorRegistry,
}: UseGaugeChartDataProps) => {
const { value, min, max, color = 'blue' } = data;
const colorScheme = useMemo(
() =>
getColorScheme({
registry: colorRegistry,
colorName: color,
}),
[colorRegistry, color],
);
const normalizedValue = useMemo(
() => (max === min ? 0 : ((value - min) / (max - min)) * 100),
[value, min, max],
);
const clampedNormalizedValue = useMemo(
() => Math.max(0, Math.min(100, normalizedValue)),
[normalizedValue],
);
const chartData = useMemo(
() => [
{
id: 'gauge',
data: [
{ x: 'value', y: clampedNormalizedValue },
{ x: 'empty', y: 100 - clampedNormalizedValue },
],
},
],
[clampedNormalizedValue],
);
return {
colorScheme,
normalizedValue,
clampedNormalizedValue,
chartData,
};
};
@@ -1,44 +0,0 @@
import { type GraphColorScheme } from '@/page-layout/widgets/graph/types/GraphColorScheme';
import {
formatGraphValue,
type GraphValueFormatOptions,
} from '@/page-layout/widgets/graph/utils/graphFormatters';
type UseGaugeChartTooltipProps = {
value: number;
normalizedValue: number;
label: string;
colorScheme: GraphColorScheme;
formatOptions: GraphValueFormatOptions;
};
export const useGaugeChartTooltip = ({
value,
normalizedValue,
label,
colorScheme,
formatOptions,
}: UseGaugeChartTooltipProps) => {
const createTooltipData = () => {
// Format value based on display type to avoid redundant percentage display
const formattedValue =
formatOptions?.displayType === 'percentage'
? formatGraphValue(normalizedValue / 100, formatOptions)
: `${formatGraphValue(value, formatOptions)} (${normalizedValue.toFixed(1)}%)`;
return {
tooltipItem: {
// TODO: temporary use label as key, ideally key should be unique id -- change when we work on gauge
key: label,
label: label,
formattedValue,
value,
dotColor: colorScheme.solid,
},
};
};
return {
createTooltipData,
};
};
@@ -1,9 +0,0 @@
import { type GraphColor } from '@/page-layout/widgets/graph/types/GraphColor';
export type GaugeChartData = {
value: number;
min: number;
max: number;
color?: GraphColor;
label?: string;
};
@@ -1,168 +0,0 @@
import { calculateGaugeChartEndLineCoordinates } from '@/page-layout/widgets/graph/graph-widget-gauge-chart/utils/calculateGaugeChartEndLineCoordinates';
describe('calculateGaugeChartEndLineCoordinates', () => {
it('should calculate coordinates for angle π/2 (after adjustment points right)', () => {
const result = calculateGaugeChartEndLineCoordinates(
Math.PI / 2,
100,
100,
50,
80,
);
expect(result).toEqual({
x1: 150,
y1: 100,
x2: 180,
y2: 100,
});
});
it('should calculate coordinates for angle π (after adjustment points down)', () => {
const result = calculateGaugeChartEndLineCoordinates(
Math.PI,
100,
100,
50,
80,
);
expect(result).toEqual({
x1: 100,
y1: 150,
x2: 100,
y2: 180,
});
});
it('should calculate coordinates for angle 3π/2 (after adjustment points left)', () => {
const result = calculateGaugeChartEndLineCoordinates(
(3 * Math.PI) / 2,
100,
100,
50,
80,
);
expect(result.x1).toBeCloseTo(50, 5);
expect(result.y1).toBeCloseTo(100, 5);
expect(result.x2).toBeCloseTo(20, 5);
expect(result.y2).toBeCloseTo(100, 5);
});
it('should calculate coordinates for angle 0 (after adjustment points up)', () => {
const result = calculateGaugeChartEndLineCoordinates(0, 100, 100, 50, 80);
expect(result.x1).toBeCloseTo(100, 5);
expect(result.y1).toBeCloseTo(50, 5);
expect(result.x2).toBeCloseTo(100, 5);
expect(result.y2).toBeCloseTo(20, 5);
});
it('should calculate coordinates for 45-degree angle', () => {
const angle = Math.PI / 4;
const result = calculateGaugeChartEndLineCoordinates(
angle,
100,
100,
50,
80,
);
const adjustedAngle = angle - Math.PI / 2;
const expectedCos = Math.cos(adjustedAngle);
const expectedSin = Math.sin(adjustedAngle);
expect(result.x1).toBeCloseTo(100 + expectedCos * 50, 5);
expect(result.y1).toBeCloseTo(100 + expectedSin * 50, 5);
expect(result.x2).toBeCloseTo(100 + expectedCos * 80, 5);
expect(result.y2).toBeCloseTo(100 + expectedSin * 80, 5);
});
it('should handle different center positions', () => {
const result = calculateGaugeChartEndLineCoordinates(
Math.PI,
200,
150,
30,
60,
);
expect(result).toEqual({
x1: 200,
y1: 180,
x2: 200,
y2: 210,
});
});
it('should handle zero radius', () => {
const result = calculateGaugeChartEndLineCoordinates(
Math.PI / 4,
100,
100,
0,
0,
);
expect(result).toEqual({
x1: 100,
y1: 100,
x2: 100,
y2: 100,
});
});
it('should handle negative angles', () => {
const result = calculateGaugeChartEndLineCoordinates(
-Math.PI / 2,
100,
100,
50,
80,
);
expect(result.x1).toBeCloseTo(50, 5);
expect(result.y1).toBeCloseTo(100, 5);
expect(result.x2).toBeCloseTo(20, 5);
expect(result.y2).toBeCloseTo(100, 5);
});
it('should create a line from inner to outer radius', () => {
const angle = Math.PI / 6;
const centerX = 100;
const centerY = 100;
const innerRadius = 40;
const outerRadius = 70;
const result = calculateGaugeChartEndLineCoordinates(
angle,
centerX,
centerY,
innerRadius,
outerRadius,
);
const dist1 = Math.sqrt(
(result.x1 - centerX) ** 2 + (result.y1 - centerY) ** 2,
);
const dist2 = Math.sqrt(
(result.x2 - centerX) ** 2 + (result.y2 - centerY) ** 2,
);
expect(dist1).toBeCloseTo(innerRadius, 5);
expect(dist2).toBeCloseTo(outerRadius, 5);
const angle1 = Math.atan2(result.y1 - centerY, result.x1 - centerX);
const angle2 = Math.atan2(result.y2 - centerY, result.x2 - centerX);
expect(angle1).toBeCloseTo(angle2, 5);
});
it('should handle angles greater than 2π', () => {
const result = calculateGaugeChartEndLineCoordinates(
2.5 * Math.PI,
100,
100,
50,
80,
);
const equivalentResult = calculateGaugeChartEndLineCoordinates(
0.5 * Math.PI,
100,
100,
50,
80,
);
expect(result.x1).toBeCloseTo(equivalentResult.x1, 10);
expect(result.y1).toBeCloseTo(equivalentResult.y1, 10);
expect(result.x2).toBeCloseTo(equivalentResult.x2, 10);
expect(result.y2).toBeCloseTo(equivalentResult.y2, 10);
});
});
@@ -1,16 +0,0 @@
export const calculateGaugeChartEndLineCoordinates = (
endAngle: number,
centerX: number,
centerY: number,
innerRadius: number,
outerRadius: number,
) => {
const adjustedAngle = endAngle - Math.PI / 2;
const x1 = centerX + Math.cos(adjustedAngle) * innerRadius;
const y1 = centerY + Math.sin(adjustedAngle) * innerRadius;
const x2 = centerX + Math.cos(adjustedAngle) * outerRadius;
const y2 = centerY + Math.sin(adjustedAngle) * outerRadius;
return { x1, y1, x2, y2 };
};
@@ -27,8 +27,7 @@ export const hasMinimalRequiredConfigForGraph = (
}
if (
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration') ||
isWidgetConfigurationOfType(configuration, 'GaugeChartConfiguration')
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration')
) {
return isDefined(configuration.aggregateFieldMetadataId);
}
@@ -63,16 +63,12 @@ export const ChartColorSelectionDropdownContent = () => {
const isBarOrLineChart =
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration');
const isGaugeChart = isWidgetConfigurationOfType(
configuration,
'GaugeChartConfiguration',
);
const isPieChart = isWidgetConfigurationOfType(
configuration,
'PieChartConfiguration',
);
if (!isBarOrLineChart && !isGaugeChart && !isPieChart) {
if (!isBarOrLineChart && !isPieChart) {
return null;
}
@@ -67,8 +67,7 @@ const isChartConfiguration = (
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration') ||
isWidgetConfigurationOfType(configuration, 'PieChartConfiguration') ||
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration') ||
isWidgetConfigurationOfType(configuration, 'GaugeChartConfiguration')
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration')
);
};
@@ -1,16 +0,0 @@
import { CHART_SETTINGS_HEADINGS } from '@/side-panel/pages/page-layout/constants/ChartSettingsHeadings';
import { CHART_DATA_SOURCE_SETTING } from '@/side-panel/pages/page-layout/constants/settings/ChartDataSourceSetting';
import { DATA_LABELS_SETTING } from '@/side-panel/pages/page-layout/constants/settings/DataLabelsSetting';
import { FILTER_SETTING } from '@/side-panel/pages/page-layout/constants/settings/FilterSetting';
import { type ChartSettingsGroup } from '@/side-panel/pages/page-layout/types/ChartSettingsGroup';
export const GAUGE_CHART_SETTINGS: ChartSettingsGroup[] = [
{
heading: CHART_SETTINGS_HEADINGS.DATA,
items: [CHART_DATA_SOURCE_SETTING, FILTER_SETTING],
},
{
heading: CHART_SETTINGS_HEADINGS.STYLE,
items: [DATA_LABELS_SETTING],
},
];
@@ -7,5 +7,4 @@ export const GRAPH_CONFIGURATION_TYPE_TO_CONFIG_TYPENAME: Partial<
[WidgetConfigurationType.LINE_CHART]: 'LineChartConfiguration',
[WidgetConfigurationType.PIE_CHART]: 'PieChartConfiguration',
[WidgetConfigurationType.AGGREGATE_CHART]: 'AggregateChartConfiguration',
[WidgetConfigurationType.GAUGE_CHART]: 'GaugeChartConfiguration',
} as const;
@@ -1,5 +1,4 @@
import { AGGREGATE_CHART_SETTINGS } from '@/side-panel/pages/page-layout/constants/AggregateChartSettings';
import { GAUGE_CHART_SETTINGS } from '@/side-panel/pages/page-layout/constants/GaugeChartSettings';
import { LINE_CHART_SETTINGS } from '@/side-panel/pages/page-layout/constants/LineChartSettings';
import { PIE_CHART_SETTINGS } from '@/side-panel/pages/page-layout/constants/PieChartSettings';
import { type ChartSettingsGroup } from '@/side-panel/pages/page-layout/types/ChartSettingsGroup';
@@ -13,7 +12,6 @@ import {
IconChartLine,
IconChartPie,
type IconComponent,
IconGauge,
IconSum,
} from 'twenty-ui/display';
import { BarChartLayout } from '~/generated-metadata/graphql';
@@ -51,9 +49,4 @@ export const GRAPH_TYPE_INFORMATION: Record<
icon: IconSum,
settings: AGGREGATE_CHART_SETTINGS,
},
[GraphType.GAUGE]: {
label: msg`Gauge Chart`,
icon: IconGauge,
settings: GAUGE_CHART_SETTINGS,
},
};
@@ -47,9 +47,7 @@ export const useChartSettingsValues = ({
configuration.__typename === 'LineChartConfiguration';
const hasColorProperty =
isBarOrLineChart ||
configuration.__typename === 'GaugeChartConfiguration' ||
configuration.__typename === 'PieChartConfiguration';
isBarOrLineChart || configuration.__typename === 'PieChartConfiguration';
const isPieChart = configuration.__typename === 'PieChartConfiguration';
@@ -84,7 +84,7 @@ export const useGetConfigToUpdateAfterGraphTypeChange = ({
configurationType: newConfigurationType,
} as Partial<ChartConfiguration>;
if (graphType !== GraphType.AGGREGATE && graphType !== GraphType.GAUGE) {
if (graphType !== GraphType.AGGREGATE) {
const objectMetadataItem = objectMetadataItems.find(
(item) => item.id === widget.objectMetadataId,
);
@@ -1,4 +1,3 @@
import { type TypedGaugeChartConfiguration } from '@/side-panel/pages/page-layout/types/TypedGaugeChartConfiguration';
import { type TypedAggregateChartConfiguration } from './TypedAggregateChartConfiguration';
import { type TypedBarChartConfiguration } from './TypedBarChartConfiguration';
import { type TypedLineChartConfiguration } from './TypedLineChartConfiguration';
@@ -8,5 +7,4 @@ export type ChartConfiguration =
| TypedBarChartConfiguration
| TypedLineChartConfiguration
| TypedPieChartConfiguration
| TypedAggregateChartConfiguration
| TypedGaugeChartConfiguration;
| TypedAggregateChartConfiguration;
@@ -1,12 +1,10 @@
import { type TypedAggregateChartConfiguration } from '@/side-panel/pages/page-layout/types/TypedAggregateChartConfiguration';
import { type TypedBarChartConfiguration } from '@/side-panel/pages/page-layout/types/TypedBarChartConfiguration';
import { type TypedGaugeChartConfiguration } from '@/side-panel/pages/page-layout/types/TypedGaugeChartConfiguration';
import { type TypedLineChartConfiguration } from '@/side-panel/pages/page-layout/types/TypedLineChartConfiguration';
import { type TypedPieChartConfiguration } from '@/side-panel/pages/page-layout/types/TypedPieChartConfiguration';
export type ChartWidgetConfiguration =
| TypedBarChartConfiguration
| TypedGaugeChartConfiguration
| TypedLineChartConfiguration
| TypedAggregateChartConfiguration
| TypedPieChartConfiguration;
@@ -4,5 +4,4 @@ export enum GraphType {
LINE = 'LINE',
PIE = 'PIE',
AGGREGATE = 'AGGREGATE',
GAUGE = 'GAUGE',
}
@@ -1,8 +0,0 @@
import {
type GaugeChartConfiguration,
type WidgetConfigurationType,
} from '~/generated-metadata/graphql';
export type TypedGaugeChartConfiguration = GaugeChartConfiguration & {
configurationType: WidgetConfigurationType.GAUGE_CHART;
};
@@ -33,12 +33,6 @@ describe('getConfigurationTypeFromGraphType', () => {
);
});
it('returns GAUGE_CHART for GAUGE', () => {
expect(getConfigurationTypeFromGraphType(GraphType.GAUGE)).toBe(
WidgetConfigurationType.GAUGE_CHART,
);
});
it('throws for unknown graph type', () => {
const unknownGraphType = 'UNKNOWN' as never;
expect(() => getConfigurationTypeFromGraphType(unknownGraphType)).toThrow();
@@ -5,7 +5,6 @@ import {
TEST_AGGREGATE_CHART_CONFIGURATION,
TEST_BAR_CHART_CONFIGURATION,
TEST_BAR_CHART_CONFIGURATION_HORIZONTAL,
TEST_GAUGE_CHART_CONFIGURATION,
TEST_LINE_CHART_CONFIGURATION,
TEST_PIE_CHART_CONFIGURATION,
} from '~/testing/mock-data/widget-configurations';
@@ -51,14 +50,6 @@ describe('getCurrentGraphTypeFromConfig', () => {
).toBe(GraphType.AGGREGATE);
});
it('returns GAUGE for gauge chart', () => {
expect(
getCurrentGraphTypeFromConfig(
TEST_GAUGE_CHART_CONFIGURATION as ChartConfiguration,
),
).toBe(GraphType.GAUGE);
});
it('throws for unknown configuration type', () => {
const unknownConfig = {
__typename: 'UnknownConfiguration',
@@ -15,7 +15,6 @@ const VALID_CHART_TYPES: ReadonlyArray<ChartConfiguration['__typename']> = [
'LineChartConfiguration',
'PieChartConfiguration',
'AggregateChartConfiguration',
'GaugeChartConfiguration',
] as const;
export const assertChartWidgetOrThrow: AssertChartWidgetOrThrow = (
@@ -15,8 +15,6 @@ export const getConfigurationTypeFromGraphType = (
return WidgetConfigurationType.PIE_CHART;
case GraphType.AGGREGATE:
return WidgetConfigurationType.AGGREGATE_CHART;
case GraphType.GAUGE:
return WidgetConfigurationType.GAUGE_CHART;
default:
assertUnreachable(graphType);
}
@@ -27,9 +27,5 @@ export const getCurrentGraphTypeFromConfig = (
return GraphType.AGGREGATE;
}
if (isWidgetConfigurationOfType(configuration, 'GaugeChartConfiguration')) {
return GraphType.GAUGE;
}
throw new Error(t`Unknown chart configuration type`);
};
@@ -9,7 +9,6 @@ import {
type FieldsConfiguration,
type FilesConfiguration,
type FrontComponentConfiguration,
type GaugeChartConfiguration,
type IframeConfiguration,
type LineChartConfiguration,
type NotesConfiguration,
@@ -69,12 +68,6 @@ type WidgetConfigurationTypenameMap = {
FilesConfiguration: Omit<FilesConfiguration, 'configurationType'> & {
configurationType: WidgetConfigurationType.FILES;
};
GaugeChartConfiguration: Omit<
GaugeChartConfiguration,
'configurationType'
> & {
configurationType: WidgetConfigurationType.GAUGE_CHART;
};
IframeConfiguration: Omit<IframeConfiguration, 'configurationType'> & {
configurationType: WidgetConfigurationType.IFRAME;
};
@@ -18,7 +18,6 @@ export const isWidgetConfigurationOfTypeGraph = (
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration') ||
isWidgetConfigurationOfType(configuration, 'PieChartConfiguration') ||
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration') ||
isWidgetConfigurationOfType(configuration, 'GaugeChartConfiguration')
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration')
);
};
@@ -1,6 +1,5 @@
import { type TypedAggregateChartConfiguration } from '@/side-panel/pages/page-layout/types/TypedAggregateChartConfiguration';
import { type TypedBarChartConfiguration } from '@/side-panel/pages/page-layout/types/TypedBarChartConfiguration';
import { type TypedGaugeChartConfiguration } from '@/side-panel/pages/page-layout/types/TypedGaugeChartConfiguration';
import { type TypedLineChartConfiguration } from '@/side-panel/pages/page-layout/types/TypedLineChartConfiguration';
import { type TypedPieChartConfiguration } from '@/side-panel/pages/page-layout/types/TypedPieChartConfiguration';
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
@@ -77,14 +76,6 @@ export const TEST_AGGREGATE_CHART_CONFIGURATION: TypedAggregateChartConfiguratio
displayDataLabel: false,
};
export const TEST_GAUGE_CHART_CONFIGURATION: TypedGaugeChartConfiguration = {
__typename: 'GaugeChartConfiguration',
configurationType: WidgetConfigurationType.GAUGE_CHART,
aggregateFieldMetadataId: TEST_FIELD_METADATA_ID_1,
aggregateOperation: AggregateOperations.SUM,
displayDataLabel: false,
};
export const TEST_IFRAME_CONFIGURATION: IframeConfiguration = {
__typename: 'IframeConfiguration',
configurationType: WidgetConfigurationType.IFRAME,
@@ -109,7 +100,6 @@ export const ALL_CHART_CONFIGURATIONS: WidgetConfiguration[] = [
TEST_LINE_CHART_CONFIGURATION,
TEST_PIE_CHART_CONFIGURATION,
TEST_AGGREGATE_CHART_CONFIGURATION,
TEST_GAUGE_CHART_CONFIGURATION,
];
export const ALL_NON_CHART_CONFIGURATIONS = [
@@ -6,7 +6,6 @@ import { WorkspaceIteratorService } from 'src/database/commands/command-runners/
import { type RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspace.command-runner';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { RegisteredWorkspaceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-workspace-command.decorator';
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service';
@@ -59,8 +58,8 @@ export class DeleteGaugeWidgetsCommand extends ActiveOrSuspendedWorkspaceCommand
const gaugeWidgets = widgets.filter(
(widget) =>
widget.universalConfiguration?.configurationType ===
WidgetConfigurationType.GAUGE_CHART,
(widget.universalConfiguration?.configurationType as string) ===
'GAUGE_CHART',
);
if (gaugeWidgets.length === 0) {
@@ -126,27 +126,6 @@ export const fromPageLayoutWidgetConfigurationToUniversalConfiguration = ({
};
}
case WidgetConfigurationType.GAUGE_CHART: {
const { aggregateFieldMetadataId, filter, ...rest } = configuration;
const aggregateFieldMetadataUniversalIdentifier =
getFieldMetadataUniversalIdentifier({
fieldMetadataId: aggregateFieldMetadataId,
fieldMetadataUniversalIdentifierById,
shouldThrowOnMissingIdentifier,
});
return {
...rest,
aggregateFieldMetadataUniversalIdentifier,
filter: convertChartFilterToUniversalFilter({
filter,
fieldMetadataUniversalIdentifierById,
shouldThrowOnMissingIdentifier,
}),
};
}
case WidgetConfigurationType.PIE_CHART: {
const {
aggregateFieldMetadataId,
@@ -5,5 +5,4 @@ export const VALID_GRAPH_CONFIGURATION_TYPES = [
WidgetConfigurationType.BAR_CHART,
WidgetConfigurationType.LINE_CHART,
WidgetConfigurationType.PIE_CHART,
WidgetConfigurationType.GAUGE_CHART,
] as const;
@@ -1,6 +1,5 @@
import { type AggregateChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/aggregate-chart-configuration.dto';
import { type BarChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/bar-chart-configuration.dto';
import { type GaugeChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/gauge-chart-configuration.dto';
import { type LineChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/line-chart-configuration.dto';
import { type PieChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/pie-chart-configuration.dto';
@@ -8,5 +7,4 @@ export type GraphConfiguration =
| BarChartConfigurationDTO
| LineChartConfigurationDTO
| PieChartConfigurationDTO
| AggregateChartConfigurationDTO
| GaugeChartConfigurationDTO;
| AggregateChartConfigurationDTO;
@@ -34,7 +34,6 @@ export const validateGraphConfigurationByType = ({
widgetTitle,
});
case WidgetConfigurationType.AGGREGATE_CHART:
case WidgetConfigurationType.GAUGE_CHART:
return [];
default:
return [];
@@ -8,7 +8,6 @@ import { FieldRichTextConfigurationDTO } from 'src/engine/metadata-modules/page-
import { FieldsConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/fields-configuration.dto';
import { FilesConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/files-configuration.dto';
import { FrontComponentConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/front-component-configuration.dto';
import { GaugeChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/gauge-chart-configuration.dto';
import { IframeConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/iframe-configuration.dto';
import { LineChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/line-chart-configuration.dto';
import { NotesConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/notes-configuration.dto';
@@ -31,7 +30,6 @@ export const ALL_WIDGET_CONFIGURATION_TYPE_VALIDATOR_BY_WIDGET_CONFIGURATION_TYP
PIE_CHART: PieChartConfigurationDTO,
LINE_CHART: LineChartConfigurationDTO,
IFRAME: IframeConfigurationDTO,
GAUGE_CHART: GaugeChartConfigurationDTO,
BAR_CHART: BarChartConfigurationDTO,
CALENDAR: CalendarConfigurationDTO,
FRONT_COMPONENT: FrontComponentConfigurationDTO,
@@ -3,7 +3,6 @@ import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout
export const GRAPH_CONFIGURATION_TYPES = new Set<WidgetConfigurationType>([
WidgetConfigurationType.AGGREGATE_CHART,
WidgetConfigurationType.BAR_CHART,
WidgetConfigurationType.GAUGE_CHART,
WidgetConfigurationType.LINE_CHART,
WidgetConfigurationType.PIE_CHART,
]);
@@ -1,75 +0,0 @@
import { Field, Int, ObjectType } from '@nestjs/graphql';
import {
IsBoolean,
IsEnum,
IsIn,
IsNotEmpty,
IsObject,
IsOptional,
IsString,
IsTimeZone,
IsUUID,
Max,
Min,
} from 'class-validator';
import { GraphQLJSON } from 'graphql-type-json';
import { CalendarStartDay } from 'twenty-shared/constants';
import {
AggregateOperations,
type ChartFilter,
type GaugeChartConfiguration,
SerializedRelation,
} from 'twenty-shared/types';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
@ObjectType('GaugeChartConfiguration')
export class GaugeChartConfigurationDTO implements GaugeChartConfiguration {
@Field(() => WidgetConfigurationType)
@IsIn([WidgetConfigurationType.GAUGE_CHART])
@IsNotEmpty()
configurationType: WidgetConfigurationType.GAUGE_CHART;
@Field(() => UUIDScalarType)
@IsUUID()
@IsNotEmpty()
aggregateFieldMetadataId: SerializedRelation;
@Field(() => AggregateOperations)
@IsEnum(AggregateOperations)
@IsNotEmpty()
aggregateOperation: AggregateOperations;
@Field(() => Boolean, { nullable: true, defaultValue: false })
@IsBoolean()
@IsOptional()
displayDataLabel?: boolean;
@Field(() => String, { nullable: true })
@IsString()
@IsOptional()
color?: string;
@Field(() => String, { nullable: true })
@IsString()
@IsOptional()
description?: string;
@Field(() => GraphQLJSON, { nullable: true })
@IsObject()
@IsOptional()
filter?: ChartFilter;
@Field(() => String, { nullable: true, defaultValue: 'UTC' })
@IsTimeZone()
@IsOptional()
timezone?: string;
@Field(() => Int, { nullable: true, defaultValue: CalendarStartDay.MONDAY })
@IsOptional()
@Min(0)
@Max(7)
firstDayOfTheWeek?: number;
}
@@ -2,7 +2,6 @@ import { registerEnumType } from '@nestjs/graphql';
export enum GraphType {
AGGREGATE_CHART = 'AGGREGATE_CHART',
GAUGE_CHART = 'GAUGE_CHART',
PIE_CHART = 'PIE_CHART',
BAR_CHART = 'BAR_CHART',
LINE_CHART = 'LINE_CHART',
@@ -6,7 +6,6 @@ import { GraphType } from 'src/engine/metadata-modules/page-layout-widget/enums/
export enum WidgetConfigurationType {
AGGREGATE_CHART = GraphType.AGGREGATE_CHART,
GAUGE_CHART = GraphType.GAUGE_CHART,
PIE_CHART = GraphType.PIE_CHART,
BAR_CHART = GraphType.BAR_CHART,
LINE_CHART = GraphType.LINE_CHART,
@@ -31,7 +30,6 @@ export enum WidgetConfigurationType {
}
export type AllGraphWidgetConfigurationType =
| WidgetConfigurationType.AGGREGATE_CHART
| WidgetConfigurationType.GAUGE_CHART
| WidgetConfigurationType.PIE_CHART
| WidgetConfigurationType.BAR_CHART
| WidgetConfigurationType.LINE_CHART;
@@ -1,12 +1,10 @@
import { type AggregateChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/aggregate-chart-configuration.dto';
import { type BarChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/bar-chart-configuration.dto';
import { type GaugeChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/gauge-chart-configuration.dto';
import { type LineChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/line-chart-configuration.dto';
import { type PieChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/pie-chart-configuration.dto';
export type ChartReferencingFieldInConfiguration =
| AggregateChartConfigurationDTO
| BarChartConfigurationDTO
| GaugeChartConfigurationDTO
| LineChartConfigurationDTO
| PieChartConfigurationDTO;
@@ -7,7 +7,6 @@ import {
INVALID_STANDALONE_RICH_TEXT_CONFIG_BODY_WRONG_TYPE,
INVALID_STANDALONE_RICH_TEXT_CONFIG_MISSING_BODY,
INVALID_VERTICAL_BAR_CHART_CONFIG_MISSING_GROUP_BY,
TEST_GAUGE_CHART_CONFIG,
TEST_HORIZONTAL_BAR_CHART_CONFIG,
TEST_HORIZONTAL_BAR_CHART_CONFIG_MINIMAL,
TEST_IFRAME_CONFIG,
@@ -206,16 +205,6 @@ describe('validateWidgetConfigurationInput', () => {
).not.toThrow();
});
});
describe('GAUGE_CHART graph', () => {
it('should not throw for gauge chart configuration', () => {
expect(() =>
validateWidgetConfigurationInput({
configuration: TEST_GAUGE_CHART_CONFIG,
}),
).not.toThrow();
});
});
});
describe('Edge cases', () => {
@@ -4,7 +4,6 @@ import { AggregateChartConfigurationDTO } from 'src/engine/metadata-modules/page
import { BarChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/bar-chart-configuration.dto';
import { FieldConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/field-configuration.dto';
import { FrontComponentConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/front-component-configuration.dto';
import { GaugeChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/gauge-chart-configuration.dto';
import { IframeConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/iframe-configuration.dto';
import { LineChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/line-chart-configuration.dto';
import { PieChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/pie-chart-configuration.dto';
@@ -98,12 +97,6 @@ export const validateWidgetConfigurationInput = ({
configuration,
);
break;
case WidgetConfigurationType.GAUGE_CHART:
errors = validateWidgetConfigurationByDto(
GaugeChartConfigurationDTO,
configuration,
);
break;
case WidgetConfigurationType.IFRAME:
errors = validateWidgetConfigurationByDto(
IframeConfigurationDTO,
@@ -117,26 +117,6 @@ export const fromUniversalConfigurationToFlatPageLayoutWidgetConfiguration = ({
};
}
case WidgetConfigurationType.GAUGE_CHART: {
const { aggregateFieldMetadataUniversalIdentifier, filter, ...rest } =
universalConfiguration;
const aggregateFieldMetadataId = resolveFieldMetadataIdOrThrow({
fieldMetadataUniversalIdentifier:
aggregateFieldMetadataUniversalIdentifier,
flatFieldMetadataMaps,
});
return {
...rest,
aggregateFieldMetadataId,
filter: convertUniversalFilterToChartFilter({
filter,
flatFieldMetadataMaps,
}),
};
}
case WidgetConfigurationType.PIE_CHART: {
const {
aggregateFieldMetadataUniversalIdentifier,
@@ -2,7 +2,6 @@ import { AggregateOperations } from 'twenty-shared/types';
import { type AggregateChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/aggregate-chart-configuration.dto';
import { type BarChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/bar-chart-configuration.dto';
import { type GaugeChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/gauge-chart-configuration.dto';
import { type IframeConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/iframe-configuration.dto';
import { type LineChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/line-chart-configuration.dto';
import { type PieChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/pie-chart-configuration.dto';
@@ -220,18 +219,3 @@ export const TEST_PIE_CHART_CONFIG_MINIMAL: PieChartConfigurationDTO = {
orderBy: GraphOrderBy.FIELD_ASC,
displayDataLabel: false,
};
export const TEST_GAUGE_CHART_CONFIG: GaugeChartConfigurationDTO = {
configurationType: WidgetConfigurationType.GAUGE_CHART,
aggregateFieldMetadataId: UNIT_TEST_FIELD_METADATA_ID_1,
aggregateOperation: AggregateOperations.SUM,
description: 'Completion percentage',
displayDataLabel: true,
};
export const TEST_GAUGE_CHART_CONFIG_MINIMAL: GaugeChartConfigurationDTO = {
configurationType: WidgetConfigurationType.GAUGE_CHART,
aggregateFieldMetadataId: UNIT_TEST_FIELD_METADATA_ID_1,
aggregateOperation: AggregateOperations.COUNT_TRUE,
displayDataLabel: false,
};
@@ -66,66 +66,6 @@ exports[`Page layout widget creation should succeed should create a page layout
}
`;
exports[`Page layout widget creation should succeed should create a page layout widget with GAUGE_CHART full configuration 1`] = `
{
"configuration": {
"aggregateFieldMetadataId": Any<String>,
"aggregateOperation": "SUM",
"color": null,
"configurationType": "GAUGE_CHART",
"description": "Completion percentage",
"displayDataLabel": true,
"filter": null,
"firstDayOfTheWeek": 1,
"timezone": "UTC",
},
"createdAt": Any<String>,
"deletedAt": null,
"gridPosition": {
"column": 0,
"columnSpan": 1,
"row": 0,
"rowSpan": 1,
},
"id": Any<String>,
"objectMetadataId": Any<String>,
"pageLayoutTabId": Any<String>,
"title": "Gauge Chart Widget",
"type": "GRAPH",
"updatedAt": Any<String>,
}
`;
exports[`Page layout widget creation should succeed should create a page layout widget with GAUGE_CHART minimal configuration 1`] = `
{
"configuration": {
"aggregateFieldMetadataId": Any<String>,
"aggregateOperation": "COUNT_TRUE",
"color": null,
"configurationType": "GAUGE_CHART",
"description": null,
"displayDataLabel": false,
"filter": null,
"firstDayOfTheWeek": 1,
"timezone": "UTC",
},
"createdAt": Any<String>,
"deletedAt": null,
"gridPosition": {
"column": 0,
"columnSpan": 1,
"row": 0,
"rowSpan": 1,
},
"id": Any<String>,
"objectMetadataId": Any<String>,
"pageLayoutTabId": Any<String>,
"title": "Gauge Chart Widget Minimal",
"type": "GRAPH",
"updatedAt": Any<String>,
}
`;
exports[`Page layout widget creation should succeed should create a page layout widget with HORIZONTAL BAR_CHART full configuration 1`] = `
{
"configuration": {
@@ -33,36 +33,6 @@ exports[`Page layout widget update should succeed from a GRAPH widget should upd
}
`;
exports[`Page layout widget update should succeed from a GRAPH widget should update page layout widget to GAUGE_CHART configuration 1`] = `
{
"configuration": {
"aggregateFieldMetadataId": Any<String>,
"aggregateOperation": "SUM",
"color": null,
"configurationType": "GAUGE_CHART",
"description": "Completion percentage",
"displayDataLabel": true,
"filter": null,
"firstDayOfTheWeek": 1,
"timezone": "UTC",
},
"createdAt": Any<String>,
"deletedAt": null,
"gridPosition": {
"column": 0,
"columnSpan": 1,
"row": 0,
"rowSpan": 1,
},
"id": Any<String>,
"objectMetadataId": Any<String>,
"pageLayoutTabId": Any<String>,
"title": "Original Graph Widget",
"type": "GRAPH",
"updatedAt": Any<String>,
}
`;
exports[`Page layout widget update should succeed from a GRAPH widget should update page layout widget to HORIZONTAL BAR_CHART configuration 1`] = `
{
"configuration": {
@@ -88,17 +88,6 @@ export const WIDGET_CONFIGURATION_GQL_FIELDS = `
timezone
firstDayOfTheWeek
}
... on GaugeChartConfiguration {
configurationType
aggregateFieldMetadataId
aggregateOperation
displayDataLabel
color
description
filter
timezone
firstDayOfTheWeek
}
... on IframeConfiguration {
configurationType
url
@@ -293,32 +293,6 @@ describe('Page layout widget creation should succeed', () => {
}),
},
},
{
title: 'create a page layout widget with GAUGE_CHART full configuration',
context: {
widgetTitle: 'Gauge Chart Widget',
buildConfiguration: () => ({
configurationType: WidgetConfigurationType.GAUGE_CHART,
aggregateFieldMetadataId: testSetup.fieldMetadataId1,
aggregateOperation: AggregateOperations.SUM,
description: 'Completion percentage',
displayDataLabel: true,
}),
},
},
{
title:
'create a page layout widget with GAUGE_CHART minimal configuration',
context: {
widgetTitle: 'Gauge Chart Widget Minimal',
buildConfiguration: () => ({
configurationType: WidgetConfigurationType.GAUGE_CHART,
aggregateFieldMetadataId: testSetup.fieldMetadataId1,
aggregateOperation: AggregateOperations.COUNT_TRUE,
displayDataLabel: false,
}),
},
},
];
beforeAll(async () => {
@@ -316,18 +316,6 @@ describe('Page layout widget update should succeed', () => {
}),
},
},
{
title: 'update page layout widget to GAUGE_CHART configuration',
context: {
buildConfiguration: () => ({
configurationType: WidgetConfigurationType.GAUGE_CHART,
aggregateFieldMetadataId: testSetup.fieldMetadataId1,
aggregateOperation: AggregateOperations.SUM,
description: 'Completion percentage',
displayDataLabel: true,
}),
},
},
];
beforeEach(async () => {
@@ -173,7 +173,6 @@ export type {
export type { GridPosition } from './page-layout/grid-position.type';
export type {
AggregateChartConfiguration,
GaugeChartConfiguration,
PieChartConfiguration,
BarChartConfiguration,
LineChartConfiguration,
@@ -25,10 +25,6 @@ export type AggregateChartConfiguration = BaseChartConfiguration & {
ratioAggregateConfig?: RatioAggregateConfig;
};
export type GaugeChartConfiguration = BaseChartConfiguration & {
configurationType: 'GAUGE_CHART';
};
export type PieChartConfiguration = BaseChartConfiguration & {
configurationType: 'PIE_CHART';
groupByFieldMetadataId: SerializedRelation;
@@ -174,7 +170,6 @@ export type WorkflowRunConfiguration = {
export type PageLayoutWidgetConfiguration =
| AggregateChartConfiguration
| GaugeChartConfiguration
| PieChartConfiguration
| BarChartConfiguration
| LineChartConfiguration
@@ -18,7 +18,7 @@ export const FEATURE_TILES: FeatureTileType[] = [
bullets: [
{
icon: 'check',
text: msg`Aggregate, bar, line, pie, and gauge widgets`,
text: msg`Aggregate, bar, line, and pie widgets`,
},
{ icon: 'search', text: msg`Filtered metrics from any object` },
{ icon: 'check', text: msg`Real-time data` },