[DASHBOARDS] Add split multi-value fields setting for charts (#17907)
closes https://github.com/twentyhq/twenty/issues/17890 https://github.com/user-attachments/assets/dbf2ebe6-c2da-44d0-846e-d7fa9fac5f43
This commit is contained in:
+4
@@ -16,6 +16,8 @@ import { RANGE_MAX_SETTING } from '@/command-menu/pages/page-layout/constants/se
|
||||
import { RANGE_MIN_SETTING } from '@/command-menu/pages/page-layout/constants/settings/RangeMinSetting';
|
||||
import { SHOW_LEGEND_SETTING } from '@/command-menu/pages/page-layout/constants/settings/ShowLegendSetting';
|
||||
import { SORT_BY_GROUP_BY_FIELD_SETTING } from '@/command-menu/pages/page-layout/constants/settings/SortByGroupByFieldSetting';
|
||||
import { SPLIT_MULTI_VALUE_FIELDS_X_SETTING } from '@/command-menu/pages/page-layout/constants/settings/SplitMultiValueFieldsXSetting';
|
||||
import { SPLIT_MULTI_VALUE_FIELDS_Y_SETTING } from '@/command-menu/pages/page-layout/constants/settings/SplitMultiValueFieldsYSetting';
|
||||
import { STACKED_LINES_SETTING } from '@/command-menu/pages/page-layout/constants/settings/StackedLineSettings';
|
||||
import { type ChartSettingsGroup } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||
|
||||
@@ -31,6 +33,7 @@ export const LINE_CHART_SETTINGS: ChartSettingsGroup[] = [
|
||||
DATE_GRANULARITY_X_SETTING,
|
||||
PRIMARY_SORT_BY_SETTING,
|
||||
OMIT_NULL_VALUES_SETTING,
|
||||
SPLIT_MULTI_VALUE_FIELDS_X_SETTING,
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -43,6 +46,7 @@ export const LINE_CHART_SETTINGS: ChartSettingsGroup[] = [
|
||||
CUMULATIVE_SETTING,
|
||||
RANGE_MIN_SETTING,
|
||||
RANGE_MAX_SETTING,
|
||||
SPLIT_MULTI_VALUE_FIELDS_Y_SETTING,
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
+2
@@ -10,6 +10,7 @@ import { FILTER_SETTING } from '@/command-menu/pages/page-layout/constants/setti
|
||||
import { HIDE_EMPTY_CATEGORY_SETTING } from '@/command-menu/pages/page-layout/constants/settings/HideEmptyCategorySetting';
|
||||
import { PRIMARY_SORT_BY_SETTING } from '@/command-menu/pages/page-layout/constants/settings/PrimarySortBySetting';
|
||||
import { SHOW_LEGEND_SETTING } from '@/command-menu/pages/page-layout/constants/settings/ShowLegendSetting';
|
||||
import { SPLIT_MULTI_VALUE_FIELDS_X_SETTING } from '@/command-menu/pages/page-layout/constants/settings/SplitMultiValueFieldsXSetting';
|
||||
import { type ChartSettingsGroup } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||
|
||||
export const PIE_CHART_SETTINGS: ChartSettingsGroup[] = [
|
||||
@@ -23,6 +24,7 @@ export const PIE_CHART_SETTINGS: ChartSettingsGroup[] = [
|
||||
EACH_SLICE_REPRESENTS_SETTING,
|
||||
PRIMARY_SORT_BY_SETTING,
|
||||
HIDE_EMPTY_CATEGORY_SETTING,
|
||||
SPLIT_MULTI_VALUE_FIELDS_X_SETTING,
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
+2
@@ -28,4 +28,6 @@ export const CHART_CONFIGURATION_SETTING_LABELS = {
|
||||
PREFIX: msg`Prefix`,
|
||||
SUFFIX: msg`Suffix`,
|
||||
CUMULATIVE: msg`Cumulative`,
|
||||
SPLIT_MULTI_VALUE_FIELDS_X: msg`Split multiple values`,
|
||||
SPLIT_MULTI_VALUE_FIELDS_Y: msg`Split multiple values`,
|
||||
};
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||
import { IconArrowsSplit2 } from 'twenty-ui/display';
|
||||
|
||||
export const SPLIT_MULTI_VALUE_FIELDS_X_SETTING: ChartSettingsItem = {
|
||||
isBoolean: true,
|
||||
Icon: IconArrowsSplit2,
|
||||
label: CHART_CONFIGURATION_SETTING_LABELS.SPLIT_MULTI_VALUE_FIELDS_X,
|
||||
id: CHART_CONFIGURATION_SETTING_IDS.SPLIT_MULTI_VALUE_FIELDS_X,
|
||||
};
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||
import { IconArrowsSplit2 } from 'twenty-ui/display';
|
||||
|
||||
export const SPLIT_MULTI_VALUE_FIELDS_Y_SETTING: ChartSettingsItem = {
|
||||
isBoolean: true,
|
||||
Icon: IconArrowsSplit2,
|
||||
label: CHART_CONFIGURATION_SETTING_LABELS.SPLIT_MULTI_VALUE_FIELDS_Y,
|
||||
id: CHART_CONFIGURATION_SETTING_IDS.SPLIT_MULTI_VALUE_FIELDS_Y,
|
||||
};
|
||||
+5
@@ -257,6 +257,11 @@ export const useChartSettingsValues = ({
|
||||
return isBarOrLineChart
|
||||
? (configuration.omitNullValues ?? false)
|
||||
: false;
|
||||
case CHART_CONFIGURATION_SETTING_IDS.SPLIT_MULTI_VALUE_FIELDS_X:
|
||||
case CHART_CONFIGURATION_SETTING_IDS.SPLIT_MULTI_VALUE_FIELDS_Y:
|
||||
return isBarOrLineChart || isPieChart
|
||||
? (configuration.splitMultiValueFields ?? true)
|
||||
: true;
|
||||
case CHART_CONFIGURATION_SETTING_IDS.HIDE_EMPTY_CATEGORY:
|
||||
return isPieChart ? (configuration.hideEmptyCategory ?? false) : false;
|
||||
case CHART_CONFIGURATION_SETTING_IDS.MIN_RANGE:
|
||||
|
||||
+1
@@ -8,4 +8,5 @@ export type BarLineChartConvertibleFields = {
|
||||
primaryAxisGroupBySubFieldName?: string | null;
|
||||
primaryAxisDateGranularity?: ObjectRecordGroupByDateGranularity | null;
|
||||
primaryAxisOrderBy?: GraphOrderBy | null;
|
||||
splitMultiValueFields?: boolean | null;
|
||||
};
|
||||
|
||||
+6
@@ -27,6 +27,8 @@ export enum CHART_CONFIGURATION_SETTING_IDS {
|
||||
PREFIX = 'PREFIX',
|
||||
SUFFIX = 'SUFFIX',
|
||||
CUMULATIVE = 'CUMULATIVE',
|
||||
SPLIT_MULTI_VALUE_FIELDS_X = 'SPLIT_MULTI_VALUE_FIELDS_X',
|
||||
SPLIT_MULTI_VALUE_FIELDS_Y = 'SPLIT_MULTI_VALUE_FIELDS_Y',
|
||||
}
|
||||
|
||||
export const CHART_CONFIGURATION_SETTING_TO_CONFIG_KEY_MAP = {
|
||||
@@ -47,4 +49,8 @@ export const CHART_CONFIGURATION_SETTING_TO_CONFIG_KEY_MAP = {
|
||||
[CHART_CONFIGURATION_SETTING_IDS.PREFIX]: 'prefix',
|
||||
[CHART_CONFIGURATION_SETTING_IDS.SUFFIX]: 'suffix',
|
||||
[CHART_CONFIGURATION_SETTING_IDS.CUMULATIVE]: 'isCumulative',
|
||||
[CHART_CONFIGURATION_SETTING_IDS.SPLIT_MULTI_VALUE_FIELDS_X]:
|
||||
'splitMultiValueFields',
|
||||
[CHART_CONFIGURATION_SETTING_IDS.SPLIT_MULTI_VALUE_FIELDS_Y]:
|
||||
'splitMultiValueFields',
|
||||
} as const;
|
||||
|
||||
+1
@@ -8,4 +8,5 @@ export type PieChartConvertibleFields = {
|
||||
groupBySubFieldName?: string | null;
|
||||
dateGranularity?: ObjectRecordGroupByDateGranularity | null;
|
||||
orderBy?: GraphOrderBy | null;
|
||||
splitMultiValueFields?: boolean | null;
|
||||
};
|
||||
|
||||
+81
-1
@@ -1,7 +1,12 @@
|
||||
import { type TypedBarChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedBarChartConfiguration';
|
||||
import { type TypedLineChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedLineChartConfiguration';
|
||||
import { type TypedPieChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedPieChartConfiguration';
|
||||
import { buildChartGroupByFieldConfigUpdate } from '@/command-menu/pages/page-layout/utils/buildChartGroupByFieldConfigUpdate';
|
||||
import { ObjectRecordGroupByDateGranularity } from 'twenty-shared/types';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
ObjectRecordGroupByDateGranularity,
|
||||
} from 'twenty-shared/types';
|
||||
import {
|
||||
BarChartGroupMode,
|
||||
GraphOrderBy,
|
||||
@@ -9,6 +14,41 @@ import {
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
describe('buildChartGroupByFieldConfigUpdate', () => {
|
||||
const mockObjectMetadataItem: ObjectMetadataItem = {
|
||||
id: 'object-id',
|
||||
nameSingular: 'opportunity',
|
||||
namePlural: 'opportunities',
|
||||
labelSingular: 'Opportunity',
|
||||
labelPlural: 'Opportunities',
|
||||
description: 'An opportunity',
|
||||
icon: 'IconTargetArrow',
|
||||
isActive: true,
|
||||
isSystem: false,
|
||||
isRemote: false,
|
||||
isAuditLogged: false,
|
||||
isLabelSyncedWithName: true,
|
||||
fields: [
|
||||
{
|
||||
id: 'text-field-id',
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
type: FieldMetadataType.TEXT,
|
||||
},
|
||||
{
|
||||
id: 'array-field-id',
|
||||
name: 'tags',
|
||||
label: 'Tags',
|
||||
type: FieldMetadataType.MULTI_SELECT,
|
||||
},
|
||||
{
|
||||
id: 'array-field-id-2',
|
||||
name: 'skills',
|
||||
label: 'Skills',
|
||||
type: FieldMetadataType.ARRAY,
|
||||
},
|
||||
],
|
||||
} as any;
|
||||
|
||||
it('sets default orderBy and dateGranularity for primary axis', () => {
|
||||
const result = buildChartGroupByFieldConfigUpdate({
|
||||
configuration: {
|
||||
@@ -97,4 +137,44 @@ describe('buildChartGroupByFieldConfigUpdate', () => {
|
||||
primaryAxisOrderBy: GraphOrderBy.FIELD_ASC,
|
||||
});
|
||||
});
|
||||
|
||||
it('disables split multi-value fields for bar charts when both axes are arrays', () => {
|
||||
const result = buildChartGroupByFieldConfigUpdate({
|
||||
configuration: {
|
||||
__typename: 'BarChartConfiguration',
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
splitMultiValueFields: true,
|
||||
primaryAxisGroupByFieldMetadataId: 'array-field-id',
|
||||
} as TypedBarChartConfiguration,
|
||||
fieldMetadataIdKey: 'secondaryAxisGroupByFieldMetadataId',
|
||||
subFieldNameKey: 'secondaryAxisGroupBySubFieldName',
|
||||
fieldId: 'array-field-id-2',
|
||||
subFieldName: null,
|
||||
objectMetadataItem: mockObjectMetadataItem,
|
||||
});
|
||||
|
||||
expect(result).toMatchObject({
|
||||
splitMultiValueFields: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('disables split multi-value fields for line charts when both axes are arrays', () => {
|
||||
const result = buildChartGroupByFieldConfigUpdate({
|
||||
configuration: {
|
||||
__typename: 'LineChartConfiguration',
|
||||
configurationType: WidgetConfigurationType.LINE_CHART,
|
||||
splitMultiValueFields: true,
|
||||
secondaryAxisGroupByFieldMetadataId: 'array-field-id-2',
|
||||
} as TypedLineChartConfiguration,
|
||||
fieldMetadataIdKey: 'primaryAxisGroupByFieldMetadataId',
|
||||
subFieldNameKey: 'primaryAxisGroupBySubFieldName',
|
||||
fieldId: 'array-field-id',
|
||||
subFieldName: null,
|
||||
objectMetadataItem: mockObjectMetadataItem,
|
||||
});
|
||||
|
||||
expect(result).toMatchObject({
|
||||
splitMultiValueFields: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+4
-4
@@ -31,7 +31,7 @@ describe('getBarChartSettings', () => {
|
||||
);
|
||||
|
||||
expect(xAxisGroup).toBeDefined();
|
||||
expect(xAxisGroup?.items).toHaveLength(4);
|
||||
expect(xAxisGroup?.items).toHaveLength(5);
|
||||
expect(xAxisGroup?.items[0].id).toBe(DATA_DISPLAY_X_SETTING.id);
|
||||
expect(xAxisGroup?.items[0].label).toBe(DATA_DISPLAY_X_SETTING.label);
|
||||
expect(xAxisGroup?.items[0].Icon).toBe(IconAxisX);
|
||||
@@ -48,7 +48,7 @@ describe('getBarChartSettings', () => {
|
||||
);
|
||||
|
||||
expect(yAxisGroup).toBeDefined();
|
||||
expect(yAxisGroup?.items).toHaveLength(7);
|
||||
expect(yAxisGroup?.items).toHaveLength(8);
|
||||
expect(yAxisGroup?.items[0].id).toBe(DATA_DISPLAY_Y_SETTING.id);
|
||||
expect(yAxisGroup?.items[0].label).toBe(DATA_DISPLAY_Y_SETTING.label);
|
||||
expect(yAxisGroup?.items[0].Icon).toBe(IconAxisY);
|
||||
@@ -80,7 +80,7 @@ describe('getBarChartSettings', () => {
|
||||
);
|
||||
|
||||
expect(xAxisGroup).toBeDefined();
|
||||
expect(xAxisGroup?.items).toHaveLength(7);
|
||||
expect(xAxisGroup?.items).toHaveLength(8);
|
||||
expect(xAxisGroup?.items[0].id).toBe(DATA_DISPLAY_Y_SETTING.id);
|
||||
expect(xAxisGroup?.items[0].label).toBe(DATA_DISPLAY_Y_SETTING.label);
|
||||
expect(xAxisGroup?.items[0].Icon).toBe(IconAxisX);
|
||||
@@ -100,7 +100,7 @@ describe('getBarChartSettings', () => {
|
||||
);
|
||||
|
||||
expect(yAxisGroup).toBeDefined();
|
||||
expect(yAxisGroup?.items).toHaveLength(4);
|
||||
expect(yAxisGroup?.items).toHaveLength(5);
|
||||
expect(yAxisGroup?.items[0].id).toBe(DATA_DISPLAY_X_SETTING.id);
|
||||
expect(yAxisGroup?.items[0].label).toBe(DATA_DISPLAY_X_SETTING.label);
|
||||
expect(yAxisGroup?.items[0].Icon).toBe(IconAxisY);
|
||||
|
||||
+151
@@ -485,4 +485,155 @@ describe('shouldHideChartSetting', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('split multi-value fields visibility based on grouped field types', () => {
|
||||
const splitMultiValueFieldsXItem: ChartSettingsItem = {
|
||||
id: CHART_CONFIGURATION_SETTING_IDS.SPLIT_MULTI_VALUE_FIELDS_X,
|
||||
label: msg`Split multiple values`,
|
||||
Icon: IconChartBar,
|
||||
isBoolean: true,
|
||||
isNumberInput: false,
|
||||
};
|
||||
|
||||
const splitMultiValueFieldsYItem: ChartSettingsItem = {
|
||||
id: CHART_CONFIGURATION_SETTING_IDS.SPLIT_MULTI_VALUE_FIELDS_Y,
|
||||
label: msg`Split multiple values`,
|
||||
Icon: IconChartBar,
|
||||
isBoolean: true,
|
||||
isNumberInput: false,
|
||||
};
|
||||
|
||||
const mockObjectMetadataItem: ObjectMetadataItem = {
|
||||
id: 'object-id',
|
||||
nameSingular: 'opportunity',
|
||||
namePlural: 'opportunities',
|
||||
labelSingular: 'Opportunity',
|
||||
labelPlural: 'Opportunities',
|
||||
description: 'An opportunity',
|
||||
icon: 'IconTargetArrow',
|
||||
isActive: true,
|
||||
isSystem: false,
|
||||
isRemote: false,
|
||||
isAuditLogged: false,
|
||||
isLabelSyncedWithName: true,
|
||||
fields: [
|
||||
{
|
||||
id: 'text-field-id',
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
type: FieldMetadataType.TEXT,
|
||||
},
|
||||
{
|
||||
id: 'array-field-id',
|
||||
name: 'tags',
|
||||
label: 'Tags',
|
||||
type: FieldMetadataType.MULTI_SELECT,
|
||||
},
|
||||
{
|
||||
id: 'array-field-id-2',
|
||||
name: 'skills',
|
||||
label: 'Skills',
|
||||
type: FieldMetadataType.ARRAY,
|
||||
},
|
||||
],
|
||||
} as any;
|
||||
|
||||
it('should show X setting when bar chart primary group by field is an array field', () => {
|
||||
const barChartConfig: ChartConfiguration = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
primaryAxisGroupByFieldMetadataId: 'array-field-id',
|
||||
} as any;
|
||||
|
||||
const result = shouldHideChartSetting(
|
||||
splitMultiValueFieldsXItem,
|
||||
'object-id',
|
||||
true,
|
||||
barChartConfig,
|
||||
mockObjectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should hide X setting when primary group by field is not an array field', () => {
|
||||
const barChartConfig: ChartConfiguration = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
primaryAxisGroupByFieldMetadataId: 'text-field-id',
|
||||
secondaryAxisGroupByFieldMetadataId: 'array-field-id',
|
||||
} as any;
|
||||
|
||||
const result = shouldHideChartSetting(
|
||||
splitMultiValueFieldsXItem,
|
||||
'object-id',
|
||||
true,
|
||||
barChartConfig,
|
||||
mockObjectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should show Y setting when secondary group by field is an array field', () => {
|
||||
const barChartConfig: ChartConfiguration = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
primaryAxisGroupByFieldMetadataId: 'text-field-id',
|
||||
secondaryAxisGroupByFieldMetadataId: 'array-field-id',
|
||||
} as any;
|
||||
|
||||
const result = shouldHideChartSetting(
|
||||
splitMultiValueFieldsYItem,
|
||||
'object-id',
|
||||
true,
|
||||
barChartConfig,
|
||||
mockObjectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('should hide Y setting when secondary group by field is not an array field', () => {
|
||||
const barChartConfig: ChartConfiguration = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
primaryAxisGroupByFieldMetadataId: 'array-field-id',
|
||||
secondaryAxisGroupByFieldMetadataId: 'text-field-id',
|
||||
} as any;
|
||||
|
||||
const result = shouldHideChartSetting(
|
||||
splitMultiValueFieldsYItem,
|
||||
'object-id',
|
||||
true,
|
||||
barChartConfig,
|
||||
mockObjectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should hide both X and Y settings when both axes are array fields', () => {
|
||||
const barChartConfig: ChartConfiguration = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
primaryAxisGroupByFieldMetadataId: 'array-field-id',
|
||||
secondaryAxisGroupByFieldMetadataId: 'array-field-id-2',
|
||||
} as any;
|
||||
|
||||
const resultX = shouldHideChartSetting(
|
||||
splitMultiValueFieldsXItem,
|
||||
'object-id',
|
||||
true,
|
||||
barChartConfig,
|
||||
mockObjectMetadataItem,
|
||||
);
|
||||
|
||||
const resultY = shouldHideChartSetting(
|
||||
splitMultiValueFieldsYItem,
|
||||
'object-id',
|
||||
true,
|
||||
barChartConfig,
|
||||
mockObjectMetadataItem,
|
||||
);
|
||||
|
||||
expect(resultX).toBe(true);
|
||||
expect(resultY).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+40
-1
@@ -4,7 +4,7 @@ import { isFieldOrRelationNestedFieldDateKind } from '@/command-menu/pages/page-
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { ObjectRecordGroupByDateGranularity } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { isDefined, isFieldMetadataArrayKind } from 'twenty-shared/utils';
|
||||
import { BarChartGroupMode, GraphOrderBy } from '~/generated-metadata/graphql';
|
||||
|
||||
type BuildChartGroupByFieldConfigUpdateArgs<T extends ChartConfiguration> = {
|
||||
@@ -60,6 +60,23 @@ export const buildChartGroupByFieldConfigUpdate = <
|
||||
? getChartDefaultOrderByForFieldType(fieldMetadataItem?.type)
|
||||
: GraphOrderBy.FIELD_ASC;
|
||||
|
||||
const isArrayFieldMetadataId = (
|
||||
fieldMetadataId: string | null | undefined,
|
||||
): boolean => {
|
||||
if (!isDefined(fieldMetadataId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const candidateFieldMetadataItem = objectMetadataItem?.fields?.find(
|
||||
(field) => field.id === fieldMetadataId,
|
||||
);
|
||||
|
||||
return (
|
||||
isDefined(candidateFieldMetadataItem) &&
|
||||
isFieldMetadataArrayKind(candidateFieldMetadataItem.type)
|
||||
);
|
||||
};
|
||||
|
||||
if (isPrimaryAxis) {
|
||||
const existingDateGranularity =
|
||||
isBarChart || isLineChart
|
||||
@@ -79,6 +96,11 @@ export const buildChartGroupByFieldConfigUpdate = <
|
||||
!isNewFieldDateType &&
|
||||
(isBarChart || isLineChart);
|
||||
|
||||
const shouldDisableSplitMultiValueFields =
|
||||
(isBarChart || isLineChart) &&
|
||||
isArrayFieldMetadataId(fieldId) &&
|
||||
isArrayFieldMetadataId(configuration.secondaryAxisGroupByFieldMetadataId);
|
||||
|
||||
return {
|
||||
...baseConfig,
|
||||
primaryAxisOrderBy: isDefined(fieldId) ? defaultOrderBy : null,
|
||||
@@ -86,6 +108,9 @@ export const buildChartGroupByFieldConfigUpdate = <
|
||||
? (existingDateGranularity ?? ObjectRecordGroupByDateGranularity.DAY)
|
||||
: null,
|
||||
...(shouldResetCumulative ? { isCumulative: false } : {}),
|
||||
...(shouldDisableSplitMultiValueFields
|
||||
? { splitMultiValueFields: false }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -108,6 +133,10 @@ export const buildChartGroupByFieldConfigUpdate = <
|
||||
}
|
||||
|
||||
if (isBarChart) {
|
||||
const shouldDisableSplitMultiValueFields =
|
||||
isArrayFieldMetadataId(configuration.primaryAxisGroupByFieldMetadataId) &&
|
||||
isArrayFieldMetadataId(fieldId);
|
||||
|
||||
return {
|
||||
...baseConfig,
|
||||
secondaryAxisOrderBy: isDefined(fieldId) ? defaultOrderBy : null,
|
||||
@@ -118,10 +147,17 @@ export const buildChartGroupByFieldConfigUpdate = <
|
||||
groupMode: isDefined(fieldId)
|
||||
? (configuration.groupMode ?? BarChartGroupMode.STACKED)
|
||||
: null,
|
||||
...(shouldDisableSplitMultiValueFields
|
||||
? { splitMultiValueFields: false }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
|
||||
if (isLineChart) {
|
||||
const shouldDisableSplitMultiValueFields =
|
||||
isArrayFieldMetadataId(configuration.primaryAxisGroupByFieldMetadataId) &&
|
||||
isArrayFieldMetadataId(fieldId);
|
||||
|
||||
return {
|
||||
...baseConfig,
|
||||
secondaryAxisOrderBy: isDefined(fieldId) ? defaultOrderBy : null,
|
||||
@@ -130,6 +166,9 @@ export const buildChartGroupByFieldConfigUpdate = <
|
||||
ObjectRecordGroupByDateGranularity.DAY)
|
||||
: null,
|
||||
isStacked: isDefined(fieldId) ? (configuration.isStacked ?? true) : null,
|
||||
...(shouldDisableSplitMultiValueFields
|
||||
? { splitMultiValueFields: false }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -19,5 +19,6 @@ export const convertBarOrLineChartConfigToPieChart = (
|
||||
groupBySubFieldName: configuration.primaryAxisGroupBySubFieldName,
|
||||
dateGranularity: configuration.primaryAxisDateGranularity,
|
||||
orderBy: configuration.primaryAxisOrderBy,
|
||||
splitMultiValueFields: configuration.splitMultiValueFields,
|
||||
};
|
||||
};
|
||||
|
||||
+1
@@ -14,5 +14,6 @@ export const convertPieChartConfigToBarOrLineChart = (
|
||||
primaryAxisGroupBySubFieldName: configuration.groupBySubFieldName,
|
||||
primaryAxisDateGranularity: configuration.dateGranularity,
|
||||
primaryAxisOrderBy: configuration.orderBy,
|
||||
splitMultiValueFields: configuration.splitMultiValueFields,
|
||||
};
|
||||
};
|
||||
|
||||
+4
@@ -16,6 +16,8 @@ import { RANGE_MAX_SETTING } from '@/command-menu/pages/page-layout/constants/se
|
||||
import { RANGE_MIN_SETTING } from '@/command-menu/pages/page-layout/constants/settings/RangeMinSetting';
|
||||
import { SHOW_LEGEND_SETTING } from '@/command-menu/pages/page-layout/constants/settings/ShowLegendSetting';
|
||||
import { SORT_BY_GROUP_BY_FIELD_SETTING } from '@/command-menu/pages/page-layout/constants/settings/SortByGroupByFieldSetting';
|
||||
import { SPLIT_MULTI_VALUE_FIELDS_X_SETTING } from '@/command-menu/pages/page-layout/constants/settings/SplitMultiValueFieldsXSetting';
|
||||
import { SPLIT_MULTI_VALUE_FIELDS_Y_SETTING } from '@/command-menu/pages/page-layout/constants/settings/SplitMultiValueFieldsYSetting';
|
||||
import { STACKED_BARS_SETTING } from '@/command-menu/pages/page-layout/constants/settings/StackedBarsSetting';
|
||||
import { type ChartSettingsGroup } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||
import { IconAxisX, IconAxisY } from 'twenty-ui/display';
|
||||
@@ -34,6 +36,7 @@ export const getBarChartSettings = (
|
||||
DATE_GRANULARITY_X_SETTING,
|
||||
PRIMARY_SORT_BY_SETTING,
|
||||
OMIT_NULL_VALUES_SETTING,
|
||||
SPLIT_MULTI_VALUE_FIELDS_X_SETTING,
|
||||
];
|
||||
|
||||
const secondaryAxisItems = [
|
||||
@@ -44,6 +47,7 @@ export const getBarChartSettings = (
|
||||
CUMULATIVE_SETTING,
|
||||
RANGE_MIN_SETTING,
|
||||
RANGE_MAX_SETTING,
|
||||
SPLIT_MULTI_VALUE_FIELDS_Y_SETTING,
|
||||
];
|
||||
|
||||
const xAxisItems = isHorizontal ? secondaryAxisItems : primaryAxisItems;
|
||||
|
||||
+59
-1
@@ -6,7 +6,11 @@ import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataI
|
||||
import { isFieldRelation } from '@/object-record/record-field/ui/types/guards/isFieldRelation';
|
||||
import { isRelationNestedFieldDateKind } from '@/page-layout/widgets/graph/utils/isRelationNestedFieldDateKind';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { isDefined, isFieldMetadataDateKind } from 'twenty-shared/utils';
|
||||
import {
|
||||
isDefined,
|
||||
isFieldMetadataArrayKind,
|
||||
isFieldMetadataDateKind,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
const shouldHideDateGranularityBasedOnFieldType = (
|
||||
fieldMetadataId: string | undefined | null,
|
||||
@@ -102,6 +106,60 @@ export const shouldHideChartSetting = (
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
item.id === CHART_CONFIGURATION_SETTING_IDS.SPLIT_MULTI_VALUE_FIELDS_X ||
|
||||
item.id === CHART_CONFIGURATION_SETTING_IDS.SPLIT_MULTI_VALUE_FIELDS_Y
|
||||
) {
|
||||
const isXAxis =
|
||||
item.id === CHART_CONFIGURATION_SETTING_IDS.SPLIT_MULTI_VALUE_FIELDS_X;
|
||||
|
||||
let fieldMetadataId: string | null | undefined;
|
||||
|
||||
if (isBarOrLineChart) {
|
||||
fieldMetadataId = isXAxis
|
||||
? configuration.primaryAxisGroupByFieldMetadataId
|
||||
: configuration.secondaryAxisGroupByFieldMetadataId;
|
||||
} else if (
|
||||
isWidgetConfigurationOfType(configuration, 'PieChartConfiguration')
|
||||
) {
|
||||
fieldMetadataId = isXAxis
|
||||
? configuration.groupByFieldMetadataId
|
||||
: undefined;
|
||||
}
|
||||
|
||||
if (!isDefined(fieldMetadataId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isBarOrLineChart) {
|
||||
const primaryField = objectMetadataItem.fields.find(
|
||||
(field) =>
|
||||
field.id === configuration.primaryAxisGroupByFieldMetadataId,
|
||||
);
|
||||
const secondaryField = objectMetadataItem.fields.find(
|
||||
(field) =>
|
||||
field.id === configuration.secondaryAxisGroupByFieldMetadataId,
|
||||
);
|
||||
const bothAxesAreArrayFields =
|
||||
isDefined(primaryField) &&
|
||||
isFieldMetadataArrayKind(primaryField.type) &&
|
||||
isDefined(secondaryField) &&
|
||||
isFieldMetadataArrayKind(secondaryField.type);
|
||||
|
||||
if (bothAxesAreArrayFields === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const groupByField = objectMetadataItem.fields.find(
|
||||
(field) => field.id === fieldMetadataId,
|
||||
);
|
||||
|
||||
return (
|
||||
!isDefined(groupByField) || !isFieldMetadataArrayKind(groupByField.type)
|
||||
);
|
||||
}
|
||||
|
||||
if (item.id === CHART_CONFIGURATION_SETTING_IDS.SHOW_LEGEND) {
|
||||
if (isWidgetConfigurationOfType(configuration, 'PieChartConfiguration')) {
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user