Baptiste Devessier
2025-12-10 10:31:36 +01:00
committed by GitHub
parent 7b98804ec1
commit fd54a2af5c
55 changed files with 774 additions and 110 deletions
@@ -2,6 +2,7 @@ import { GRAPH_TYPE_INFORMATION } from '@/command-menu/pages/page-layout/constan
import { isChartWidget } from '@/command-menu/pages/page-layout/utils/isChartWidget';
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
import { type PageLayoutTab } from '@/page-layout/types/PageLayoutTab';
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
import { useTheme } from '@emotion/react';
import { t } from '@lingui/core/macro';
import { isDefined } from 'twenty-shared/utils';
@@ -11,7 +12,6 @@ import {
IconPlus,
type IconComponent,
} from 'twenty-ui/display';
import { type PageLayoutWidget } from '~/generated/graphql';
type PageLayoutHeaderInfo = {
headerIcon: IconComponent | undefined;
@@ -10,7 +10,6 @@ import { useChartSettingsValues } from '@/command-menu/pages/page-layout/hooks/u
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
import { useGetConfigToUpdateAfterGraphTypeChange } from '@/command-menu/pages/page-layout/hooks/useUpdateGraphTypeConfig';
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 { shouldHideChartSetting } from '@/command-menu/pages/page-layout/utils/shouldHideChartSetting';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
@@ -20,7 +19,9 @@ import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';
import { isFieldMetadataDateKind } from 'twenty-shared/utils';
import { GraphType, type PageLayoutWidget } from '~/generated/graphql';
import { assertChartWidgetOrThrow } from '@/command-menu/pages/page-layout/utils/assertChartWidgetOrThrow';
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
import { GraphType } from '~/generated/graphql';
const StyledCommandMenuContainer = styled.div`
display: flex;
@@ -36,11 +37,9 @@ export const ChartSettings = ({ widget }: { widget: PageLayoutWidget }) => {
useUpdateCurrentWidgetConfig(pageLayoutId);
const { objectMetadataItems } = useObjectMetadataItems();
if (widget.configuration?.__typename === 'IframeConfiguration') {
throw new Error(t`IframeConfiguration is not supported`);
}
assertChartWidgetOrThrow(widget);
const configuration = widget.configuration as ChartConfiguration;
const configuration = widget.configuration;
const currentGraphType = configuration?.graphType;
const { getChartSettingsValues } = useChartSettingsValues({
@@ -26,9 +26,11 @@ export const CommandMenuPageLayoutIframeSettings = () => {
throw new Error('Widget ID must be present while editing the widget');
}
const widgetConfiguration = widgetInEditMode.configuration;
const configUrl =
widgetInEditMode.configuration && 'url' in widgetInEditMode.configuration
? widgetInEditMode.configuration.url
widgetConfiguration && 'url' in widgetConfiguration
? widgetConfiguration.url
: null;
const [url, setUrl] = useState<string | null>(
@@ -56,15 +58,18 @@ export const CommandMenuPageLayoutIframeSettings = () => {
const handleUrlChange = (value: string) => {
setUrl(value);
if (validateUrl(value)) {
const trimmedValue = value.trim();
updatePageLayoutWidget(widgetInEditMode.id, {
configuration: {
...widgetInEditMode.configuration,
url: trimmedValue || null,
},
});
if (!validateUrl(value)) {
return;
}
const trimmedValue = value.trim();
updatePageLayoutWidget(widgetInEditMode.id, {
configuration: {
__typename: 'IframeConfiguration',
url: isNonEmptyString(trimmedValue) ? trimmedValue : null,
},
});
};
return (
@@ -1,9 +1,9 @@
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
import type { PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilCallback } from 'recoil';
import type { PageLayoutWidget } from '~/generated/graphql';
export const useUpdateCurrentWidgetConfig = (pageLayoutIdFromProps: string) => {
const pageLayoutDraftCallbackState = useRecoilComponentCallbackState(
@@ -7,13 +7,14 @@ import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadat
import { pageLayoutCurrentLayoutsComponentState } from '@/page-layout/states/pageLayoutCurrentLayoutsComponentState';
import { pageLayoutDraftComponentState } from '@/page-layout/states/pageLayoutDraftComponentState';
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
import { getTabListInstanceIdFromPageLayoutId } from '@/page-layout/utils/getTabListInstanceIdFromPageLayoutId';
import { updateWidgetMinimumSizeForGraphType } from '@/page-layout/utils/updateWidgetMinimumSizeForGraphType';
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import { GraphType, type PageLayoutWidget } from '~/generated/graphql';
import { GraphType } from '~/generated/graphql';
export const useGetConfigToUpdateAfterGraphTypeChange = ({
pageLayoutId,
@@ -1,7 +1,8 @@
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';
import { type PageLayoutWidget, type WidgetType } from '~/generated/graphql';
import { type WidgetType } from '~/generated/graphql';
export type ChartWidget = ModifiedProperties<
PageLayoutWidget,
@@ -0,0 +1,44 @@
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
import { type PageLayoutWidget } from '@/page-layout/types/PageLayoutWidget';
import { isNonEmptyString } from '@sniptt/guards';
import { assertIsDefinedOrThrow } from 'twenty-shared/utils';
type AssertChartWidgetOrThrow = (
widget: PageLayoutWidget,
) => asserts widget is PageLayoutWidget & {
objectMetadataId: string;
configuration: ChartConfiguration;
};
const VALID_CHART_TYPES: ReadonlyArray<ChartConfiguration['__typename']> = [
'BarChartConfiguration',
'LineChartConfiguration',
'PieChartConfiguration',
'AggregateChartConfiguration',
'GaugeChartConfiguration',
] as const;
export const assertChartWidgetOrThrow: AssertChartWidgetOrThrow = (
widget: PageLayoutWidget,
) => {
assertIsDefinedOrThrow(
widget.objectMetadataId,
new Error('Widget objectMetadataId is required'),
);
assertIsDefinedOrThrow(
widget.configuration,
new Error('Widget configuration is required'),
);
if (
!isNonEmptyString(widget.configuration.__typename) ||
!VALID_CHART_TYPES.includes(
widget.configuration.__typename as ChartConfiguration['__typename'],
)
) {
throw new Error(
`Expected chart configuration but got ${widget.configuration.__typename}`,
);
}
};