[BREAKING_CHANGE_DASHBOARDS][DASHBOARD_CACHE_FLUSH_REQUIRED] Refactor page layout widget configuration type (#16671)
# Introduction In this pull-request we're refactoring the page layout widget configuration entity to be containing its discriminated key simplifying underlying code and maintainability - Made the configuration and title non nullable - Introduced a generic predicate for the `widgetConfigurationType` - Upgraded command to remove `graphType` and insert new `configurationType` to existing entries - Migrated frontend to new type system --------- Co-authored-by: bosiraphael <raphael.bosi@gmail.com> Co-authored-by: Raphaël Bosi <71827178+bosiraphael@users.noreply.github.com>
This commit is contained in:
+6
-3
@@ -1,5 +1,6 @@
|
||||
import { GRAPH_TYPE_INFORMATION } from '@/command-menu/pages/page-layout/constants/GraphTypeInformation';
|
||||
import { isChartWidget } from '@/command-menu/pages/page-layout/utils/isChartWidget';
|
||||
import { getCurrentGraphTypeFromConfig } from '@/command-menu/pages/page-layout/utils/getCurrentGraphTypeFromConfig';
|
||||
import { isWidgetConfigurationOfTypeGraph } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfTypeGraph';
|
||||
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
|
||||
import { type PageLayoutTab } from '@/page-layout/types/PageLayoutTab';
|
||||
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
|
||||
@@ -116,11 +117,13 @@ export const usePageLayoutHeaderInfo = ({
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!isChartWidget(widgetInEditMode)) {
|
||||
if (!isWidgetConfigurationOfTypeGraph(widgetInEditMode.configuration)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const currentGraphType = widgetInEditMode.configuration.graphType;
|
||||
const currentGraphType = getCurrentGraphTypeFromConfig(
|
||||
widgetInEditMode.configuration,
|
||||
);
|
||||
const graphTypeInfo = GRAPH_TYPE_INFORMATION[currentGraphType];
|
||||
const graphTypeLabel = t(graphTypeInfo.label);
|
||||
|
||||
|
||||
+4
-5
@@ -1,11 +1,10 @@
|
||||
import { getChartLimitMessage } from '@/command-menu/pages/page-layout/utils/getChartLimitMessage';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { SidePanelInformationBanner } from 'twenty-ui/display';
|
||||
|
||||
import { type GraphType } from '~/generated/graphql';
|
||||
import { type WidgetConfigurationType } from '~/generated/graphql';
|
||||
|
||||
type ChartLimitInfoBannerProps = {
|
||||
graphType: GraphType;
|
||||
widgetConfigurationType: WidgetConfigurationType;
|
||||
isPrimaryAxisDate: boolean;
|
||||
primaryAxisDateGranularity: Parameters<
|
||||
typeof getChartLimitMessage
|
||||
@@ -13,14 +12,14 @@ type ChartLimitInfoBannerProps = {
|
||||
};
|
||||
|
||||
export const ChartLimitInfoBanner = ({
|
||||
graphType,
|
||||
widgetConfigurationType,
|
||||
isPrimaryAxisDate,
|
||||
primaryAxisDateGranularity,
|
||||
}: ChartLimitInfoBannerProps) => {
|
||||
return (
|
||||
<SidePanelInformationBanner
|
||||
message={getChartLimitMessage({
|
||||
graphType,
|
||||
widgetConfigurationType,
|
||||
isPrimaryAxisDate,
|
||||
primaryAxisDateGranularity,
|
||||
})}
|
||||
|
||||
+18
-12
@@ -19,11 +19,11 @@ import styled from '@emotion/styled';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { isFieldMetadataDateKind } from 'twenty-shared/utils';
|
||||
|
||||
import { GraphType } from '@/command-menu/pages/page-layout/types/GraphType';
|
||||
import { assertChartWidgetOrThrow } from '@/command-menu/pages/page-layout/utils/assertChartWidgetOrThrow';
|
||||
import { isBarOrLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarOrLineChartConfiguration';
|
||||
import { isPieChartConfiguration } from '@/command-menu/pages/page-layout/utils/isPieChartConfiguration';
|
||||
import { getCurrentGraphTypeFromConfig } from '@/command-menu/pages/page-layout/utils/getCurrentGraphTypeFromConfig';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
|
||||
import { GraphType } from '~/generated/graphql';
|
||||
|
||||
const StyledCommandMenuContainer = styled.div`
|
||||
display: flex;
|
||||
@@ -42,7 +42,6 @@ export const ChartSettings = ({ widget }: { widget: PageLayoutWidget }) => {
|
||||
assertChartWidgetOrThrow(widget);
|
||||
|
||||
const configuration = widget.configuration;
|
||||
const currentGraphType = configuration?.graphType;
|
||||
|
||||
const { getChartSettingsValues } = useChartSettingsValues({
|
||||
objectMetadataId: widget.objectMetadataId,
|
||||
@@ -81,6 +80,8 @@ export const ChartSettings = ({ widget }: { widget: PageLayoutWidget }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const currentGraphType = getCurrentGraphTypeFromConfig(configuration);
|
||||
|
||||
const chartSettings = GRAPH_TYPE_INFORMATION[currentGraphType].settings;
|
||||
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
@@ -103,11 +104,18 @@ export const ChartSettings = ({ widget }: { widget: PageLayoutWidget }) => {
|
||||
.map((item) => item.id),
|
||||
);
|
||||
|
||||
const primaryAxisFieldMetadataId = isBarOrLineChartConfiguration(
|
||||
const isBarOrLineChart =
|
||||
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration');
|
||||
|
||||
const isPieChart = isWidgetConfigurationOfType(
|
||||
configuration,
|
||||
)
|
||||
'PieChartConfiguration',
|
||||
);
|
||||
|
||||
const primaryAxisFieldMetadataId = isBarOrLineChart
|
||||
? configuration.primaryAxisGroupByFieldMetadataId
|
||||
: isPieChartConfiguration(configuration)
|
||||
: isPieChart
|
||||
? configuration.groupByFieldMetadataId
|
||||
: null;
|
||||
|
||||
@@ -117,11 +125,9 @@ export const ChartSettings = ({ widget }: { widget: PageLayoutWidget }) => {
|
||||
|
||||
const isPrimaryAxisDate = isFieldMetadataDateKind(primaryAxisField?.type);
|
||||
|
||||
const primaryAxisDateGranularity = isBarOrLineChartConfiguration(
|
||||
configuration,
|
||||
)
|
||||
const primaryAxisDateGranularity = isBarOrLineChart
|
||||
? configuration.primaryAxisDateGranularity
|
||||
: isPieChartConfiguration(configuration)
|
||||
: isPieChart
|
||||
? configuration.dateGranularity
|
||||
: null;
|
||||
|
||||
@@ -156,7 +162,7 @@ export const ChartSettings = ({ widget }: { widget: PageLayoutWidget }) => {
|
||||
<CommandGroup key={group.heading.id} heading={t(group.heading)}>
|
||||
{shouldShowBanner && hasWidgetTooManyGroups && (
|
||||
<ChartLimitInfoBanner
|
||||
graphType={currentGraphType}
|
||||
widgetConfigurationType={configuration.configurationType}
|
||||
isPrimaryAxisDate={isPrimaryAxisDate}
|
||||
primaryAxisDateGranularity={primaryAxisDateGranularity}
|
||||
/>
|
||||
|
||||
+2
-1
@@ -1,8 +1,9 @@
|
||||
import { GRAPH_TYPE_INFORMATION } from '@/command-menu/pages/page-layout/constants/GraphTypeInformation';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import styled from '@emotion/styled';
|
||||
import { FeatureFlagKey, GraphType } from '~/generated-metadata/graphql';
|
||||
import { FeatureFlagKey } from '~/generated-metadata/graphql';
|
||||
|
||||
import { GraphType } from '@/command-menu/pages/page-layout/types/GraphType';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { MenuPicker } from 'twenty-ui/navigation';
|
||||
|
||||
|
||||
+2
-5
@@ -1,6 +1,7 @@
|
||||
import { ChartSettings } from '@/command-menu/pages/page-layout/components/ChartSettings';
|
||||
import { WidgetSettingsFooter } from '@/command-menu/pages/page-layout/components/WidgetSettingsFooter';
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { isChartWidget } from '@/command-menu/pages/page-layout/utils/isChartWidget';
|
||||
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
|
||||
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
|
||||
import { WidgetComponentInstanceContext } from '@/page-layout/widgets/states/contexts/WidgetComponentInstanceContext';
|
||||
@@ -31,11 +32,7 @@ export const CommandMenuPageLayoutChartSettings = () => {
|
||||
.flatMap((tab) => tab.widgets)
|
||||
.find((widget) => widget.id === pageLayoutEditingWidgetId);
|
||||
|
||||
if (
|
||||
!isDefined(widgetInEditMode) ||
|
||||
!isDefined(widgetInEditMode.configuration) ||
|
||||
!('graphType' in widgetInEditMode.configuration)
|
||||
) {
|
||||
if (!isDefined(widgetInEditMode) || !isChartWidget(widgetInEditMode)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -7,6 +7,7 @@ import { t } from '@lingui/core/macro';
|
||||
import { isNonEmptyString, isString } from '@sniptt/guards';
|
||||
import { useState } from 'react';
|
||||
import { isDefined, isValidUrl } from 'twenty-shared/utils';
|
||||
import { WidgetConfigurationType } from '~/generated/graphql';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
@@ -67,6 +68,7 @@ export const CommandMenuPageLayoutIframeSettings = () => {
|
||||
updatePageLayoutWidget(widgetInEditMode.id, {
|
||||
configuration: {
|
||||
__typename: 'IframeConfiguration',
|
||||
configurationType: WidgetConfigurationType.IFRAME,
|
||||
url: isNonEmptyString(trimmedValue) ? trimmedValue : null,
|
||||
},
|
||||
});
|
||||
|
||||
-2
@@ -19,7 +19,6 @@ import {
|
||||
IconChartPie,
|
||||
IconFrame,
|
||||
} from 'twenty-ui/display';
|
||||
import { GraphType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const CommandMenuPageLayoutWidgetTypeSelect = () => {
|
||||
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
|
||||
@@ -49,7 +48,6 @@ export const CommandMenuPageLayoutWidgetTypeSelect = () => {
|
||||
if (!isDefined(pageLayoutEditingWidgetId)) {
|
||||
const fieldSelection = buildBarChartFieldSelection();
|
||||
const newWidget = createPageLayoutGraphWidget({
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
fieldSelection,
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { isAggregateChartConfiguration } from '@/command-menu/pages/page-layout/utils/isAggregateChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { type ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
|
||||
import { convertExtendedAggregateOperationToAggregateOperation } from '@/object-record/utils/convertExtendedAggregateOperationToAggregateOperation';
|
||||
import { DASHBOARD_AGGREGATE_OPERATION_RATIO } from '@/page-layout/widgets/graph/constants/DashboardAggregateOperationRatio';
|
||||
@@ -53,7 +53,7 @@ export const ChartAggregateOperationSelectableListItem = ({
|
||||
configuration.aggregateOperation;
|
||||
|
||||
const isCurrentlyRatio =
|
||||
isAggregateChartConfiguration(configuration) &&
|
||||
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration') &&
|
||||
isDefined(configuration.ratioAggregateConfig);
|
||||
|
||||
if (!isExtendedAggregateOperation(operation)) {
|
||||
|
||||
+13
-9
@@ -3,9 +3,7 @@ import { ChartRatioAggregateOperationSelectableListItem } from '@/command-menu/p
|
||||
import { ChartRatioOptionValueSelectionDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartRatioOptionValueSelectionDropdownContent';
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { isAggregateChartConfiguration } from '@/command-menu/pages/page-layout/utils/isAggregateChartConfiguration';
|
||||
import { isBarOrLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarOrLineChartConfiguration';
|
||||
import { isPieChartConfiguration } from '@/command-menu/pages/page-layout/utils/isPieChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { DateAggregateOperations } from '@/object-record/record-table/constants/DateAggregateOperations';
|
||||
import { getAvailableAggregateOperationsForFieldMetadataType } from '@/object-record/record-table/record-table-footer/utils/getAvailableAggregateOperationsForFieldMetadataType';
|
||||
@@ -42,13 +40,19 @@ export const ChartAggregateOperationSelectionDropdownContent = ({
|
||||
|
||||
const configuration = widgetInEditMode?.configuration;
|
||||
|
||||
const isAggregateChart = isAggregateChartConfiguration(configuration);
|
||||
const isAggregateChart = isWidgetConfigurationOfType(
|
||||
configuration,
|
||||
'AggregateChartConfiguration',
|
||||
);
|
||||
const isBarOrLineChart =
|
||||
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration');
|
||||
const isPieChart = isWidgetConfigurationOfType(
|
||||
configuration,
|
||||
'PieChartConfiguration',
|
||||
);
|
||||
|
||||
if (
|
||||
!isBarOrLineChartConfiguration(configuration) &&
|
||||
!isAggregateChart &&
|
||||
!isPieChartConfiguration(configuration)
|
||||
) {
|
||||
if (!isBarOrLineChart && !isAggregateChart && !isPieChart) {
|
||||
throw new Error('Invalid configuration type');
|
||||
}
|
||||
|
||||
|
||||
+9
-3
@@ -2,7 +2,7 @@ import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pa
|
||||
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { getChartAxisNameDisplayOptions } from '@/command-menu/pages/page-layout/utils/getChartAxisNameDisplayOptions';
|
||||
import { isBarOrLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarOrLineChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
@@ -18,11 +18,17 @@ export const ChartAxisNameSelectionDropdownContent = () => {
|
||||
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
|
||||
const { widgetInEditMode } = useWidgetInEditMode(pageLayoutId);
|
||||
|
||||
if (!isBarOrLineChartConfiguration(widgetInEditMode?.configuration)) {
|
||||
const configuration = widgetInEditMode?.configuration;
|
||||
|
||||
const isBarOrLineChart =
|
||||
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration');
|
||||
|
||||
if (!isBarOrLineChart) {
|
||||
throw new Error('Invalid configuration type');
|
||||
}
|
||||
|
||||
const currentAxisNameDisplay = widgetInEditMode.configuration.axisNameDisplay;
|
||||
const currentAxisNameDisplay = configuration.axisNameDisplay;
|
||||
|
||||
const dropdownId = useAvailableComponentInstanceIdOrThrow(
|
||||
DropdownComponentInstanceContext,
|
||||
|
||||
+20
-10
@@ -4,10 +4,7 @@ import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pa
|
||||
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { isBarOrLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarOrLineChartConfiguration';
|
||||
import { isGaugeChartConfiguration } from '@/command-menu/pages/page-layout/utils/isGaugeChartConfiguration';
|
||||
import { isIframeConfiguration } from '@/command-menu/pages/page-layout/utils/isIframeConfiguration';
|
||||
import { isPieChartConfiguration } from '@/command-menu/pages/page-layout/utils/isPieChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
@@ -52,17 +49,30 @@ export const ChartColorSelectionDropdownContent = () => {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isIframeConfiguration(widgetInEditMode.configuration)) {
|
||||
if (
|
||||
isWidgetConfigurationOfType(
|
||||
widgetInEditMode.configuration,
|
||||
'IframeConfiguration',
|
||||
)
|
||||
) {
|
||||
throw new Error('Invalid configuration type');
|
||||
}
|
||||
|
||||
const configuration = widgetInEditMode.configuration as ChartConfiguration;
|
||||
|
||||
if (
|
||||
!isBarOrLineChartConfiguration(configuration) &&
|
||||
!isGaugeChartConfiguration(configuration) &&
|
||||
!isPieChartConfiguration(configuration)
|
||||
) {
|
||||
const isBarOrLineChart =
|
||||
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration');
|
||||
const isGaugeChart = isWidgetConfigurationOfType(
|
||||
configuration,
|
||||
'GaugeChartConfiguration',
|
||||
);
|
||||
const isPieChart = isWidgetConfigurationOfType(
|
||||
configuration,
|
||||
'PieChartConfiguration',
|
||||
);
|
||||
|
||||
if (!isBarOrLineChart && !isGaugeChart && !isPieChart) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+37
-7
@@ -3,9 +3,9 @@ import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/h
|
||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { getDateGranularityLabel } from '@/command-menu/pages/page-layout/utils/getDateGranularityLabel';
|
||||
import { isBarOrLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarOrLineChartConfiguration';
|
||||
import { isChartConfiguration } from '@/command-menu/pages/page-layout/utils/isChartConfiguration';
|
||||
import { isPieChartConfiguration } from '@/command-menu/pages/page-layout/utils/isPieChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
@@ -17,6 +17,7 @@ import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/ho
|
||||
import { ObjectRecordGroupByDateGranularity } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { MenuItemSelect } from 'twenty-ui/navigation';
|
||||
import { type WidgetConfiguration } from '~/generated/graphql';
|
||||
|
||||
type ChartDateGranularitySelectionDropdownContentProps = {
|
||||
axis?: 'primary' | 'secondary';
|
||||
@@ -31,11 +32,15 @@ const getCurrentDateGranularity = ({
|
||||
}) => {
|
||||
const defaultGranularity = ObjectRecordGroupByDateGranularity.DAY;
|
||||
|
||||
if (isPieChartConfiguration(configuration)) {
|
||||
if (isWidgetConfigurationOfType(configuration, 'PieChartConfiguration')) {
|
||||
return configuration.dateGranularity || defaultGranularity;
|
||||
}
|
||||
|
||||
if (!isBarOrLineChartConfiguration(configuration)) {
|
||||
const isBarOrLineChart =
|
||||
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration');
|
||||
|
||||
if (!isBarOrLineChart) {
|
||||
return defaultGranularity;
|
||||
}
|
||||
|
||||
@@ -48,6 +53,23 @@ const getCurrentDateGranularity = ({
|
||||
);
|
||||
};
|
||||
|
||||
const isChartConfiguration = (
|
||||
configuration:
|
||||
| WidgetConfiguration
|
||||
| FieldsConfiguration
|
||||
| FieldConfiguration
|
||||
| null
|
||||
| undefined,
|
||||
): configuration is ChartConfiguration => {
|
||||
return (
|
||||
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'PieChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'GaugeChartConfiguration')
|
||||
);
|
||||
};
|
||||
|
||||
export const ChartDateGranularitySelectionDropdownContent = ({
|
||||
axis,
|
||||
}: ChartDateGranularitySelectionDropdownContentProps) => {
|
||||
@@ -60,11 +82,19 @@ export const ChartDateGranularitySelectionDropdownContent = ({
|
||||
throw new Error('Invalid configuration type');
|
||||
}
|
||||
|
||||
if (!isDefined(axis) && !isPieChartConfiguration(configuration)) {
|
||||
const isPieChart = isWidgetConfigurationOfType(
|
||||
configuration,
|
||||
'PieChartConfiguration',
|
||||
);
|
||||
const isBarOrLineChart =
|
||||
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration');
|
||||
|
||||
if (!isDefined(axis) && !isPieChart) {
|
||||
throw new Error('Invalid configuration type');
|
||||
}
|
||||
|
||||
if (isDefined(axis) && !isBarOrLineChartConfiguration(configuration)) {
|
||||
if (isDefined(axis) && !isBarOrLineChart) {
|
||||
throw new Error('Invalid configuration type');
|
||||
}
|
||||
|
||||
|
||||
+14
-8
@@ -1,9 +1,7 @@
|
||||
import { ChartAggregateOperationSelectionDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartAggregateOperationSelectionDropdownContent';
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { isAggregateChartConfiguration } from '@/command-menu/pages/page-layout/utils/isAggregateChartConfiguration';
|
||||
import { isBarOrLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarOrLineChartConfiguration';
|
||||
import { isPieChartConfiguration } from '@/command-menu/pages/page-layout/utils/isPieChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { isFieldRelation } from '@/object-record/record-field/ui/types/guards/isFieldRelation';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
@@ -31,11 +29,19 @@ export const ChartFieldSelectionForAggregateOperationDropdownContent = () => {
|
||||
|
||||
const configuration = widgetInEditMode?.configuration;
|
||||
|
||||
if (
|
||||
!isBarOrLineChartConfiguration(configuration) &&
|
||||
!isAggregateChartConfiguration(configuration) &&
|
||||
!isPieChartConfiguration(configuration)
|
||||
) {
|
||||
const isBarOrLineChart =
|
||||
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration');
|
||||
const isAggregateChart = isWidgetConfigurationOfType(
|
||||
configuration,
|
||||
'AggregateChartConfiguration',
|
||||
);
|
||||
const isPieChart = isWidgetConfigurationOfType(
|
||||
configuration,
|
||||
'PieChartConfiguration',
|
||||
);
|
||||
|
||||
if (!isBarOrLineChart && !isAggregateChart && !isPieChart) {
|
||||
throw new Error('Invalid configuration type');
|
||||
}
|
||||
|
||||
|
||||
+3
-5
@@ -1,13 +1,11 @@
|
||||
import { ChartGroupByFieldSelectionDropdownContentBase } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartGroupByFieldSelectionDropdownContentBase';
|
||||
import {
|
||||
type BarChartConfiguration,
|
||||
type LineChartConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
import { type TypedBarChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedBarChartConfiguration';
|
||||
import { type TypedLineChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedLineChartConfiguration';
|
||||
|
||||
export const ChartGroupByFieldSelectionDropdownContent = () => {
|
||||
return (
|
||||
<ChartGroupByFieldSelectionDropdownContentBase<
|
||||
BarChartConfiguration | LineChartConfiguration
|
||||
TypedBarChartConfiguration | TypedLineChartConfiguration
|
||||
>
|
||||
fieldMetadataIdKey="secondaryAxisGroupByFieldMetadataId"
|
||||
subFieldNameKey="secondaryAxisGroupBySubFieldName"
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
import { ChartGroupByFieldSelectionDropdownContentBase } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartGroupByFieldSelectionDropdownContentBase';
|
||||
import { type PieChartConfiguration } from '~/generated/graphql';
|
||||
import { type TypedPieChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedPieChartConfiguration';
|
||||
|
||||
export const ChartPieFieldSelectionDropdownContent = () => {
|
||||
return (
|
||||
<ChartGroupByFieldSelectionDropdownContentBase<PieChartConfiguration>
|
||||
<ChartGroupByFieldSelectionDropdownContentBase<TypedPieChartConfiguration>
|
||||
fieldMetadataIdKey="groupByFieldMetadataId"
|
||||
subFieldNameKey="groupBySubFieldName"
|
||||
/>
|
||||
|
||||
+5
-3
@@ -1,6 +1,6 @@
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { isAggregateChartConfiguration } from '@/command-menu/pages/page-layout/utils/isAggregateChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { DASHBOARD_AGGREGATE_OPERATION_RATIO } from '@/page-layout/widgets/graph/constants/DashboardAggregateOperationRatio';
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
@@ -30,8 +30,10 @@ export const ChartRatioAggregateOperationSelectableListItem = ({
|
||||
);
|
||||
|
||||
const isCurrentlyRatio =
|
||||
isAggregateChartConfiguration(widgetInEditMode?.configuration) &&
|
||||
isDefined(widgetInEditMode.configuration.ratioAggregateConfig);
|
||||
isWidgetConfigurationOfType(
|
||||
widgetInEditMode?.configuration,
|
||||
'AggregateChartConfiguration',
|
||||
) && isDefined(widgetInEditMode.configuration.ratioAggregateConfig);
|
||||
|
||||
const isFocused = selectedItemId === DASHBOARD_AGGREGATE_OPERATION_RATIO;
|
||||
|
||||
|
||||
+3
-2
@@ -1,7 +1,7 @@
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { isAggregateChartConfiguration } from '@/command-menu/pages/page-layout/utils/isAggregateChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
@@ -36,8 +36,9 @@ export const ChartRatioOptionBooleanSelectableListItem = ({
|
||||
dropdownId,
|
||||
);
|
||||
|
||||
const currentRatioConfig = isAggregateChartConfiguration(
|
||||
const currentRatioConfig = isWidgetConfigurationOfType(
|
||||
widgetInEditMode?.configuration,
|
||||
'AggregateChartConfiguration',
|
||||
)
|
||||
? widgetInEditMode.configuration.ratioAggregateConfig
|
||||
: undefined;
|
||||
|
||||
+3
-2
@@ -1,7 +1,7 @@
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { isAggregateChartConfiguration } from '@/command-menu/pages/page-layout/utils/isAggregateChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
@@ -38,8 +38,9 @@ export const ChartRatioOptionSelectSelectableListItem = ({
|
||||
dropdownId,
|
||||
);
|
||||
|
||||
const currentRatioConfig = isAggregateChartConfiguration(
|
||||
const currentRatioConfig = isWidgetConfigurationOfType(
|
||||
widgetInEditMode?.configuration,
|
||||
'AggregateChartConfiguration',
|
||||
)
|
||||
? widgetInEditMode.configuration.ratioAggregateConfig
|
||||
: undefined;
|
||||
|
||||
+7
-2
@@ -2,7 +2,7 @@ import { ChartRatioOptionBooleanSelectableListItem } from '@/command-menu/pages/
|
||||
import { ChartRatioOptionSelectSelectableListItem } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartRatioOptionSelectSelectableListItem';
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { isAggregateChartConfiguration } from '@/command-menu/pages/page-layout/utils/isAggregateChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
||||
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
|
||||
@@ -42,7 +42,12 @@ export const ChartRatioOptionValueSelectionDropdownContent = ({
|
||||
DropdownComponentInstanceContext,
|
||||
);
|
||||
|
||||
if (!isAggregateChartConfiguration(widgetInEditMode?.configuration)) {
|
||||
if (
|
||||
!isWidgetConfigurationOfType(
|
||||
widgetInEditMode?.configuration,
|
||||
'AggregateChartConfiguration',
|
||||
)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+4
-2
@@ -3,7 +3,7 @@ import { useGraphGroupBySortOptionLabels } from '@/command-menu/pages/page-layou
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { isBarOrLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarOrLineChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
@@ -23,7 +23,9 @@ export const ChartSortByGroupByFieldDropdownContent = () => {
|
||||
|
||||
const configuration = widgetInEditMode?.configuration;
|
||||
|
||||
const isBarOrLineChart = isBarOrLineChartConfiguration(configuration);
|
||||
const isBarOrLineChart =
|
||||
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration');
|
||||
|
||||
if (!isBarOrLineChart) {
|
||||
throw new Error('Invalid configuration type');
|
||||
|
||||
+13
-6
@@ -3,9 +3,7 @@ import { useGraphXSortOptionLabels } from '@/command-menu/pages/page-layout/hook
|
||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||
import { isBarChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarChartConfiguration';
|
||||
import { isLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isLineChartConfiguration';
|
||||
import { isPieChartConfiguration } from '@/command-menu/pages/page-layout/utils/isPieChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { isRelationNestedFieldDateKind } from '@/page-layout/widgets/graph/utils/isRelationNestedFieldDateKind';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
@@ -30,9 +28,18 @@ export const ChartSortBySelectionDropdownContent = () => {
|
||||
const { widgetInEditMode } = useWidgetInEditMode(pageLayoutId);
|
||||
const configuration = widgetInEditMode?.configuration;
|
||||
|
||||
const isPieChart = isPieChartConfiguration(configuration);
|
||||
const isLineChart = isLineChartConfiguration(configuration);
|
||||
const isBarChart = isBarChartConfiguration(configuration);
|
||||
const isPieChart = isWidgetConfigurationOfType(
|
||||
configuration,
|
||||
'PieChartConfiguration',
|
||||
);
|
||||
const isLineChart = isWidgetConfigurationOfType(
|
||||
configuration,
|
||||
'LineChartConfiguration',
|
||||
);
|
||||
const isBarChart = isWidgetConfigurationOfType(
|
||||
configuration,
|
||||
'BarChartConfiguration',
|
||||
);
|
||||
|
||||
if (!isBarChart && !isLineChart && !isPieChart) {
|
||||
throw new Error('Invalid configuration type');
|
||||
|
||||
+3
-5
@@ -1,13 +1,11 @@
|
||||
import { ChartGroupByFieldSelectionDropdownContentBase } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartGroupByFieldSelectionDropdownContentBase';
|
||||
import {
|
||||
type BarChartConfiguration,
|
||||
type LineChartConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
import { type TypedBarChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedBarChartConfiguration';
|
||||
import { type TypedLineChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedLineChartConfiguration';
|
||||
|
||||
export const ChartXAxisFieldSelectionDropdownContent = () => {
|
||||
return (
|
||||
<ChartGroupByFieldSelectionDropdownContentBase<
|
||||
BarChartConfiguration | LineChartConfiguration
|
||||
TypedBarChartConfiguration | TypedLineChartConfiguration
|
||||
>
|
||||
fieldMetadataIdKey="primaryAxisGroupByFieldMetadataId"
|
||||
subFieldNameKey="primaryAxisGroupBySubFieldName"
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { WidgetConfigurationType } from '~/generated/graphql';
|
||||
|
||||
export const GRAPH_CONFIGURATION_TYPE_TO_CONFIG_TYPENAME: Partial<
|
||||
Record<WidgetConfigurationType, string>
|
||||
> = {
|
||||
[WidgetConfigurationType.BAR_CHART]: 'BarChartConfiguration',
|
||||
[WidgetConfigurationType.LINE_CHART]: 'LineChartConfiguration',
|
||||
[WidgetConfigurationType.PIE_CHART]: 'PieChartConfiguration',
|
||||
[WidgetConfigurationType.AGGREGATE_CHART]: 'AggregateChartConfiguration',
|
||||
[WidgetConfigurationType.GAUGE_CHART]: 'GaugeChartConfiguration',
|
||||
} as const;
|
||||
+4
-3
@@ -3,6 +3,7 @@ import { GAUGE_CHART_SETTINGS } from '@/command-menu/pages/page-layout/constants
|
||||
import { LINE_CHART_SETTINGS } from '@/command-menu/pages/page-layout/constants/LineChartSettings';
|
||||
import { PIE_CHART_SETTINGS } from '@/command-menu/pages/page-layout/constants/PieChartSettings';
|
||||
import { type ChartSettingsGroup } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||
import { GraphType } from '@/command-menu/pages/page-layout/types/GraphType';
|
||||
import { getBarChartSettings } from '@/command-menu/pages/page-layout/utils/getBarChartSettings';
|
||||
import { type MessageDescriptor } from '@lingui/core';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
@@ -15,7 +16,7 @@ import {
|
||||
IconGauge,
|
||||
IconSum,
|
||||
} from 'twenty-ui/display';
|
||||
import { GraphType } from '~/generated-metadata/graphql';
|
||||
import { BarChartLayout } from '~/generated/graphql';
|
||||
|
||||
export const GRAPH_TYPE_INFORMATION: Record<
|
||||
GraphType,
|
||||
@@ -28,12 +29,12 @@ export const GRAPH_TYPE_INFORMATION: Record<
|
||||
[GraphType.VERTICAL_BAR]: {
|
||||
label: msg`Vertical Bar Chart`,
|
||||
icon: IconChartBar,
|
||||
settings: getBarChartSettings(GraphType.VERTICAL_BAR),
|
||||
settings: getBarChartSettings(BarChartLayout.VERTICAL),
|
||||
},
|
||||
[GraphType.HORIZONTAL_BAR]: {
|
||||
label: msg`Horizontal Bar Chart`,
|
||||
icon: IconChartBarHorizontal,
|
||||
settings: getBarChartSettings(GraphType.HORIZONTAL_BAR),
|
||||
settings: getBarChartSettings(BarChartLayout.HORIZONTAL),
|
||||
},
|
||||
[GraphType.PIE]: {
|
||||
label: msg`Pie Chart`,
|
||||
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
import { GraphType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const GRAPH_TYPE_TO_CONFIG_TYPENAME = {
|
||||
[GraphType.VERTICAL_BAR]: 'BarChartConfiguration',
|
||||
[GraphType.HORIZONTAL_BAR]: 'BarChartConfiguration',
|
||||
[GraphType.LINE]: 'LineChartConfiguration',
|
||||
[GraphType.PIE]: 'PieChartConfiguration',
|
||||
[GraphType.AGGREGATE]: 'AggregateChartConfiguration',
|
||||
[GraphType.GAUGE]: 'GaugeChartConfiguration',
|
||||
} as const;
|
||||
+16
-15
@@ -3,16 +3,17 @@ import { RecoilRoot } from 'recoil';
|
||||
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||
import { type TypedBarChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedBarChartConfiguration';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import {
|
||||
AggregateOperations,
|
||||
AxisNameDisplay,
|
||||
type BarChartConfiguration,
|
||||
BarChartGroupMode,
|
||||
BarChartLayout,
|
||||
FieldMetadataType,
|
||||
GraphOrderBy,
|
||||
GraphType,
|
||||
WidgetConfigurationType,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { useChartSettingsValues } from '@/command-menu/pages/page-layout/hooks/useChartSettingsValues';
|
||||
|
||||
@@ -59,13 +60,12 @@ const mockObjectMetadataItem: ObjectMetadataItem = {
|
||||
} as ObjectMetadataItem;
|
||||
|
||||
const buildBarChartConfiguration = (
|
||||
overrides: Partial<BarChartConfiguration>,
|
||||
): BarChartConfiguration =>
|
||||
overrides: Partial<TypedBarChartConfiguration>,
|
||||
): TypedBarChartConfiguration =>
|
||||
({
|
||||
__typename: 'BarChartConfiguration',
|
||||
aggregateFieldMetadataId: 'field-amount',
|
||||
aggregateOperation: AggregateOperations.SUM,
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
primaryAxisGroupByFieldMetadataId: 'field-company-name',
|
||||
primaryAxisGroupBySubFieldName: null,
|
||||
secondaryAxisGroupByFieldMetadataId: null,
|
||||
@@ -76,7 +76,7 @@ const buildBarChartConfiguration = (
|
||||
displayDataLabel: false,
|
||||
groupMode: 'GROUPED',
|
||||
...overrides,
|
||||
}) as BarChartConfiguration;
|
||||
}) as TypedBarChartConfiguration;
|
||||
|
||||
const renderUseChartSettingsValues = (configuration: ChartConfiguration) => {
|
||||
return renderHook(
|
||||
@@ -102,7 +102,6 @@ const renderUseChartSettingsValues = (configuration: ChartConfiguration) => {
|
||||
describe('useChartSettingsValues', () => {
|
||||
describe('Vertical bar chart (1D - single grouping)', () => {
|
||||
const verticalBarConfig = buildBarChartConfiguration({
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
primaryAxisGroupByFieldMetadataId: 'field-company-name',
|
||||
secondaryAxisGroupByFieldMetadataId: null,
|
||||
});
|
||||
@@ -172,7 +171,7 @@ describe('useChartSettingsValues', () => {
|
||||
|
||||
describe('Horizontal bar chart (1D - single grouping)', () => {
|
||||
const horizontalBarConfig = buildBarChartConfiguration({
|
||||
graphType: GraphType.HORIZONTAL_BAR,
|
||||
layout: BarChartLayout.HORIZONTAL,
|
||||
primaryAxisGroupByFieldMetadataId: 'field-company-name',
|
||||
secondaryAxisGroupByFieldMetadataId: null,
|
||||
});
|
||||
@@ -213,7 +212,7 @@ describe('useChartSettingsValues', () => {
|
||||
|
||||
describe('Vertical bar chart (2D - with secondary grouping)', () => {
|
||||
const verticalBar2DConfig = buildBarChartConfiguration({
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
layout: BarChartLayout.VERTICAL,
|
||||
primaryAxisGroupByFieldMetadataId: 'field-company-name',
|
||||
secondaryAxisGroupByFieldMetadataId: 'field-stage',
|
||||
secondaryAxisOrderBy: GraphOrderBy.FIELD_DESC,
|
||||
@@ -253,7 +252,7 @@ describe('useChartSettingsValues', () => {
|
||||
|
||||
describe('Horizontal bar chart (2D - with secondary grouping)', () => {
|
||||
const horizontalBar2DConfig = buildBarChartConfiguration({
|
||||
graphType: GraphType.HORIZONTAL_BAR,
|
||||
layout: BarChartLayout.HORIZONTAL,
|
||||
primaryAxisGroupByFieldMetadataId: 'field-company-name',
|
||||
secondaryAxisGroupByFieldMetadataId: 'field-stage',
|
||||
secondaryAxisOrderBy: GraphOrderBy.FIELD_DESC,
|
||||
@@ -282,7 +281,7 @@ describe('useChartSettingsValues', () => {
|
||||
|
||||
describe('Composite field with subfield', () => {
|
||||
const configWithSubField = buildBarChartConfiguration({
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
layout: BarChartLayout.VERTICAL,
|
||||
primaryAxisGroupByFieldMetadataId: 'field-full-name',
|
||||
primaryAxisGroupBySubFieldName: 'firstName',
|
||||
});
|
||||
@@ -345,7 +344,7 @@ describe('useChartSettingsValues', () => {
|
||||
it('should return capitalized color when color is set', () => {
|
||||
const config = buildBarChartConfiguration({
|
||||
color: 'blue',
|
||||
} as Partial<BarChartConfiguration>);
|
||||
});
|
||||
|
||||
const { result } = renderUseChartSettingsValues(config);
|
||||
|
||||
@@ -525,7 +524,7 @@ describe('useChartSettingsValues', () => {
|
||||
describe('Critical: Proves no swapping occurs', () => {
|
||||
it('horizontal bar with NULL secondary should still return primary for DATA_ON_DISPLAY_X', () => {
|
||||
const horizontalConfig = buildBarChartConfiguration({
|
||||
graphType: GraphType.HORIZONTAL_BAR,
|
||||
layout: BarChartLayout.HORIZONTAL,
|
||||
primaryAxisGroupByFieldMetadataId: 'field-company-name',
|
||||
secondaryAxisGroupByFieldMetadataId: null,
|
||||
});
|
||||
@@ -554,12 +553,14 @@ describe('useChartSettingsValues', () => {
|
||||
|
||||
const verticalConfig = buildBarChartConfiguration({
|
||||
...baseConfig,
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
layout: BarChartLayout.VERTICAL,
|
||||
});
|
||||
|
||||
const horizontalConfig = buildBarChartConfiguration({
|
||||
...baseConfig,
|
||||
graphType: GraphType.HORIZONTAL_BAR,
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
layout: BarChartLayout.HORIZONTAL,
|
||||
});
|
||||
|
||||
const { result: verticalResult } =
|
||||
|
||||
+56
-20
@@ -1,10 +1,12 @@
|
||||
import { GRAPH_TYPE_TO_CONFIG_TYPENAME } from '@/command-menu/pages/page-layout/constants/GraphTypeToConfigTypename';
|
||||
import { GRAPH_CONFIGURATION_TYPE_TO_CONFIG_TYPENAME } from '@/command-menu/pages/page-layout/constants/GraphConfigurationTypeToConfigTypename';
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { GraphType } from '@/command-menu/pages/page-layout/types/GraphType';
|
||||
import { convertAggregateOperationForDateField } from '@/command-menu/pages/page-layout/utils/convertAggregateOperationForDateField';
|
||||
import { convertBarOrLineChartConfigToPieChart } from '@/command-menu/pages/page-layout/utils/convertBarOrLineChartConfigToPieChart';
|
||||
import { convertPieChartConfigToBarOrLineChart } from '@/command-menu/pages/page-layout/utils/convertPieChartConfigToBarOrLineChart';
|
||||
import { isBarOrLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarOrLineChartConfiguration';
|
||||
import { isPieChartConfiguration } from '@/command-menu/pages/page-layout/utils/isPieChartConfiguration';
|
||||
import { getConfigurationTypeFromGraphType } from '@/command-menu/pages/page-layout/utils/getConfigurationTypeFromGraphType';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { isWidgetConfigurationOfTypeGraph } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfTypeGraph';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { pageLayoutCurrentLayoutsComponentState } from '@/page-layout/states/pageLayoutCurrentLayoutsComponentState';
|
||||
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
|
||||
@@ -16,7 +18,7 @@ import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTab
|
||||
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { GraphType } from '~/generated/graphql';
|
||||
import { BarChartLayout } from '~/generated/graphql';
|
||||
|
||||
export const useGetConfigToUpdateAfterGraphTypeChange = ({
|
||||
pageLayoutId,
|
||||
@@ -75,13 +77,20 @@ export const useGetConfigToUpdateAfterGraphTypeChange = ({
|
||||
throw new Error('Widget configuration not found in draft state');
|
||||
}
|
||||
|
||||
const currentConfiguration =
|
||||
widgetInDraft.configuration as ChartConfiguration;
|
||||
const currentConfiguration = widgetInDraft.configuration;
|
||||
|
||||
let configToUpdate: Record<string, any> = {
|
||||
__typename: GRAPH_TYPE_TO_CONFIG_TYPENAME[graphType],
|
||||
graphType,
|
||||
};
|
||||
if (!isWidgetConfigurationOfTypeGraph(currentConfiguration)) {
|
||||
throw new Error('Widget configuration is not a chart configuration');
|
||||
}
|
||||
|
||||
const newConfigurationType =
|
||||
getConfigurationTypeFromGraphType(graphType);
|
||||
|
||||
let configToUpdate = {
|
||||
__typename:
|
||||
GRAPH_CONFIGURATION_TYPE_TO_CONFIG_TYPENAME[newConfigurationType],
|
||||
configurationType: newConfigurationType,
|
||||
} as Partial<ChartConfiguration>;
|
||||
|
||||
if (
|
||||
graphType !== GraphType.AGGREGATE &&
|
||||
@@ -106,13 +115,26 @@ export const useGetConfigToUpdateAfterGraphTypeChange = ({
|
||||
}
|
||||
|
||||
const isPieChart = graphType === GraphType.PIE;
|
||||
const isVerticalBarChart = graphType === GraphType.VERTICAL_BAR;
|
||||
const isHorizontalBarChart = graphType === GraphType.HORIZONTAL_BAR;
|
||||
const isLineChart = graphType === GraphType.LINE;
|
||||
const isBarOrLineChart =
|
||||
graphType === GraphType.VERTICAL_BAR ||
|
||||
graphType === GraphType.HORIZONTAL_BAR ||
|
||||
graphType === GraphType.LINE;
|
||||
isVerticalBarChart || isHorizontalBarChart || isLineChart;
|
||||
|
||||
const wasBarOrLineChart =
|
||||
isBarOrLineChartConfiguration(currentConfiguration);
|
||||
const wasPieChart = isPieChartConfiguration(currentConfiguration);
|
||||
isWidgetConfigurationOfType(
|
||||
currentConfiguration,
|
||||
'BarChartConfiguration',
|
||||
) ||
|
||||
isWidgetConfigurationOfType(
|
||||
currentConfiguration,
|
||||
'LineChartConfiguration',
|
||||
);
|
||||
|
||||
const wasPieChart = isWidgetConfigurationOfType(
|
||||
currentConfiguration,
|
||||
'PieChartConfiguration',
|
||||
);
|
||||
|
||||
if (isPieChart && wasBarOrLineChart) {
|
||||
configToUpdate = {
|
||||
@@ -128,6 +150,20 @@ export const useGetConfigToUpdateAfterGraphTypeChange = ({
|
||||
};
|
||||
}
|
||||
|
||||
if (isHorizontalBarChart) {
|
||||
configToUpdate = {
|
||||
...configToUpdate,
|
||||
layout: BarChartLayout.HORIZONTAL,
|
||||
};
|
||||
}
|
||||
|
||||
if (isVerticalBarChart) {
|
||||
configToUpdate = {
|
||||
...configToUpdate,
|
||||
layout: BarChartLayout.VERTICAL,
|
||||
};
|
||||
}
|
||||
|
||||
const activeTabId = snapshot.getLoadable(activeTabIdState).getValue();
|
||||
|
||||
if (isDefined(activeTabId) && isDefined(currentlyEditingWidgetId)) {
|
||||
@@ -135,12 +171,12 @@ export const useGetConfigToUpdateAfterGraphTypeChange = ({
|
||||
.getLoadable(pageLayoutCurrentLayoutsState)
|
||||
.getValue();
|
||||
|
||||
const updatedLayouts = updateWidgetMinimumSizeForGraphType(
|
||||
graphType,
|
||||
currentlyEditingWidgetId,
|
||||
activeTabId,
|
||||
const updatedLayouts = updateWidgetMinimumSizeForGraphType({
|
||||
configurationType: newConfigurationType,
|
||||
widgetId: currentlyEditingWidgetId,
|
||||
tabId: activeTabId,
|
||||
currentLayouts,
|
||||
);
|
||||
});
|
||||
|
||||
set(pageLayoutCurrentLayoutsState, updatedLayouts);
|
||||
}
|
||||
|
||||
+10
-12
@@ -1,14 +1,12 @@
|
||||
import {
|
||||
type AggregateChartConfiguration,
|
||||
type BarChartConfiguration,
|
||||
type GaugeChartConfiguration,
|
||||
type LineChartConfiguration,
|
||||
type PieChartConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
import { type TypedGaugeChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedGaugeChartConfiguration';
|
||||
import { type TypedAggregateChartConfiguration } from './TypedAggregateChartConfiguration';
|
||||
import { type TypedBarChartConfiguration } from './TypedBarChartConfiguration';
|
||||
import { type TypedLineChartConfiguration } from './TypedLineChartConfiguration';
|
||||
import { type TypedPieChartConfiguration } from './TypedPieChartConfiguration';
|
||||
|
||||
export type ChartConfiguration =
|
||||
| BarChartConfiguration
|
||||
| LineChartConfiguration
|
||||
| PieChartConfiguration
|
||||
| AggregateChartConfiguration
|
||||
| GaugeChartConfiguration;
|
||||
| TypedBarChartConfiguration
|
||||
| TypedLineChartConfiguration
|
||||
| TypedPieChartConfiguration
|
||||
| TypedAggregateChartConfiguration
|
||||
| TypedGaugeChartConfiguration;
|
||||
|
||||
+1
-5
@@ -1,4 +1,3 @@
|
||||
import { type ChartFilters } from '@/command-menu/pages/page-layout/types/ChartFilters';
|
||||
import { type ChartWidgetConfiguration } from '@/command-menu/pages/page-layout/types/ChartWidgetConfiguration';
|
||||
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
|
||||
import { type ModifiedProperties } from 'twenty-shared/types';
|
||||
@@ -8,9 +7,6 @@ export type ChartWidget = ModifiedProperties<
|
||||
PageLayoutWidget,
|
||||
{
|
||||
type: WidgetType.GRAPH;
|
||||
configuration: ModifiedProperties<
|
||||
ChartWidgetConfiguration,
|
||||
{ filter?: ChartFilters }
|
||||
>;
|
||||
configuration: ChartWidgetConfiguration;
|
||||
}
|
||||
>;
|
||||
|
||||
+10
-12
@@ -1,14 +1,12 @@
|
||||
import {
|
||||
type AggregateChartConfiguration,
|
||||
type BarChartConfiguration,
|
||||
type GaugeChartConfiguration,
|
||||
type LineChartConfiguration,
|
||||
type PieChartConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
import { type TypedAggregateChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedAggregateChartConfiguration';
|
||||
import { type TypedBarChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedBarChartConfiguration';
|
||||
import { type TypedGaugeChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedGaugeChartConfiguration';
|
||||
import { type TypedLineChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedLineChartConfiguration';
|
||||
import { type TypedPieChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedPieChartConfiguration';
|
||||
|
||||
export type ChartWidgetConfiguration =
|
||||
| BarChartConfiguration
|
||||
| GaugeChartConfiguration
|
||||
| LineChartConfiguration
|
||||
| AggregateChartConfiguration
|
||||
| PieChartConfiguration;
|
||||
| TypedBarChartConfiguration
|
||||
| TypedGaugeChartConfiguration
|
||||
| TypedLineChartConfiguration
|
||||
| TypedAggregateChartConfiguration
|
||||
| TypedPieChartConfiguration;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
export enum GraphType {
|
||||
VERTICAL_BAR = 'VERTICAL_BAR',
|
||||
HORIZONTAL_BAR = 'HORIZONTAL_BAR',
|
||||
LINE = 'LINE',
|
||||
PIE = 'PIE',
|
||||
AGGREGATE = 'AGGREGATE',
|
||||
GAUGE = 'GAUGE',
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import {
|
||||
type AggregateChartConfiguration,
|
||||
type WidgetConfigurationType,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
export type TypedAggregateChartConfiguration = AggregateChartConfiguration & {
|
||||
configurationType: WidgetConfigurationType.AGGREGATE_CHART;
|
||||
};
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import {
|
||||
type BarChartConfiguration,
|
||||
type WidgetConfigurationType,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
export type TypedBarChartConfiguration = BarChartConfiguration & {
|
||||
configurationType: WidgetConfigurationType.BAR_CHART;
|
||||
};
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import {
|
||||
type GaugeChartConfiguration,
|
||||
type WidgetConfigurationType,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
export type TypedGaugeChartConfiguration = GaugeChartConfiguration & {
|
||||
configurationType: WidgetConfigurationType.GAUGE_CHART;
|
||||
};
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import {
|
||||
type LineChartConfiguration,
|
||||
type WidgetConfigurationType,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
export type TypedLineChartConfiguration = LineChartConfiguration & {
|
||||
configurationType: WidgetConfigurationType.LINE_CHART;
|
||||
};
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import {
|
||||
type PieChartConfiguration,
|
||||
type WidgetConfigurationType,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
export type TypedPieChartConfiguration = PieChartConfiguration & {
|
||||
configurationType: WidgetConfigurationType.PIE_CHART;
|
||||
};
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
import { assertChartWidgetOrThrow } from '@/command-menu/pages/page-layout/utils/assertChartWidgetOrThrow';
|
||||
import {
|
||||
ALL_CHART_CONFIGURATIONS,
|
||||
createTestWidget,
|
||||
TEST_BAR_CHART_CONFIGURATION,
|
||||
TEST_IFRAME_CONFIGURATION,
|
||||
} from '~/testing/mock-data/widget-configurations';
|
||||
|
||||
describe('assertChartWidgetOrThrow', () => {
|
||||
it('does not throw for valid chart widget', () => {
|
||||
const widget = createTestWidget({
|
||||
configuration: TEST_BAR_CHART_CONFIGURATION,
|
||||
});
|
||||
|
||||
expect(() => assertChartWidgetOrThrow(widget)).not.toThrow();
|
||||
});
|
||||
|
||||
it('throws when objectMetadataId is missing', () => {
|
||||
const widget = createTestWidget({ objectMetadataId: undefined });
|
||||
|
||||
expect(() => assertChartWidgetOrThrow(widget)).toThrow(
|
||||
'Widget objectMetadataId is required',
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when objectMetadataId is null', () => {
|
||||
const widget = createTestWidget({ objectMetadataId: null });
|
||||
|
||||
expect(() => assertChartWidgetOrThrow(widget)).toThrow(
|
||||
'Widget objectMetadataId is required',
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when configuration is not a valid chart type', () => {
|
||||
const widget = createTestWidget({
|
||||
configuration: TEST_IFRAME_CONFIGURATION,
|
||||
});
|
||||
|
||||
expect(() => assertChartWidgetOrThrow(widget)).toThrow(
|
||||
'Expected chart configuration but got IframeConfiguration',
|
||||
);
|
||||
});
|
||||
|
||||
it('passes for all valid chart types', () => {
|
||||
ALL_CHART_CONFIGURATIONS.forEach((config) => {
|
||||
const widget = createTestWidget({ configuration: config });
|
||||
|
||||
expect(() => assertChartWidgetOrThrow(widget)).not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
+11
-6
@@ -1,9 +1,10 @@
|
||||
import { type TypedBarChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedBarChartConfiguration';
|
||||
import { type TypedPieChartConfiguration } from '@/command-menu/pages/page-layout/types/TypedPieChartConfiguration';
|
||||
import { ObjectRecordGroupByDateGranularity } from 'twenty-shared/types';
|
||||
import {
|
||||
type BarChartConfiguration,
|
||||
BarChartGroupMode,
|
||||
GraphOrderBy,
|
||||
type PieChartConfiguration,
|
||||
WidgetConfigurationType,
|
||||
} from '~/generated/graphql';
|
||||
import { buildChartGroupByFieldConfigUpdate } from '@/command-menu/pages/page-layout/utils/buildChartGroupByFieldConfigUpdate';
|
||||
|
||||
@@ -12,7 +13,8 @@ describe('buildChartGroupByFieldConfigUpdate', () => {
|
||||
const result = buildChartGroupByFieldConfigUpdate({
|
||||
configuration: {
|
||||
__typename: 'BarChartConfiguration',
|
||||
} as BarChartConfiguration,
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
} as TypedBarChartConfiguration,
|
||||
fieldMetadataIdKey: 'primaryAxisGroupByFieldMetadataId',
|
||||
subFieldNameKey: 'primaryAxisGroupBySubFieldName',
|
||||
fieldId: 'field',
|
||||
@@ -29,7 +31,8 @@ describe('buildChartGroupByFieldConfigUpdate', () => {
|
||||
const result = buildChartGroupByFieldConfigUpdate({
|
||||
configuration: {
|
||||
__typename: 'BarChartConfiguration',
|
||||
} as BarChartConfiguration,
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
} as TypedBarChartConfiguration,
|
||||
fieldMetadataIdKey: 'primaryAxisGroupByFieldMetadataId',
|
||||
subFieldNameKey: 'primaryAxisGroupBySubFieldName',
|
||||
fieldId: null,
|
||||
@@ -46,7 +49,8 @@ describe('buildChartGroupByFieldConfigUpdate', () => {
|
||||
const result = buildChartGroupByFieldConfigUpdate({
|
||||
configuration: {
|
||||
__typename: 'BarChartConfiguration',
|
||||
} as BarChartConfiguration,
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
} as TypedBarChartConfiguration,
|
||||
fieldMetadataIdKey: 'secondaryAxisGroupByFieldMetadataId',
|
||||
subFieldNameKey: 'secondaryAxisGroupBySubFieldName',
|
||||
fieldId: 'field',
|
||||
@@ -62,7 +66,8 @@ describe('buildChartGroupByFieldConfigUpdate', () => {
|
||||
const result = buildChartGroupByFieldConfigUpdate({
|
||||
configuration: {
|
||||
__typename: 'PieChartConfiguration',
|
||||
} as PieChartConfiguration,
|
||||
configurationType: WidgetConfigurationType.PIE_CHART,
|
||||
} as TypedPieChartConfiguration,
|
||||
fieldMetadataIdKey: 'groupByFieldMetadataId',
|
||||
subFieldNameKey: 'groupBySubFieldName',
|
||||
fieldId: 'field',
|
||||
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { convertAggregateOperationForDateField } from '@/command-menu/pages/page-layout/utils/convertAggregateOperationForDateField';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { AggregateOperations } from '@/object-record/record-table/constants/AggregateOperations';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { TEST_BAR_CHART_CONFIGURATION } from '~/testing/mock-data/widget-configurations';
|
||||
|
||||
const createMockObjectMetadataItem = (
|
||||
fields: { id: string; type: FieldMetadataType }[],
|
||||
): ObjectMetadataItem =>
|
||||
({
|
||||
id: 'object-1',
|
||||
fields: fields.map((f) => ({ ...f, name: 'field' })),
|
||||
}) as ObjectMetadataItem;
|
||||
|
||||
describe('convertAggregateOperationForDateField', () => {
|
||||
it('returns COUNT when date field uses MIN operation', () => {
|
||||
const config: ChartConfiguration = {
|
||||
...TEST_BAR_CHART_CONFIGURATION,
|
||||
aggregateFieldMetadataId: 'date-field',
|
||||
aggregateOperation: AggregateOperations.MIN,
|
||||
};
|
||||
|
||||
const objectMetadataItem = createMockObjectMetadataItem([
|
||||
{ id: 'date-field', type: FieldMetadataType.DATE },
|
||||
]);
|
||||
|
||||
const result = convertAggregateOperationForDateField(
|
||||
config,
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(AggregateOperations.COUNT);
|
||||
});
|
||||
|
||||
it('returns COUNT when datetime field uses MAX operation', () => {
|
||||
const config: ChartConfiguration = {
|
||||
...TEST_BAR_CHART_CONFIGURATION,
|
||||
aggregateFieldMetadataId: 'datetime-field',
|
||||
aggregateOperation: AggregateOperations.MAX,
|
||||
};
|
||||
|
||||
const objectMetadataItem = createMockObjectMetadataItem([
|
||||
{ id: 'datetime-field', type: FieldMetadataType.DATE_TIME },
|
||||
]);
|
||||
|
||||
const result = convertAggregateOperationForDateField(
|
||||
config,
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBe(AggregateOperations.COUNT);
|
||||
});
|
||||
|
||||
it('returns undefined when field is not a date type', () => {
|
||||
const config: ChartConfiguration = {
|
||||
...TEST_BAR_CHART_CONFIGURATION,
|
||||
aggregateFieldMetadataId: 'number-field',
|
||||
aggregateOperation: AggregateOperations.MIN,
|
||||
};
|
||||
|
||||
const objectMetadataItem = createMockObjectMetadataItem([
|
||||
{ id: 'number-field', type: FieldMetadataType.NUMBER },
|
||||
]);
|
||||
|
||||
const result = convertAggregateOperationForDateField(
|
||||
config,
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns undefined when operation is not MIN or MAX', () => {
|
||||
const config: ChartConfiguration = {
|
||||
...TEST_BAR_CHART_CONFIGURATION,
|
||||
aggregateFieldMetadataId: 'date-field',
|
||||
aggregateOperation: AggregateOperations.SUM,
|
||||
};
|
||||
|
||||
const objectMetadataItem = createMockObjectMetadataItem([
|
||||
{ id: 'date-field', type: FieldMetadataType.DATE },
|
||||
]);
|
||||
|
||||
const result = convertAggregateOperationForDateField(
|
||||
config,
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns undefined when objectMetadataItem is undefined', () => {
|
||||
const config: ChartConfiguration = {
|
||||
...TEST_BAR_CHART_CONFIGURATION,
|
||||
aggregateOperation: AggregateOperations.MIN,
|
||||
};
|
||||
|
||||
const result = convertAggregateOperationForDateField(config, undefined);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('returns undefined when field is not found', () => {
|
||||
const config: ChartConfiguration = {
|
||||
...TEST_BAR_CHART_CONFIGURATION,
|
||||
aggregateFieldMetadataId: 'missing-field',
|
||||
aggregateOperation: AggregateOperations.MIN,
|
||||
};
|
||||
|
||||
const objectMetadataItem = createMockObjectMetadataItem([
|
||||
{ id: 'other-field', type: FieldMetadataType.DATE },
|
||||
]);
|
||||
|
||||
const result = convertAggregateOperationForDateField(
|
||||
config,
|
||||
objectMetadataItem,
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
});
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
import { convertBarOrLineChartConfigToPieChart } from '@/command-menu/pages/page-layout/utils/convertBarOrLineChartConfigToPieChart';
|
||||
import { type BarChartConfiguration } from '~/generated/graphql';
|
||||
import {
|
||||
TEST_BAR_CHART_CONFIGURATION,
|
||||
TEST_LINE_CHART_CONFIGURATION,
|
||||
TEST_PIE_CHART_CONFIGURATION,
|
||||
} from '~/testing/mock-data/widget-configurations';
|
||||
|
||||
describe('convertBarOrLineChartConfigToPieChart', () => {
|
||||
it('maps bar chart fields to pie chart equivalents', () => {
|
||||
const result = convertBarOrLineChartConfigToPieChart(
|
||||
TEST_BAR_CHART_CONFIGURATION,
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
groupByFieldMetadataId:
|
||||
TEST_BAR_CHART_CONFIGURATION.primaryAxisGroupByFieldMetadataId,
|
||||
groupBySubFieldName:
|
||||
TEST_BAR_CHART_CONFIGURATION.primaryAxisGroupBySubFieldName,
|
||||
dateGranularity: TEST_BAR_CHART_CONFIGURATION.primaryAxisDateGranularity,
|
||||
orderBy: TEST_BAR_CHART_CONFIGURATION.primaryAxisOrderBy,
|
||||
});
|
||||
});
|
||||
|
||||
it('maps line chart fields to pie chart equivalents', () => {
|
||||
const result = convertBarOrLineChartConfigToPieChart(
|
||||
TEST_LINE_CHART_CONFIGURATION,
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
groupByFieldMetadataId:
|
||||
TEST_LINE_CHART_CONFIGURATION.primaryAxisGroupByFieldMetadataId,
|
||||
groupBySubFieldName:
|
||||
TEST_LINE_CHART_CONFIGURATION.primaryAxisGroupBySubFieldName,
|
||||
dateGranularity: TEST_LINE_CHART_CONFIGURATION.primaryAxisDateGranularity,
|
||||
orderBy: TEST_LINE_CHART_CONFIGURATION.primaryAxisOrderBy,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns empty object for non-bar/line chart configuration', () => {
|
||||
const result = convertBarOrLineChartConfigToPieChart(
|
||||
TEST_PIE_CHART_CONFIGURATION as unknown as BarChartConfiguration,
|
||||
);
|
||||
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
import { convertPieChartConfigToBarOrLineChart } from '@/command-menu/pages/page-layout/utils/convertPieChartConfigToBarOrLineChart';
|
||||
import { type PieChartConfiguration } from '~/generated/graphql';
|
||||
import {
|
||||
TEST_BAR_CHART_CONFIGURATION,
|
||||
TEST_PIE_CHART_CONFIGURATION,
|
||||
} from '~/testing/mock-data/widget-configurations';
|
||||
|
||||
describe('convertPieChartConfigToBarOrLineChart', () => {
|
||||
it('maps pie chart fields to bar/line chart equivalents', () => {
|
||||
const result = convertPieChartConfigToBarOrLineChart(
|
||||
TEST_PIE_CHART_CONFIGURATION,
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
primaryAxisGroupByFieldMetadataId:
|
||||
TEST_PIE_CHART_CONFIGURATION.groupByFieldMetadataId,
|
||||
primaryAxisGroupBySubFieldName:
|
||||
TEST_PIE_CHART_CONFIGURATION.groupBySubFieldName,
|
||||
primaryAxisDateGranularity: TEST_PIE_CHART_CONFIGURATION.dateGranularity,
|
||||
primaryAxisOrderBy: TEST_PIE_CHART_CONFIGURATION.orderBy,
|
||||
});
|
||||
});
|
||||
|
||||
it('handles null/undefined fields', () => {
|
||||
const minimalPieConfig: PieChartConfiguration = {
|
||||
...TEST_PIE_CHART_CONFIGURATION,
|
||||
groupByFieldMetadataId: undefined as unknown as string,
|
||||
groupBySubFieldName: null,
|
||||
dateGranularity: null,
|
||||
orderBy: null,
|
||||
};
|
||||
|
||||
const result = convertPieChartConfigToBarOrLineChart(minimalPieConfig);
|
||||
|
||||
expect(result).toEqual({
|
||||
primaryAxisGroupByFieldMetadataId: undefined,
|
||||
primaryAxisGroupBySubFieldName: null,
|
||||
primaryAxisDateGranularity: null,
|
||||
primaryAxisOrderBy: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns empty object for non-pie chart configuration', () => {
|
||||
const result = convertPieChartConfigToBarOrLineChart(
|
||||
TEST_BAR_CHART_CONFIGURATION as unknown as PieChartConfiguration,
|
||||
);
|
||||
|
||||
expect(result).toEqual({});
|
||||
});
|
||||
});
|
||||
+12
-12
@@ -17,14 +17,14 @@ import { RANGE_MIN_SETTING } from '@/command-menu/pages/page-layout/constants/se
|
||||
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 { STACKED_BARS_SETTING } from '@/command-menu/pages/page-layout/constants/settings/StackedBarsSetting';
|
||||
import { IconAxisX, IconAxisY } from 'twenty-ui/display';
|
||||
import { GraphType } from '~/generated-metadata/graphql';
|
||||
import { getBarChartSettings } from '@/command-menu/pages/page-layout/utils/getBarChartSettings';
|
||||
import { IconAxisX, IconAxisY } from 'twenty-ui/display';
|
||||
import { BarChartLayout } from '~/generated/graphql';
|
||||
|
||||
describe('getBarChartSettings', () => {
|
||||
describe('Vertical bar chart', () => {
|
||||
it('should place primary axis items under "X axis" heading', () => {
|
||||
const result = getBarChartSettings(GraphType.VERTICAL_BAR);
|
||||
const result = getBarChartSettings(BarChartLayout.VERTICAL);
|
||||
|
||||
const xAxisGroup = result.find(
|
||||
(group) => group.heading.id === CHART_SETTINGS_HEADINGS.X_AXIS.id,
|
||||
@@ -41,7 +41,7 @@ describe('getBarChartSettings', () => {
|
||||
});
|
||||
|
||||
it('should place secondary axis items under "Y axis" heading', () => {
|
||||
const result = getBarChartSettings(GraphType.VERTICAL_BAR);
|
||||
const result = getBarChartSettings(BarChartLayout.VERTICAL);
|
||||
|
||||
const yAxisGroup = result.find(
|
||||
(group) => group.heading.id === CHART_SETTINGS_HEADINGS.Y_AXIS.id,
|
||||
@@ -61,7 +61,7 @@ describe('getBarChartSettings', () => {
|
||||
});
|
||||
|
||||
it('should have all expected groups in correct order', () => {
|
||||
const result = getBarChartSettings(GraphType.VERTICAL_BAR);
|
||||
const result = getBarChartSettings(BarChartLayout.VERTICAL);
|
||||
|
||||
expect(result).toHaveLength(4);
|
||||
expect(result[0].heading).toBe(CHART_SETTINGS_HEADINGS.DATA);
|
||||
@@ -73,7 +73,7 @@ describe('getBarChartSettings', () => {
|
||||
|
||||
describe('Horizontal bar chart', () => {
|
||||
it('should place SECONDARY axis items under "X axis" heading', () => {
|
||||
const result = getBarChartSettings(GraphType.HORIZONTAL_BAR);
|
||||
const result = getBarChartSettings(BarChartLayout.HORIZONTAL);
|
||||
|
||||
const xAxisGroup = result.find(
|
||||
(group) => group.heading.id === CHART_SETTINGS_HEADINGS.X_AXIS.id,
|
||||
@@ -93,7 +93,7 @@ describe('getBarChartSettings', () => {
|
||||
});
|
||||
|
||||
it('should place PRIMARY axis items under "Y axis" heading', () => {
|
||||
const result = getBarChartSettings(GraphType.HORIZONTAL_BAR);
|
||||
const result = getBarChartSettings(BarChartLayout.HORIZONTAL);
|
||||
|
||||
const yAxisGroup = result.find(
|
||||
(group) => group.heading.id === CHART_SETTINGS_HEADINGS.Y_AXIS.id,
|
||||
@@ -110,7 +110,7 @@ describe('getBarChartSettings', () => {
|
||||
});
|
||||
|
||||
it('should have all expected groups in correct order', () => {
|
||||
const result = getBarChartSettings(GraphType.HORIZONTAL_BAR);
|
||||
const result = getBarChartSettings(BarChartLayout.HORIZONTAL);
|
||||
|
||||
expect(result).toHaveLength(4);
|
||||
expect(result[0].heading).toBe(CHART_SETTINGS_HEADINGS.DATA);
|
||||
@@ -122,8 +122,8 @@ describe('getBarChartSettings', () => {
|
||||
|
||||
describe('Common groups', () => {
|
||||
it('should have consistent Data group for both orientations', () => {
|
||||
const verticalResult = getBarChartSettings(GraphType.VERTICAL_BAR);
|
||||
const horizontalResult = getBarChartSettings(GraphType.HORIZONTAL_BAR);
|
||||
const verticalResult = getBarChartSettings(BarChartLayout.VERTICAL);
|
||||
const horizontalResult = getBarChartSettings(BarChartLayout.HORIZONTAL);
|
||||
|
||||
const verticalDataGroup = verticalResult.find(
|
||||
(group) => group.heading.id === CHART_SETTINGS_HEADINGS.DATA.id,
|
||||
@@ -140,8 +140,8 @@ describe('getBarChartSettings', () => {
|
||||
});
|
||||
|
||||
it('should have consistent Style group for both orientations', () => {
|
||||
const verticalResult = getBarChartSettings(GraphType.VERTICAL_BAR);
|
||||
const horizontalResult = getBarChartSettings(GraphType.HORIZONTAL_BAR);
|
||||
const verticalResult = getBarChartSettings(BarChartLayout.VERTICAL);
|
||||
const horizontalResult = getBarChartSettings(BarChartLayout.HORIZONTAL);
|
||||
|
||||
const verticalStyleGroup = verticalResult.find(
|
||||
(group) => group.heading.id === CHART_SETTINGS_HEADINGS.STYLE.id,
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
import { getChartLimitMessage } from '@/command-menu/pages/page-layout/utils/getChartLimitMessage';
|
||||
import { ObjectRecordGroupByDateGranularity } from 'twenty-shared/types';
|
||||
import { WidgetConfigurationType } from '~/generated/graphql';
|
||||
|
||||
describe('getChartLimitMessage', () => {
|
||||
it('returns date-based message for bar chart with date axis', () => {
|
||||
const result = getChartLimitMessage({
|
||||
widgetConfigurationType: WidgetConfigurationType.BAR_CHART,
|
||||
isPrimaryAxisDate: true,
|
||||
primaryAxisDateGranularity: ObjectRecordGroupByDateGranularity.DAY,
|
||||
});
|
||||
|
||||
expect(result).toContain('Undisplayed data');
|
||||
expect(result).toContain('days');
|
||||
expect(result).toContain('per chart');
|
||||
});
|
||||
|
||||
it('returns bars message for bar chart without date axis', () => {
|
||||
const result = getChartLimitMessage({
|
||||
widgetConfigurationType: WidgetConfigurationType.BAR_CHART,
|
||||
isPrimaryAxisDate: false,
|
||||
primaryAxisDateGranularity: null,
|
||||
});
|
||||
|
||||
expect(result).toContain('bars per chart');
|
||||
});
|
||||
|
||||
it('returns data points message for line chart without date axis', () => {
|
||||
const result = getChartLimitMessage({
|
||||
widgetConfigurationType: WidgetConfigurationType.LINE_CHART,
|
||||
isPrimaryAxisDate: false,
|
||||
primaryAxisDateGranularity: null,
|
||||
});
|
||||
|
||||
expect(result).toContain('data points per chart');
|
||||
});
|
||||
|
||||
it('returns slices message for pie chart', () => {
|
||||
const result = getChartLimitMessage({
|
||||
widgetConfigurationType: WidgetConfigurationType.PIE_CHART,
|
||||
isPrimaryAxisDate: false,
|
||||
primaryAxisDateGranularity: null,
|
||||
});
|
||||
|
||||
expect(result).toContain('slices per chart');
|
||||
});
|
||||
|
||||
it('returns date-based message with weeks granularity', () => {
|
||||
const result = getChartLimitMessage({
|
||||
widgetConfigurationType: WidgetConfigurationType.LINE_CHART,
|
||||
isPrimaryAxisDate: true,
|
||||
primaryAxisDateGranularity: ObjectRecordGroupByDateGranularity.WEEK,
|
||||
});
|
||||
|
||||
expect(result).toContain('weeks');
|
||||
});
|
||||
|
||||
it('returns slices message when isPrimaryAxisDate is true but granularity is null', () => {
|
||||
const result = getChartLimitMessage({
|
||||
widgetConfigurationType: WidgetConfigurationType.PIE_CHART,
|
||||
isPrimaryAxisDate: true,
|
||||
primaryAxisDateGranularity: null,
|
||||
});
|
||||
|
||||
expect(result).toContain('slices per chart');
|
||||
});
|
||||
});
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
import { GraphType } from '@/command-menu/pages/page-layout/types/GraphType';
|
||||
import { getConfigurationTypeFromGraphType } from '@/command-menu/pages/page-layout/utils/getConfigurationTypeFromGraphType';
|
||||
import { WidgetConfigurationType } from '~/generated/graphql';
|
||||
|
||||
describe('getConfigurationTypeFromGraphType', () => {
|
||||
it('returns BAR_CHART for VERTICAL_BAR', () => {
|
||||
expect(getConfigurationTypeFromGraphType(GraphType.VERTICAL_BAR)).toBe(
|
||||
WidgetConfigurationType.BAR_CHART,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns BAR_CHART for HORIZONTAL_BAR', () => {
|
||||
expect(getConfigurationTypeFromGraphType(GraphType.HORIZONTAL_BAR)).toBe(
|
||||
WidgetConfigurationType.BAR_CHART,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns LINE_CHART for LINE', () => {
|
||||
expect(getConfigurationTypeFromGraphType(GraphType.LINE)).toBe(
|
||||
WidgetConfigurationType.LINE_CHART,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns PIE_CHART for PIE', () => {
|
||||
expect(getConfigurationTypeFromGraphType(GraphType.PIE)).toBe(
|
||||
WidgetConfigurationType.PIE_CHART,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns AGGREGATE_CHART for AGGREGATE', () => {
|
||||
expect(getConfigurationTypeFromGraphType(GraphType.AGGREGATE)).toBe(
|
||||
WidgetConfigurationType.AGGREGATE_CHART,
|
||||
);
|
||||
});
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { GraphType } from '@/command-menu/pages/page-layout/types/GraphType';
|
||||
import { getCurrentGraphTypeFromConfig } from '@/command-menu/pages/page-layout/utils/getCurrentGraphTypeFromConfig';
|
||||
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';
|
||||
|
||||
describe('getCurrentGraphTypeFromConfig', () => {
|
||||
it('returns VERTICAL_BAR for bar chart with vertical layout', () => {
|
||||
expect(
|
||||
getCurrentGraphTypeFromConfig(
|
||||
TEST_BAR_CHART_CONFIGURATION as ChartConfiguration,
|
||||
),
|
||||
).toBe(GraphType.VERTICAL_BAR);
|
||||
});
|
||||
|
||||
it('returns HORIZONTAL_BAR for bar chart with horizontal layout', () => {
|
||||
expect(
|
||||
getCurrentGraphTypeFromConfig(
|
||||
TEST_BAR_CHART_CONFIGURATION_HORIZONTAL as ChartConfiguration,
|
||||
),
|
||||
).toBe(GraphType.HORIZONTAL_BAR);
|
||||
});
|
||||
|
||||
it('returns LINE for line chart', () => {
|
||||
expect(
|
||||
getCurrentGraphTypeFromConfig(
|
||||
TEST_LINE_CHART_CONFIGURATION as ChartConfiguration,
|
||||
),
|
||||
).toBe(GraphType.LINE);
|
||||
});
|
||||
|
||||
it('returns PIE for pie chart', () => {
|
||||
expect(
|
||||
getCurrentGraphTypeFromConfig(
|
||||
TEST_PIE_CHART_CONFIGURATION as ChartConfiguration,
|
||||
),
|
||||
).toBe(GraphType.PIE);
|
||||
});
|
||||
|
||||
it('returns AGGREGATE for aggregate chart', () => {
|
||||
expect(
|
||||
getCurrentGraphTypeFromConfig(
|
||||
TEST_AGGREGATE_CHART_CONFIGURATION as ChartConfiguration,
|
||||
),
|
||||
).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',
|
||||
} as unknown as ChartConfiguration;
|
||||
|
||||
expect(() => getCurrentGraphTypeFromConfig(unknownConfig)).toThrow(
|
||||
'Unknown chart configuration type',
|
||||
);
|
||||
});
|
||||
});
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
import { getDateGranularityPluralLabel } from '@/command-menu/pages/page-layout/utils/getDateGranularityPluralLabel';
|
||||
import { ObjectRecordGroupByDateGranularity } from 'twenty-shared/types';
|
||||
|
||||
describe('getDateGranularityPluralLabel', () => {
|
||||
it('returns "days" for DAY granularity', () => {
|
||||
expect(
|
||||
getDateGranularityPluralLabel(ObjectRecordGroupByDateGranularity.DAY),
|
||||
).toBe('days');
|
||||
});
|
||||
|
||||
it('returns "weeks" for WEEK granularity', () => {
|
||||
expect(
|
||||
getDateGranularityPluralLabel(ObjectRecordGroupByDateGranularity.WEEK),
|
||||
).toBe('weeks');
|
||||
});
|
||||
|
||||
it('returns "months" for MONTH granularity', () => {
|
||||
expect(
|
||||
getDateGranularityPluralLabel(ObjectRecordGroupByDateGranularity.MONTH),
|
||||
).toBe('months');
|
||||
});
|
||||
|
||||
it('returns "quarters" for QUARTER granularity', () => {
|
||||
expect(
|
||||
getDateGranularityPluralLabel(ObjectRecordGroupByDateGranularity.QUARTER),
|
||||
).toBe('quarters');
|
||||
});
|
||||
|
||||
it('returns "years" for YEAR granularity', () => {
|
||||
expect(
|
||||
getDateGranularityPluralLabel(ObjectRecordGroupByDateGranularity.YEAR),
|
||||
).toBe('years');
|
||||
});
|
||||
|
||||
it('returns "days" for DAY_OF_THE_WEEK granularity', () => {
|
||||
expect(
|
||||
getDateGranularityPluralLabel(
|
||||
ObjectRecordGroupByDateGranularity.DAY_OF_THE_WEEK,
|
||||
),
|
||||
).toBe('days');
|
||||
});
|
||||
|
||||
it('returns "months" for MONTH_OF_THE_YEAR granularity', () => {
|
||||
expect(
|
||||
getDateGranularityPluralLabel(
|
||||
ObjectRecordGroupByDateGranularity.MONTH_OF_THE_YEAR,
|
||||
),
|
||||
).toBe('months');
|
||||
});
|
||||
|
||||
it('returns "quarters" for QUARTER_OF_THE_YEAR granularity', () => {
|
||||
expect(
|
||||
getDateGranularityPluralLabel(
|
||||
ObjectRecordGroupByDateGranularity.QUARTER_OF_THE_YEAR,
|
||||
),
|
||||
).toBe('quarters');
|
||||
});
|
||||
|
||||
it('returns "items" for NONE granularity', () => {
|
||||
expect(
|
||||
getDateGranularityPluralLabel(ObjectRecordGroupByDateGranularity.NONE),
|
||||
).toBe('items');
|
||||
});
|
||||
});
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
import {
|
||||
type AggregateChartConfiguration,
|
||||
type BarChartConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
import { isAggregateChartConfiguration } from '@/command-menu/pages/page-layout/utils/isAggregateChartConfiguration';
|
||||
|
||||
describe('isAggregateChartConfiguration', () => {
|
||||
it('should return true for AggregateChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'AggregateChartConfiguration',
|
||||
} as AggregateChartConfiguration;
|
||||
|
||||
expect(isAggregateChartConfiguration(configuration)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for BarChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
} as BarChartConfiguration;
|
||||
|
||||
expect(isAggregateChartConfiguration(configuration)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null', () => {
|
||||
expect(isAggregateChartConfiguration(null)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for undefined', () => {
|
||||
expect(isAggregateChartConfiguration(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
import {
|
||||
type BarChartConfiguration,
|
||||
type LineChartConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
import { isBarChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarChartConfiguration';
|
||||
|
||||
describe('isBarChartConfiguration', () => {
|
||||
it('should return true for BarChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'BarChartConfiguration' as const,
|
||||
} as BarChartConfiguration;
|
||||
|
||||
expect(isBarChartConfiguration(configuration)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for LineChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'LineChartConfiguration' as const,
|
||||
} as LineChartConfiguration;
|
||||
|
||||
expect(isBarChartConfiguration(configuration)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null', () => {
|
||||
expect(isBarChartConfiguration(null)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for undefined', () => {
|
||||
expect(isBarChartConfiguration(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
import {
|
||||
type BarChartConfiguration,
|
||||
type LineChartConfiguration,
|
||||
type PieChartConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
import { isBarOrLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarOrLineChartConfiguration';
|
||||
|
||||
describe('isBarOrLineChartConfiguration', () => {
|
||||
it('should return true for BarChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
} as BarChartConfiguration;
|
||||
|
||||
expect(isBarOrLineChartConfiguration(configuration)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for LineChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'LineChartConfiguration',
|
||||
} as LineChartConfiguration;
|
||||
|
||||
expect(isBarOrLineChartConfiguration(configuration)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for PieChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'PieChartConfiguration',
|
||||
} as PieChartConfiguration;
|
||||
|
||||
expect(isBarOrLineChartConfiguration(configuration)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null', () => {
|
||||
expect(isBarOrLineChartConfiguration(null)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for undefined', () => {
|
||||
expect(isBarOrLineChartConfiguration(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
-76
@@ -1,76 +0,0 @@
|
||||
import {
|
||||
type AggregateChartConfiguration,
|
||||
type BarChartConfiguration,
|
||||
type GaugeChartConfiguration,
|
||||
type IframeConfiguration,
|
||||
type LineChartConfiguration,
|
||||
type PieChartConfiguration,
|
||||
type StandaloneRichTextConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
import { isChartConfiguration } from '@/command-menu/pages/page-layout/utils/isChartConfiguration';
|
||||
|
||||
describe('isChartConfiguration', () => {
|
||||
it('should return true for BarChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
} as BarChartConfiguration;
|
||||
|
||||
expect(isChartConfiguration(configuration)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for LineChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'LineChartConfiguration',
|
||||
} as LineChartConfiguration;
|
||||
|
||||
expect(isChartConfiguration(configuration)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for PieChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'PieChartConfiguration',
|
||||
} as PieChartConfiguration;
|
||||
|
||||
expect(isChartConfiguration(configuration)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for AggregateChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'AggregateChartConfiguration',
|
||||
} as AggregateChartConfiguration;
|
||||
|
||||
expect(isChartConfiguration(configuration)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true for GaugeChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'GaugeChartConfiguration',
|
||||
} as GaugeChartConfiguration;
|
||||
|
||||
expect(isChartConfiguration(configuration)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for IframeConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'IframeConfiguration',
|
||||
} as IframeConfiguration;
|
||||
|
||||
expect(isChartConfiguration(configuration)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for StandaloneRichTextConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'StandaloneRichTextConfiguration',
|
||||
} as StandaloneRichTextConfiguration;
|
||||
|
||||
expect(isChartConfiguration(configuration)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null', () => {
|
||||
expect(isChartConfiguration(null)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for undefined', () => {
|
||||
expect(isChartConfiguration(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
import { isChartWidget } from '@/command-menu/pages/page-layout/utils/isChartWidget';
|
||||
import {
|
||||
createTestWidget,
|
||||
TEST_BAR_CHART_CONFIGURATION,
|
||||
TEST_FIELDS_CONFIGURATION,
|
||||
TEST_IFRAME_CONFIGURATION,
|
||||
TEST_LINE_CHART_CONFIGURATION,
|
||||
TEST_PIE_CHART_CONFIGURATION,
|
||||
} from '~/testing/mock-data/widget-configurations';
|
||||
|
||||
describe('isChartWidget', () => {
|
||||
it('returns true for widget with BarChartConfiguration', () => {
|
||||
const widget = createTestWidget({
|
||||
configuration: TEST_BAR_CHART_CONFIGURATION,
|
||||
});
|
||||
|
||||
expect(isChartWidget(widget)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for widget with LineChartConfiguration', () => {
|
||||
const widget = createTestWidget({
|
||||
configuration: TEST_LINE_CHART_CONFIGURATION,
|
||||
});
|
||||
|
||||
expect(isChartWidget(widget)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns true for widget with PieChartConfiguration', () => {
|
||||
const widget = createTestWidget({
|
||||
configuration: TEST_PIE_CHART_CONFIGURATION,
|
||||
});
|
||||
|
||||
expect(isChartWidget(widget)).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false for widget with IframeConfiguration', () => {
|
||||
const widget = createTestWidget({
|
||||
configuration: TEST_IFRAME_CONFIGURATION,
|
||||
});
|
||||
|
||||
expect(isChartWidget(widget)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false for widget with FieldsConfiguration', () => {
|
||||
const widget = createTestWidget({
|
||||
configuration: TEST_FIELDS_CONFIGURATION,
|
||||
});
|
||||
|
||||
expect(isChartWidget(widget)).toBe(false);
|
||||
});
|
||||
});
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
import {
|
||||
type BarChartConfiguration,
|
||||
type GaugeChartConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
import { isGaugeChartConfiguration } from '@/command-menu/pages/page-layout/utils/isGaugeChartConfiguration';
|
||||
|
||||
describe('isGaugeChartConfiguration', () => {
|
||||
it('should return true for GaugeChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'GaugeChartConfiguration',
|
||||
} as GaugeChartConfiguration;
|
||||
|
||||
expect(isGaugeChartConfiguration(configuration)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for BarChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
} as BarChartConfiguration;
|
||||
|
||||
expect(isGaugeChartConfiguration(configuration)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null', () => {
|
||||
expect(isGaugeChartConfiguration(null)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for undefined', () => {
|
||||
expect(isGaugeChartConfiguration(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
import {
|
||||
type BarChartConfiguration,
|
||||
type IframeConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
import { isIframeConfiguration } from '@/command-menu/pages/page-layout/utils/isIframeConfiguration';
|
||||
|
||||
describe('isIframeConfiguration', () => {
|
||||
it('should return true for IframeConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'IframeConfiguration',
|
||||
} as IframeConfiguration;
|
||||
|
||||
expect(isIframeConfiguration(configuration)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for BarChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
} as BarChartConfiguration;
|
||||
|
||||
expect(isIframeConfiguration(configuration)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null', () => {
|
||||
expect(isIframeConfiguration(null)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for undefined', () => {
|
||||
expect(isIframeConfiguration(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
import {
|
||||
type BarChartConfiguration,
|
||||
type LineChartConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
import { isLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isLineChartConfiguration';
|
||||
|
||||
describe('isLineChartConfiguration', () => {
|
||||
it('should return true for LineChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'LineChartConfiguration',
|
||||
} as LineChartConfiguration;
|
||||
|
||||
expect(isLineChartConfiguration(configuration)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for BarChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
} as BarChartConfiguration;
|
||||
|
||||
expect(isLineChartConfiguration(configuration)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null', () => {
|
||||
expect(isLineChartConfiguration(null)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for undefined', () => {
|
||||
expect(isLineChartConfiguration(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
+19
-10
@@ -1,12 +1,13 @@
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||
import { isMinMaxRangeValid } from '@/command-menu/pages/page-layout/utils/isMinMaxRangeValid';
|
||||
import { GraphType } from '~/generated/graphql';
|
||||
import { BarChartLayout, WidgetConfigurationType } from '~/generated/graphql';
|
||||
|
||||
describe('isMinMaxRangeValid', () => {
|
||||
const mockConfiguration = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
layout: BarChartLayout.VERTICAL,
|
||||
rangeMin: 10,
|
||||
rangeMax: 100,
|
||||
} as ChartConfiguration;
|
||||
@@ -78,7 +79,8 @@ describe('isMinMaxRangeValid', () => {
|
||||
it('should be valid when new rangeMin is negative and greater than existing rangeMax', () => {
|
||||
const configWithNegatives = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
layout: BarChartLayout.VERTICAL,
|
||||
rangeMin: -100,
|
||||
rangeMax: -10,
|
||||
} as ChartConfiguration;
|
||||
@@ -101,7 +103,8 @@ describe('isMinMaxRangeValid', () => {
|
||||
it('should be valid when new rangeMin is zero and greater than existing rangeMax', () => {
|
||||
const configWithZero = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
layout: BarChartLayout.VERTICAL,
|
||||
rangeMin: 0,
|
||||
rangeMax: 100,
|
||||
} as ChartConfiguration;
|
||||
@@ -119,7 +122,8 @@ describe('isMinMaxRangeValid', () => {
|
||||
it('should be valid when setting rangeMin on configuration without any range values', () => {
|
||||
const emptyConfig = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
layout: BarChartLayout.VERTICAL,
|
||||
} as ChartConfiguration;
|
||||
|
||||
const result = isMinMaxRangeValid(
|
||||
@@ -134,7 +138,8 @@ describe('isMinMaxRangeValid', () => {
|
||||
it('should be valid when setting rangeMax on configuration without any range values', () => {
|
||||
const emptyConfig = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
layout: BarChartLayout.VERTICAL,
|
||||
} as ChartConfiguration;
|
||||
|
||||
const result = isMinMaxRangeValid(
|
||||
@@ -149,7 +154,8 @@ describe('isMinMaxRangeValid', () => {
|
||||
it('should be valid when setting rangeMin without existing rangeMax', () => {
|
||||
const configWithOnlyMin = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
layout: BarChartLayout.VERTICAL,
|
||||
rangeMin: 10,
|
||||
} as ChartConfiguration;
|
||||
|
||||
@@ -165,7 +171,8 @@ describe('isMinMaxRangeValid', () => {
|
||||
it('should be valid when setting rangeMax without existing rangeMin', () => {
|
||||
const configWithOnlyMax = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
layout: BarChartLayout.VERTICAL,
|
||||
rangeMax: 100,
|
||||
} as ChartConfiguration;
|
||||
|
||||
@@ -181,7 +188,8 @@ describe('isMinMaxRangeValid', () => {
|
||||
it('should be invalid when setting rangeMin that would exceed existing rangeMax', () => {
|
||||
const configWithOnlyMax = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
layout: BarChartLayout.VERTICAL,
|
||||
rangeMax: 100,
|
||||
} as ChartConfiguration;
|
||||
|
||||
@@ -197,7 +205,8 @@ describe('isMinMaxRangeValid', () => {
|
||||
it('should be invalid when setting rangeMax that would be less than existing rangeMin', () => {
|
||||
const configWithOnlyMin = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
graphType: GraphType.VERTICAL_BAR,
|
||||
configurationType: WidgetConfigurationType.BAR_CHART,
|
||||
layout: BarChartLayout.VERTICAL,
|
||||
rangeMin: 50,
|
||||
} as ChartConfiguration;
|
||||
|
||||
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
import {
|
||||
type BarChartConfiguration,
|
||||
type PieChartConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
import { isPieChartConfiguration } from '@/command-menu/pages/page-layout/utils/isPieChartConfiguration';
|
||||
|
||||
describe('isPieChartConfiguration', () => {
|
||||
it('should return true for PieChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'PieChartConfiguration',
|
||||
} as PieChartConfiguration;
|
||||
|
||||
expect(isPieChartConfiguration(configuration)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false for BarChartConfiguration', () => {
|
||||
const configuration = {
|
||||
__typename: 'BarChartConfiguration',
|
||||
} as BarChartConfiguration;
|
||||
|
||||
expect(isPieChartConfiguration(configuration)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for null', () => {
|
||||
expect(isPieChartConfiguration(null)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false for undefined', () => {
|
||||
expect(isPieChartConfiguration(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import {
|
||||
ALL_CHART_CONFIGURATIONS,
|
||||
TEST_BAR_CHART_CONFIGURATION,
|
||||
TEST_IFRAME_CONFIGURATION,
|
||||
TEST_PIE_CHART_CONFIGURATION,
|
||||
TEST_STANDALONE_RICH_TEXT_CONFIGURATION,
|
||||
} from '~/testing/mock-data/widget-configurations';
|
||||
|
||||
describe('isWidgetConfigurationOfType', () => {
|
||||
it('returns true when __typename matches', () => {
|
||||
expect(
|
||||
isWidgetConfigurationOfType(
|
||||
TEST_BAR_CHART_CONFIGURATION,
|
||||
'BarChartConfiguration',
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('returns false when __typename does not match', () => {
|
||||
expect(
|
||||
isWidgetConfigurationOfType(
|
||||
TEST_BAR_CHART_CONFIGURATION,
|
||||
'PieChartConfiguration',
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false for null configuration', () => {
|
||||
expect(isWidgetConfigurationOfType(null, 'BarChartConfiguration')).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns false for undefined configuration', () => {
|
||||
expect(
|
||||
isWidgetConfigurationOfType(undefined, 'BarChartConfiguration'),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('correctly identifies PieChartConfiguration', () => {
|
||||
expect(
|
||||
isWidgetConfigurationOfType(
|
||||
TEST_PIE_CHART_CONFIGURATION,
|
||||
'PieChartConfiguration',
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('correctly identifies IframeConfiguration', () => {
|
||||
expect(
|
||||
isWidgetConfigurationOfType(
|
||||
TEST_IFRAME_CONFIGURATION,
|
||||
'IframeConfiguration',
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('correctly identifies StandaloneRichTextConfiguration', () => {
|
||||
expect(
|
||||
isWidgetConfigurationOfType(
|
||||
TEST_STANDALONE_RICH_TEXT_CONFIGURATION,
|
||||
'StandaloneRichTextConfiguration',
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('works with all chart configuration types', () => {
|
||||
ALL_CHART_CONFIGURATIONS.forEach((config) => {
|
||||
expect(isWidgetConfigurationOfType(config, config.__typename!)).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
import { isWidgetConfigurationOfTypeGraph } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfTypeGraph';
|
||||
import {
|
||||
ALL_CHART_CONFIGURATIONS,
|
||||
TEST_FIELDS_CONFIGURATION,
|
||||
TEST_IFRAME_CONFIGURATION,
|
||||
TEST_STANDALONE_RICH_TEXT_CONFIGURATION,
|
||||
} from '~/testing/mock-data/widget-configurations';
|
||||
|
||||
describe('isWidgetConfigurationOfTypeGraph', () => {
|
||||
it('returns true for all chart configurations', () => {
|
||||
ALL_CHART_CONFIGURATIONS.forEach((config) => {
|
||||
expect(isWidgetConfigurationOfTypeGraph(config)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('returns false for IframeConfiguration', () => {
|
||||
expect(isWidgetConfigurationOfTypeGraph(TEST_IFRAME_CONFIGURATION)).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns false for StandaloneRichTextConfiguration', () => {
|
||||
expect(
|
||||
isWidgetConfigurationOfTypeGraph(TEST_STANDALONE_RICH_TEXT_CONFIGURATION),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false for FieldsConfiguration', () => {
|
||||
expect(isWidgetConfigurationOfTypeGraph(TEST_FIELDS_CONFIGURATION)).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns false for null', () => {
|
||||
expect(isWidgetConfigurationOfTypeGraph(null)).toBe(false);
|
||||
});
|
||||
|
||||
it('returns false for undefined', () => {
|
||||
expect(isWidgetConfigurationOfTypeGraph(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
+13
-6
@@ -1,8 +1,6 @@
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { isBarChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarChartConfiguration';
|
||||
import { isFieldOrRelationNestedFieldDateKind } from '@/command-menu/pages/page-layout/utils/isFieldOrNestedFieldDateKind';
|
||||
import { isLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isLineChartConfiguration';
|
||||
import { isPieChartConfiguration } from '@/command-menu/pages/page-layout/utils/isPieChartConfiguration';
|
||||
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';
|
||||
@@ -40,9 +38,18 @@ export const buildChartGroupByFieldConfigUpdate = <
|
||||
[subFieldNameKey]: subFieldName,
|
||||
};
|
||||
|
||||
const isBarChart = isBarChartConfiguration(configuration);
|
||||
const isLineChart = isLineChartConfiguration(configuration);
|
||||
const isPieChart = isPieChartConfiguration(configuration);
|
||||
const isBarChart = isWidgetConfigurationOfType(
|
||||
configuration,
|
||||
'BarChartConfiguration',
|
||||
);
|
||||
const isLineChart = isWidgetConfigurationOfType(
|
||||
configuration,
|
||||
'LineChartConfiguration',
|
||||
);
|
||||
const isPieChart = isWidgetConfigurationOfType(
|
||||
configuration,
|
||||
'PieChartConfiguration',
|
||||
);
|
||||
|
||||
if (isPrimaryAxis) {
|
||||
const existingOrderBy =
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import { type BarLineChartConvertibleFields } from '@/command-menu/pages/page-layout/types/BarLineChartConvertibleFields';
|
||||
import { isPieChartConfiguration } from '@/command-menu/pages/page-layout/utils/isPieChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { type PieChartConfiguration } from '~/generated/graphql';
|
||||
|
||||
export const convertPieChartConfigToBarOrLineChart = (
|
||||
configuration: PieChartConfiguration,
|
||||
): BarLineChartConvertibleFields => {
|
||||
if (!isPieChartConfiguration(configuration)) {
|
||||
if (!isWidgetConfigurationOfType(configuration, 'PieChartConfiguration')) {
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -19,12 +19,12 @@ import { SORT_BY_GROUP_BY_FIELD_SETTING } from '@/command-menu/pages/page-layout
|
||||
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';
|
||||
import { GraphType } from '~/generated-metadata/graphql';
|
||||
import { BarChartLayout } from '~/generated/graphql';
|
||||
|
||||
export const getBarChartSettings = (
|
||||
graphType: GraphType.VERTICAL_BAR | GraphType.HORIZONTAL_BAR,
|
||||
layout: BarChartLayout,
|
||||
): ChartSettingsGroup[] => {
|
||||
const isHorizontal = graphType === GraphType.HORIZONTAL_BAR;
|
||||
const isHorizontal = layout === BarChartLayout.HORIZONTAL;
|
||||
|
||||
const dataDisplayXIcon = isHorizontal ? IconAxisY : IconAxisX;
|
||||
const dataDisplayYIcon = isHorizontal ? IconAxisX : IconAxisY;
|
||||
|
||||
+7
-12
@@ -5,11 +5,10 @@ import { PIE_CHART_MAXIMUM_NUMBER_OF_SLICES } from '@/page-layout/widgets/graph/
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { type ObjectRecordGroupByDateGranularity } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { GraphType } from '~/generated/graphql';
|
||||
import { WidgetConfigurationType } from '~/generated/graphql';
|
||||
|
||||
type GetChartLimitMessageParams = {
|
||||
graphType: GraphType;
|
||||
widgetConfigurationType: WidgetConfigurationType;
|
||||
isPrimaryAxisDate: boolean;
|
||||
primaryAxisDateGranularity:
|
||||
| ObjectRecordGroupByDateGranularity
|
||||
@@ -18,15 +17,14 @@ type GetChartLimitMessageParams = {
|
||||
};
|
||||
|
||||
export const getChartLimitMessage = ({
|
||||
graphType,
|
||||
widgetConfigurationType,
|
||||
isPrimaryAxisDate,
|
||||
primaryAxisDateGranularity,
|
||||
}: GetChartLimitMessageParams): string => {
|
||||
const maxItems =
|
||||
graphType === GraphType.LINE
|
||||
widgetConfigurationType === WidgetConfigurationType.LINE_CHART
|
||||
? LINE_CHART_CONSTANTS.MAXIMUM_NUMBER_OF_DATA_POINTS
|
||||
: graphType === GraphType.VERTICAL_BAR ||
|
||||
graphType === GraphType.HORIZONTAL_BAR
|
||||
: widgetConfigurationType === WidgetConfigurationType.BAR_CHART
|
||||
? BAR_CHART_CONSTANTS.MAXIMUM_NUMBER_OF_BARS
|
||||
: PIE_CHART_MAXIMUM_NUMBER_OF_SLICES;
|
||||
|
||||
@@ -37,14 +35,11 @@ export const getChartLimitMessage = ({
|
||||
return t`Undisplayed data: max ${maxItems} ${granularityLabel} per chart.`;
|
||||
}
|
||||
|
||||
if (graphType === GraphType.LINE) {
|
||||
if (widgetConfigurationType === WidgetConfigurationType.LINE_CHART) {
|
||||
return t`Undisplayed data: max ${maxItems} data points per chart.`;
|
||||
}
|
||||
|
||||
if (
|
||||
graphType === GraphType.VERTICAL_BAR ||
|
||||
graphType === GraphType.HORIZONTAL_BAR
|
||||
) {
|
||||
if (widgetConfigurationType === WidgetConfigurationType.BAR_CHART) {
|
||||
return t`Undisplayed data: max ${maxItems} bars per chart.`;
|
||||
}
|
||||
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { GraphType } from '@/command-menu/pages/page-layout/types/GraphType';
|
||||
import { assertUnreachable } from 'twenty-shared/utils';
|
||||
import { WidgetConfigurationType } from '~/generated/graphql';
|
||||
|
||||
export const getConfigurationTypeFromGraphType = (
|
||||
graphType: GraphType,
|
||||
): WidgetConfigurationType => {
|
||||
switch (graphType) {
|
||||
case GraphType.VERTICAL_BAR:
|
||||
case GraphType.HORIZONTAL_BAR:
|
||||
return WidgetConfigurationType.BAR_CHART;
|
||||
case GraphType.LINE:
|
||||
return WidgetConfigurationType.LINE_CHART;
|
||||
case GraphType.PIE:
|
||||
return WidgetConfigurationType.PIE_CHART;
|
||||
case GraphType.AGGREGATE:
|
||||
return WidgetConfigurationType.AGGREGATE_CHART;
|
||||
case GraphType.GAUGE:
|
||||
return WidgetConfigurationType.GAUGE_CHART;
|
||||
default:
|
||||
assertUnreachable(graphType);
|
||||
}
|
||||
};
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { GraphType } from '@/command-menu/pages/page-layout/types/GraphType';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { BarChartLayout } from '~/generated/graphql';
|
||||
|
||||
export const getCurrentGraphTypeFromConfig = (
|
||||
configuration: ChartConfiguration,
|
||||
): GraphType => {
|
||||
if (isWidgetConfigurationOfType(configuration, 'BarChartConfiguration')) {
|
||||
return configuration.layout === BarChartLayout.HORIZONTAL
|
||||
? GraphType.HORIZONTAL_BAR
|
||||
: GraphType.VERTICAL_BAR;
|
||||
}
|
||||
|
||||
if (isWidgetConfigurationOfType(configuration, 'LineChartConfiguration')) {
|
||||
return GraphType.LINE;
|
||||
}
|
||||
|
||||
if (isWidgetConfigurationOfType(configuration, 'PieChartConfiguration')) {
|
||||
return GraphType.PIE;
|
||||
}
|
||||
|
||||
if (
|
||||
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration')
|
||||
) {
|
||||
return GraphType.AGGREGATE;
|
||||
}
|
||||
|
||||
if (isWidgetConfigurationOfType(configuration, 'GaugeChartConfiguration')) {
|
||||
return GraphType.GAUGE;
|
||||
}
|
||||
|
||||
throw new Error(t`Unknown chart configuration type`);
|
||||
};
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import {
|
||||
type AggregateChartConfiguration,
|
||||
type WidgetConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
export const isAggregateChartConfiguration = (
|
||||
configuration:
|
||||
| WidgetConfiguration
|
||||
| FieldConfiguration
|
||||
| FieldsConfiguration
|
||||
| null
|
||||
| undefined,
|
||||
): configuration is AggregateChartConfiguration => {
|
||||
return configuration?.__typename === 'AggregateChartConfiguration';
|
||||
};
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import {
|
||||
type BarChartConfiguration,
|
||||
type WidgetConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
export const isBarChartConfiguration = (
|
||||
configuration:
|
||||
| WidgetConfiguration
|
||||
| FieldConfiguration
|
||||
| FieldsConfiguration
|
||||
| null
|
||||
| undefined,
|
||||
): configuration is BarChartConfiguration => {
|
||||
return configuration?.__typename === 'BarChartConfiguration';
|
||||
};
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
import {
|
||||
type BarChartConfiguration,
|
||||
type LineChartConfiguration,
|
||||
type WidgetConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import { isBarChartConfiguration } from './isBarChartConfiguration';
|
||||
import { isLineChartConfiguration } from './isLineChartConfiguration';
|
||||
|
||||
export const isBarOrLineChartConfiguration = (
|
||||
configuration:
|
||||
| WidgetConfiguration
|
||||
| FieldConfiguration
|
||||
| FieldsConfiguration
|
||||
| null
|
||||
| undefined,
|
||||
): configuration is BarChartConfiguration | LineChartConfiguration => {
|
||||
return (
|
||||
isBarChartConfiguration(configuration) ||
|
||||
isLineChartConfiguration(configuration)
|
||||
);
|
||||
};
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
import { type WidgetConfiguration } from '~/generated/graphql';
|
||||
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { isAggregateChartConfiguration } from '@/command-menu/pages/page-layout/utils/isAggregateChartConfiguration';
|
||||
import { isBarChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarChartConfiguration';
|
||||
import { isGaugeChartConfiguration } from '@/command-menu/pages/page-layout/utils/isGaugeChartConfiguration';
|
||||
import { isLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isLineChartConfiguration';
|
||||
import { isPieChartConfiguration } from '@/command-menu/pages/page-layout/utils/isPieChartConfiguration';
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
|
||||
export const isChartConfiguration = (
|
||||
configuration:
|
||||
| WidgetConfiguration
|
||||
| FieldConfiguration
|
||||
| FieldsConfiguration
|
||||
| null
|
||||
| undefined,
|
||||
): configuration is ChartConfiguration => {
|
||||
return (
|
||||
isBarChartConfiguration(configuration) ||
|
||||
isLineChartConfiguration(configuration) ||
|
||||
isPieChartConfiguration(configuration) ||
|
||||
isAggregateChartConfiguration(configuration) ||
|
||||
isGaugeChartConfiguration(configuration)
|
||||
);
|
||||
};
|
||||
+8
-3
@@ -1,8 +1,13 @@
|
||||
import { type ChartWidget } from '@/command-menu/pages/page-layout/types/ChartWidget';
|
||||
import { WidgetType } from '~/generated/graphql';
|
||||
import { isWidgetConfigurationOfTypeGraph } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfTypeGraph';
|
||||
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
|
||||
import { type WidgetConfiguration } from '~/generated/graphql';
|
||||
|
||||
export const isChartWidget = (
|
||||
pageLayoutWidget: any,
|
||||
pageLayoutWidget: PageLayoutWidget,
|
||||
): pageLayoutWidget is ChartWidget => {
|
||||
return pageLayoutWidget.type === WidgetType.GRAPH;
|
||||
return isWidgetConfigurationOfTypeGraph(
|
||||
// TODO: Remove this cast when we FieldsConfiguration and FieldConfiguration are in the backend
|
||||
pageLayoutWidget.configuration as WidgetConfiguration,
|
||||
);
|
||||
};
|
||||
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import {
|
||||
type GaugeChartConfiguration,
|
||||
type WidgetConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
export const isGaugeChartConfiguration = (
|
||||
configuration:
|
||||
| WidgetConfiguration
|
||||
| FieldConfiguration
|
||||
| FieldsConfiguration
|
||||
| null
|
||||
| undefined,
|
||||
): configuration is GaugeChartConfiguration => {
|
||||
return configuration?.__typename === 'GaugeChartConfiguration';
|
||||
};
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import {
|
||||
type IframeConfiguration,
|
||||
type WidgetConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
export const isIframeConfiguration = (
|
||||
configuration:
|
||||
| WidgetConfiguration
|
||||
| FieldConfiguration
|
||||
| FieldsConfiguration
|
||||
| null
|
||||
| undefined,
|
||||
): configuration is IframeConfiguration => {
|
||||
return configuration?.__typename === 'IframeConfiguration';
|
||||
};
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import {
|
||||
type LineChartConfiguration,
|
||||
type WidgetConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
export const isLineChartConfiguration = (
|
||||
configuration:
|
||||
| WidgetConfiguration
|
||||
| FieldConfiguration
|
||||
| FieldsConfiguration
|
||||
| null
|
||||
| undefined,
|
||||
): configuration is LineChartConfiguration => {
|
||||
return configuration?.__typename === 'LineChartConfiguration';
|
||||
};
|
||||
+6
-2
@@ -1,6 +1,6 @@
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||
import { isBarOrLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarOrLineChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const isMinMaxRangeValid = (
|
||||
@@ -10,7 +10,11 @@ export const isMinMaxRangeValid = (
|
||||
newValue: number,
|
||||
configuration: ChartConfiguration,
|
||||
): boolean => {
|
||||
if (!isBarOrLineChartConfiguration(configuration)) {
|
||||
const isBarOrLineChart =
|
||||
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration');
|
||||
|
||||
if (!isBarOrLineChart) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import {
|
||||
type PieChartConfiguration,
|
||||
type WidgetConfiguration,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
export const isPieChartConfiguration = (
|
||||
configuration:
|
||||
| WidgetConfiguration
|
||||
| FieldConfiguration
|
||||
| FieldsConfiguration
|
||||
| null
|
||||
| undefined,
|
||||
): configuration is PieChartConfiguration => {
|
||||
return configuration?.__typename === 'PieChartConfiguration';
|
||||
};
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import {
|
||||
type AggregateChartConfiguration,
|
||||
type BarChartConfiguration,
|
||||
type GaugeChartConfiguration,
|
||||
type IframeConfiguration,
|
||||
type LineChartConfiguration,
|
||||
type PieChartConfiguration,
|
||||
type StandaloneRichTextConfiguration,
|
||||
type WidgetConfiguration,
|
||||
type WidgetConfigurationType,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
type WidgetConfigurationTypenameMap = {
|
||||
AggregateChartConfiguration: Omit<
|
||||
AggregateChartConfiguration,
|
||||
'configurationType'
|
||||
> & {
|
||||
configurationType: WidgetConfigurationType.AGGREGATE_CHART;
|
||||
};
|
||||
BarChartConfiguration: Omit<BarChartConfiguration, 'configurationType'> & {
|
||||
configurationType: WidgetConfigurationType.BAR_CHART;
|
||||
};
|
||||
GaugeChartConfiguration: Omit<
|
||||
GaugeChartConfiguration,
|
||||
'configurationType'
|
||||
> & {
|
||||
configurationType: WidgetConfigurationType.GAUGE_CHART;
|
||||
};
|
||||
IframeConfiguration: Omit<IframeConfiguration, 'configurationType'> & {
|
||||
configurationType: WidgetConfigurationType.IFRAME;
|
||||
};
|
||||
LineChartConfiguration: Omit<LineChartConfiguration, 'configurationType'> & {
|
||||
configurationType: WidgetConfigurationType.LINE_CHART;
|
||||
};
|
||||
PieChartConfiguration: Omit<PieChartConfiguration, 'configurationType'> & {
|
||||
configurationType: WidgetConfigurationType.PIE_CHART;
|
||||
};
|
||||
StandaloneRichTextConfiguration: Omit<
|
||||
StandaloneRichTextConfiguration,
|
||||
'configurationType'
|
||||
> & {
|
||||
configurationType: WidgetConfigurationType.STANDALONE_RICH_TEXT;
|
||||
};
|
||||
};
|
||||
|
||||
type WidgetConfigurationTypename = keyof WidgetConfigurationTypenameMap;
|
||||
|
||||
export type WidgetConfigurationOfType<T extends WidgetConfigurationTypename> =
|
||||
WidgetConfigurationTypenameMap[T];
|
||||
|
||||
export const isWidgetConfigurationOfType = <
|
||||
T extends WidgetConfigurationTypename,
|
||||
>(
|
||||
configuration:
|
||||
| WidgetConfiguration
|
||||
| FieldsConfiguration
|
||||
| FieldConfiguration
|
||||
| null
|
||||
| undefined,
|
||||
typename: T,
|
||||
): configuration is WidgetConfigurationTypenameMap[T] => {
|
||||
return configuration?.__typename === typename;
|
||||
};
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { type FieldConfiguration } from '@/page-layout/types/FieldConfiguration';
|
||||
import { type FieldsConfiguration } from '@/page-layout/types/FieldsConfiguration';
|
||||
import { type WidgetConfiguration } from '~/generated/graphql';
|
||||
|
||||
export const isWidgetConfigurationOfTypeGraph = (
|
||||
configuration:
|
||||
| WidgetConfiguration
|
||||
| FieldsConfiguration
|
||||
| FieldConfiguration
|
||||
| null
|
||||
| undefined,
|
||||
): configuration is ChartConfiguration => {
|
||||
return (
|
||||
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'PieChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'AggregateChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'GaugeChartConfiguration')
|
||||
);
|
||||
};
|
||||
+10
-7
@@ -1,8 +1,7 @@
|
||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||
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 { isBarOrLineChartConfiguration } from '@/command-menu/pages/page-layout/utils/isBarOrLineChartConfiguration';
|
||||
import { isPieChartConfiguration } from '@/command-menu/pages/page-layout/utils/isPieChartConfiguration';
|
||||
import { isWidgetConfigurationOfType } from '@/command-menu/pages/page-layout/utils/isWidgetConfigurationOfType';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { isFieldRelation } from '@/object-record/record-field/ui/types/guards/isFieldRelation';
|
||||
import { isRelationNestedFieldDateKind } from '@/page-layout/widgets/graph/utils/isRelationNestedFieldDateKind';
|
||||
@@ -55,8 +54,12 @@ export const shouldHideChartSetting = (
|
||||
);
|
||||
|
||||
if (isDefined(configuration) && isDefined(objectMetadataItem)) {
|
||||
const isBarOrLineChart =
|
||||
isWidgetConfigurationOfType(configuration, 'BarChartConfiguration') ||
|
||||
isWidgetConfigurationOfType(configuration, 'LineChartConfiguration');
|
||||
|
||||
if (item.id === CHART_CONFIGURATION_SETTING_IDS.DATE_GRANULARITY_X) {
|
||||
if (isBarOrLineChartConfiguration(configuration)) {
|
||||
if (isBarOrLineChart) {
|
||||
return shouldHideDateGranularityBasedOnFieldType(
|
||||
configuration.primaryAxisGroupByFieldMetadataId,
|
||||
configuration.primaryAxisGroupBySubFieldName,
|
||||
@@ -67,7 +70,7 @@ export const shouldHideChartSetting = (
|
||||
}
|
||||
|
||||
if (item.id === CHART_CONFIGURATION_SETTING_IDS.DATE_GRANULARITY_Y) {
|
||||
if (isBarOrLineChartConfiguration(configuration)) {
|
||||
if (isBarOrLineChart) {
|
||||
return shouldHideDateGranularityBasedOnFieldType(
|
||||
configuration.secondaryAxisGroupByFieldMetadataId,
|
||||
configuration.secondaryAxisGroupBySubFieldName,
|
||||
@@ -78,7 +81,7 @@ export const shouldHideChartSetting = (
|
||||
}
|
||||
|
||||
if (item.id === CHART_CONFIGURATION_SETTING_IDS.DATE_GRANULARITY) {
|
||||
if (isPieChartConfiguration(configuration)) {
|
||||
if (isWidgetConfigurationOfType(configuration, 'PieChartConfiguration')) {
|
||||
return shouldHideDateGranularityBasedOnFieldType(
|
||||
configuration.groupByFieldMetadataId,
|
||||
configuration.groupBySubFieldName,
|
||||
@@ -89,7 +92,7 @@ export const shouldHideChartSetting = (
|
||||
}
|
||||
|
||||
if (item.id === CHART_CONFIGURATION_SETTING_IDS.CUMULATIVE) {
|
||||
if (isBarOrLineChartConfiguration(configuration)) {
|
||||
if (isBarOrLineChart) {
|
||||
return shouldHideDateGranularityBasedOnFieldType(
|
||||
configuration.primaryAxisGroupByFieldMetadataId,
|
||||
configuration.primaryAxisGroupBySubFieldName,
|
||||
@@ -100,7 +103,7 @@ export const shouldHideChartSetting = (
|
||||
}
|
||||
|
||||
if (item.id === CHART_CONFIGURATION_SETTING_IDS.SHOW_LEGEND) {
|
||||
if (isPieChartConfiguration(configuration)) {
|
||||
if (isWidgetConfigurationOfType(configuration, 'PieChartConfiguration')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user