[Dashboards] Remove gauge chart types and code (#20410)
Follow-up cleanup to #20172.
This commit is contained in:
@@ -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
-28
@@ -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 },
|
||||
|
||||
-11
@@ -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
|
||||
|
||||
+4
-5
@@ -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', () => {
|
||||
|
||||
-13
@@ -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);
|
||||
|
||||
|
||||
+1
-2
@@ -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,
|
||||
|
||||
-3
@@ -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:
|
||||
|
||||
-89
@@ -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;
|
||||
}
|
||||
|
||||
-326
@@ -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>
|
||||
),
|
||||
};
|
||||
-49
@@ -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>
|
||||
);
|
||||
};
|
||||
-163
@@ -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>
|
||||
);
|
||||
};
|
||||
-216
@@ -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);
|
||||
});
|
||||
});
|
||||
-55
@@ -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,
|
||||
};
|
||||
};
|
||||
-44
@@ -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,
|
||||
};
|
||||
};
|
||||
-9
@@ -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;
|
||||
};
|
||||
-168
@@ -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);
|
||||
});
|
||||
});
|
||||
-16
@@ -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 };
|
||||
};
|
||||
+1
-2
@@ -27,8 +27,7 @@ export const hasMinimalRequiredConfigForGraph = (
|
||||
}
|
||||
|
||||
if (
|
||||
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'GaugeChartConfiguration')
|
||||
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration')
|
||||
) {
|
||||
return isDefined(configuration.aggregateFieldMetadataId);
|
||||
}
|
||||
|
||||
+1
-5
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -67,8 +67,7 @@ const isChartConfiguration = (
|
||||
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'PieChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'GaugeChartConfiguration')
|
||||
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration')
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
-16
@@ -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],
|
||||
},
|
||||
];
|
||||
-1
@@ -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;
|
||||
|
||||
-7
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
+1
-3
@@ -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';
|
||||
|
||||
|
||||
+1
-1
@@ -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
-3
@@ -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;
|
||||
|
||||
-2
@@ -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',
|
||||
}
|
||||
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
import {
|
||||
type GaugeChartConfiguration,
|
||||
type WidgetConfigurationType,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export type TypedGaugeChartConfiguration = GaugeChartConfiguration & {
|
||||
configurationType: WidgetConfigurationType.GAUGE_CHART;
|
||||
};
|
||||
-6
@@ -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();
|
||||
|
||||
-9
@@ -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',
|
||||
|
||||
-1
@@ -15,7 +15,6 @@ const VALID_CHART_TYPES: ReadonlyArray<ChartConfiguration['__typename']> = [
|
||||
'LineChartConfiguration',
|
||||
'PieChartConfiguration',
|
||||
'AggregateChartConfiguration',
|
||||
'GaugeChartConfiguration',
|
||||
] as const;
|
||||
|
||||
export const assertChartWidgetOrThrow: AssertChartWidgetOrThrow = (
|
||||
|
||||
-2
@@ -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);
|
||||
}
|
||||
|
||||
-4
@@ -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`);
|
||||
};
|
||||
|
||||
-7
@@ -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;
|
||||
};
|
||||
|
||||
+1
-2
@@ -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 = [
|
||||
|
||||
+2
-3
@@ -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) {
|
||||
|
||||
-21
@@ -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,
|
||||
|
||||
-1
@@ -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
-3
@@ -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;
|
||||
|
||||
-1
@@ -34,7 +34,6 @@ export const validateGraphConfigurationByType = ({
|
||||
widgetTitle,
|
||||
});
|
||||
case WidgetConfigurationType.AGGREGATE_CHART:
|
||||
case WidgetConfigurationType.GAUGE_CHART:
|
||||
return [];
|
||||
default:
|
||||
return [];
|
||||
|
||||
-2
@@ -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,
|
||||
|
||||
-1
@@ -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,
|
||||
]);
|
||||
|
||||
-75
@@ -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;
|
||||
}
|
||||
-1
@@ -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',
|
||||
|
||||
-2
@@ -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;
|
||||
|
||||
-2
@@ -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;
|
||||
|
||||
-11
@@ -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', () => {
|
||||
|
||||
-7
@@ -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,
|
||||
|
||||
-20
@@ -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,
|
||||
|
||||
-16
@@ -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,
|
||||
};
|
||||
|
||||
-60
@@ -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": {
|
||||
|
||||
-30
@@ -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": {
|
||||
|
||||
-11
@@ -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
|
||||
|
||||
-26
@@ -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 () => {
|
||||
|
||||
-12
@@ -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` },
|
||||
|
||||
Reference in New Issue
Block a user