Add composites subfield selection in the graph editor (#14931)
Closes https://github.com/twentyhq/core-team-issues/issues/1638 Closes https://github.com/twentyhq/core-team-issues/issues/1623 https://github.com/user-attachments/assets/2dddadaa-781b-497d-b454-0066d599bda3 --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
co-authored by
Lucas Bordeau
parent
e382730a39
commit
94546d7c09
@@ -289,6 +289,8 @@ export type BarChartConfiguration = {
|
|||||||
graphType: GraphType;
|
graphType: GraphType;
|
||||||
groupByFieldMetadataIdX: Scalars['UUID'];
|
groupByFieldMetadataIdX: Scalars['UUID'];
|
||||||
groupByFieldMetadataIdY?: Maybe<Scalars['UUID']>;
|
groupByFieldMetadataIdY?: Maybe<Scalars['UUID']>;
|
||||||
|
groupBySubFieldNameX?: Maybe<Scalars['String']>;
|
||||||
|
groupBySubFieldNameY?: Maybe<Scalars['String']>;
|
||||||
omitNullValues?: Maybe<Scalars['Boolean']>;
|
omitNullValues?: Maybe<Scalars['Boolean']>;
|
||||||
orderByX: GraphOrderBy;
|
orderByX: GraphOrderBy;
|
||||||
orderByY?: Maybe<GraphOrderBy>;
|
orderByY?: Maybe<GraphOrderBy>;
|
||||||
@@ -1598,6 +1600,8 @@ export type LineChartConfiguration = {
|
|||||||
graphType: GraphType;
|
graphType: GraphType;
|
||||||
groupByFieldMetadataIdX: Scalars['UUID'];
|
groupByFieldMetadataIdX: Scalars['UUID'];
|
||||||
groupByFieldMetadataIdY?: Maybe<Scalars['UUID']>;
|
groupByFieldMetadataIdY?: Maybe<Scalars['UUID']>;
|
||||||
|
groupBySubFieldNameX?: Maybe<Scalars['String']>;
|
||||||
|
groupBySubFieldNameY?: Maybe<Scalars['String']>;
|
||||||
omitNullValues?: Maybe<Scalars['Boolean']>;
|
omitNullValues?: Maybe<Scalars['Boolean']>;
|
||||||
orderByX: GraphOrderBy;
|
orderByX: GraphOrderBy;
|
||||||
orderByY?: Maybe<GraphOrderBy>;
|
orderByY?: Maybe<GraphOrderBy>;
|
||||||
@@ -2955,6 +2959,7 @@ export type PieChartConfiguration = {
|
|||||||
filter?: Maybe<Scalars['JSON']>;
|
filter?: Maybe<Scalars['JSON']>;
|
||||||
graphType: GraphType;
|
graphType: GraphType;
|
||||||
groupByFieldMetadataId: Scalars['UUID'];
|
groupByFieldMetadataId: Scalars['UUID'];
|
||||||
|
groupBySubFieldName?: Maybe<Scalars['String']>;
|
||||||
orderBy: GraphOrderBy;
|
orderBy: GraphOrderBy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -289,6 +289,8 @@ export type BarChartConfiguration = {
|
|||||||
graphType: GraphType;
|
graphType: GraphType;
|
||||||
groupByFieldMetadataIdX: Scalars['UUID'];
|
groupByFieldMetadataIdX: Scalars['UUID'];
|
||||||
groupByFieldMetadataIdY?: Maybe<Scalars['UUID']>;
|
groupByFieldMetadataIdY?: Maybe<Scalars['UUID']>;
|
||||||
|
groupBySubFieldNameX?: Maybe<Scalars['String']>;
|
||||||
|
groupBySubFieldNameY?: Maybe<Scalars['String']>;
|
||||||
omitNullValues?: Maybe<Scalars['Boolean']>;
|
omitNullValues?: Maybe<Scalars['Boolean']>;
|
||||||
orderByX: GraphOrderBy;
|
orderByX: GraphOrderBy;
|
||||||
orderByY?: Maybe<GraphOrderBy>;
|
orderByY?: Maybe<GraphOrderBy>;
|
||||||
@@ -1555,6 +1557,8 @@ export type LineChartConfiguration = {
|
|||||||
graphType: GraphType;
|
graphType: GraphType;
|
||||||
groupByFieldMetadataIdX: Scalars['UUID'];
|
groupByFieldMetadataIdX: Scalars['UUID'];
|
||||||
groupByFieldMetadataIdY?: Maybe<Scalars['UUID']>;
|
groupByFieldMetadataIdY?: Maybe<Scalars['UUID']>;
|
||||||
|
groupBySubFieldNameX?: Maybe<Scalars['String']>;
|
||||||
|
groupBySubFieldNameY?: Maybe<Scalars['String']>;
|
||||||
omitNullValues?: Maybe<Scalars['Boolean']>;
|
omitNullValues?: Maybe<Scalars['Boolean']>;
|
||||||
orderByX: GraphOrderBy;
|
orderByX: GraphOrderBy;
|
||||||
orderByY?: Maybe<GraphOrderBy>;
|
orderByY?: Maybe<GraphOrderBy>;
|
||||||
@@ -2866,6 +2870,7 @@ export type PieChartConfiguration = {
|
|||||||
filter?: Maybe<Scalars['JSON']>;
|
filter?: Maybe<Scalars['JSON']>;
|
||||||
graphType: GraphType;
|
graphType: GraphType;
|
||||||
groupByFieldMetadataId: Scalars['UUID'];
|
groupByFieldMetadataId: Scalars['UUID'];
|
||||||
|
groupBySubFieldName?: Maybe<Scalars['String']>;
|
||||||
orderBy: GraphOrderBy;
|
orderBy: GraphOrderBy;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -1,3 +1,4 @@
|
|||||||
|
import { COMMAND_MENU_LIST_SELECTABLE_LIST_ID } from '@/command-menu/constants/CommandMenuListSelectableListId';
|
||||||
import { hasUserSelectedCommandState } from '@/command-menu/states/hasUserSelectedCommandState';
|
import { hasUserSelectedCommandState } from '@/command-menu/states/hasUserSelectedCommandState';
|
||||||
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||||
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
||||||
@@ -11,11 +12,13 @@ export const CommandMenuDefaultSelectionEffect = ({
|
|||||||
}: {
|
}: {
|
||||||
selectableItemIds: string[];
|
selectableItemIds: string[];
|
||||||
}) => {
|
}) => {
|
||||||
const { setSelectedItemId } = useSelectableList('command-menu-list');
|
const { setSelectedItemId } = useSelectableList(
|
||||||
|
COMMAND_MENU_LIST_SELECTABLE_LIST_ID,
|
||||||
|
);
|
||||||
|
|
||||||
const selectedItemId = useRecoilComponentValue(
|
const selectedItemId = useRecoilComponentValue(
|
||||||
selectedItemIdComponentState,
|
selectedItemIdComponentState,
|
||||||
'command-menu-list',
|
COMMAND_MENU_LIST_SELECTABLE_LIST_ID,
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasUserSelectedCommand = useRecoilValue(hasUserSelectedCommandState);
|
const hasUserSelectedCommand = useRecoilValue(hasUserSelectedCommandState);
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ import {
|
|||||||
CommandMenuItem,
|
CommandMenuItem,
|
||||||
type CommandMenuItemProps,
|
type CommandMenuItemProps,
|
||||||
} from '@/command-menu/components/CommandMenuItem';
|
} from '@/command-menu/components/CommandMenuItem';
|
||||||
|
import { COMMAND_MENU_LIST_SELECTABLE_LIST_ID } from '@/command-menu/constants/CommandMenuListSelectableListId';
|
||||||
import {
|
import {
|
||||||
Dropdown,
|
Dropdown,
|
||||||
type DropdownProps,
|
type DropdownProps,
|
||||||
} from '@/ui/layout/dropdown/components/Dropdown';
|
} from '@/ui/layout/dropdown/components/Dropdown';
|
||||||
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
|
||||||
|
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||||
|
|
||||||
export type CommandMenuItemDropdownProps = CommandMenuItemProps &
|
export type CommandMenuItemDropdownProps = CommandMenuItemProps &
|
||||||
@@ -34,6 +36,10 @@ export const CommandMenuItemDropdown = ({
|
|||||||
dropdownId,
|
dropdownId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const { setSelectedItemId } = useSelectableList(
|
||||||
|
COMMAND_MENU_LIST_SELECTABLE_LIST_ID,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
clickableComponent={
|
clickableComponent={
|
||||||
@@ -55,6 +61,9 @@ export const CommandMenuItemDropdown = ({
|
|||||||
dropdownPlacement={dropdownPlacement}
|
dropdownPlacement={dropdownPlacement}
|
||||||
dropdownOffset={dropdownOffset}
|
dropdownOffset={dropdownOffset}
|
||||||
disableClickForClickableComponent={disabled}
|
disableClickForClickableComponent={disabled}
|
||||||
|
onOpen={() => {
|
||||||
|
setSelectedItemId(id);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { ActionComponent } from '@/action-menu/actions/display/components/Action
|
|||||||
import { CommandGroup } from '@/command-menu/components/CommandGroup';
|
import { CommandGroup } from '@/command-menu/components/CommandGroup';
|
||||||
import { type ActionGroupConfig } from '@/command-menu/components/CommandMenu';
|
import { type ActionGroupConfig } from '@/command-menu/components/CommandMenu';
|
||||||
import { CommandMenuDefaultSelectionEffect } from '@/command-menu/components/CommandMenuDefaultSelectionEffect';
|
import { CommandMenuDefaultSelectionEffect } from '@/command-menu/components/CommandMenuDefaultSelectionEffect';
|
||||||
|
import { COMMAND_MENU_LIST_SELECTABLE_LIST_ID } from '@/command-menu/constants/CommandMenuListSelectableListId';
|
||||||
import { COMMAND_MENU_SEARCH_BAR_HEIGHT } from '@/command-menu/constants/CommandMenuSearchBarHeight';
|
import { COMMAND_MENU_SEARCH_BAR_HEIGHT } from '@/command-menu/constants/CommandMenuSearchBarHeight';
|
||||||
import { COMMAND_MENU_SEARCH_BAR_PADDING } from '@/command-menu/constants/CommandMenuSearchBarPadding';
|
import { COMMAND_MENU_SEARCH_BAR_PADDING } from '@/command-menu/constants/CommandMenuSearchBarPadding';
|
||||||
import { SIDE_PANEL_FOCUS_ID } from '@/command-menu/constants/SidePanelFocusId';
|
import { SIDE_PANEL_FOCUS_ID } from '@/command-menu/constants/SidePanelFocusId';
|
||||||
@@ -74,7 +75,7 @@ export const CommandMenuList = ({
|
|||||||
<ScrollWrapper componentInstanceId={`scroll-wrapper-command-menu`}>
|
<ScrollWrapper componentInstanceId={`scroll-wrapper-command-menu`}>
|
||||||
<StyledInnerList>
|
<StyledInnerList>
|
||||||
<SelectableList
|
<SelectableList
|
||||||
selectableListInstanceId="command-menu-list"
|
selectableListInstanceId={COMMAND_MENU_LIST_SELECTABLE_LIST_ID}
|
||||||
focusId={SIDE_PANEL_FOCUS_ID}
|
focusId={SIDE_PANEL_FOCUS_ID}
|
||||||
selectableItemIdArray={selectableItemIds}
|
selectableItemIdArray={selectableItemIds}
|
||||||
onSelect={() => {
|
onSelect={() => {
|
||||||
|
|||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
export const COMMAND_MENU_LIST_SELECTABLE_LIST_ID = 'command-menu-list';
|
||||||
+4
-1
@@ -1,5 +1,6 @@
|
|||||||
import { COMMAND_MENU_COMPONENT_INSTANCE_ID } from '@/command-menu/constants/CommandMenuComponentInstanceId';
|
import { COMMAND_MENU_COMPONENT_INSTANCE_ID } from '@/command-menu/constants/CommandMenuComponentInstanceId';
|
||||||
import { COMMAND_MENU_CONTEXT_CHIP_GROUPS_DROPDOWN_ID } from '@/command-menu/constants/CommandMenuContextChipGroupsDropdownId';
|
import { COMMAND_MENU_CONTEXT_CHIP_GROUPS_DROPDOWN_ID } from '@/command-menu/constants/CommandMenuContextChipGroupsDropdownId';
|
||||||
|
import { COMMAND_MENU_LIST_SELECTABLE_LIST_ID } from '@/command-menu/constants/CommandMenuListSelectableListId';
|
||||||
import { COMMAND_MENU_PREVIOUS_COMPONENT_INSTANCE_ID } from '@/command-menu/constants/CommandMenuPreviousComponentInstanceId';
|
import { COMMAND_MENU_PREVIOUS_COMPONENT_INSTANCE_ID } from '@/command-menu/constants/CommandMenuPreviousComponentInstanceId';
|
||||||
import { useResetContextStoreStates } from '@/command-menu/hooks/useResetContextStoreStates';
|
import { useResetContextStoreStates } from '@/command-menu/hooks/useResetContextStoreStates';
|
||||||
import { commandMenuNavigationMorphItemByPageState } from '@/command-menu/states/commandMenuNavigationMorphItemsState';
|
import { commandMenuNavigationMorphItemByPageState } from '@/command-menu/states/commandMenuNavigationMorphItemsState';
|
||||||
@@ -27,7 +28,9 @@ import { useRecoilCallback } from 'recoil';
|
|||||||
import { isDefined } from 'twenty-shared/utils';
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
|
|
||||||
export const useCommandMenuCloseAnimationCompleteCleanup = () => {
|
export const useCommandMenuCloseAnimationCompleteCleanup = () => {
|
||||||
const { resetSelectedItem } = useSelectableList('command-menu-list');
|
const { resetSelectedItem } = useSelectableList(
|
||||||
|
COMMAND_MENU_LIST_SELECTABLE_LIST_ID,
|
||||||
|
);
|
||||||
|
|
||||||
const { resetContextStoreStates } = useResetContextStoreStates();
|
const { resetContextStoreStates } = useResetContextStoreStates();
|
||||||
|
|
||||||
|
|||||||
+9
-5
@@ -2,6 +2,7 @@ import { CommandGroup } from '@/command-menu/components/CommandGroup';
|
|||||||
import { CommandMenuItemDropdown } from '@/command-menu/components/CommandMenuItemDropdown';
|
import { CommandMenuItemDropdown } from '@/command-menu/components/CommandMenuItemDropdown';
|
||||||
import { CommandMenuItemToggle } from '@/command-menu/components/CommandMenuItemToggle';
|
import { CommandMenuItemToggle } from '@/command-menu/components/CommandMenuItemToggle';
|
||||||
import { CommandMenuList } from '@/command-menu/components/CommandMenuList';
|
import { CommandMenuList } from '@/command-menu/components/CommandMenuList';
|
||||||
|
import { COMMAND_MENU_LIST_SELECTABLE_LIST_ID } from '@/command-menu/constants/CommandMenuListSelectableListId';
|
||||||
import { useUpdateCommandMenuPageInfo } from '@/command-menu/hooks/useUpdateCommandMenuPageInfo';
|
import { useUpdateCommandMenuPageInfo } from '@/command-menu/hooks/useUpdateCommandMenuPageInfo';
|
||||||
import { ChartTypeSelectionSection } from '@/command-menu/pages/page-layout/components/ChartTypeSelectionSection';
|
import { ChartTypeSelectionSection } from '@/command-menu/pages/page-layout/components/ChartTypeSelectionSection';
|
||||||
import { GRAPH_TYPE_INFORMATION } from '@/command-menu/pages/page-layout/constants/GraphTypeInformation';
|
import { GRAPH_TYPE_INFORMATION } from '@/command-menu/pages/page-layout/constants/GraphTypeInformation';
|
||||||
@@ -14,11 +15,10 @@ import {
|
|||||||
CHART_CONFIGURATION_SETTING_IDS,
|
CHART_CONFIGURATION_SETTING_IDS,
|
||||||
CHART_CONFIGURATION_SETTING_TO_CONFIG_KEY_MAP,
|
CHART_CONFIGURATION_SETTING_TO_CONFIG_KEY_MAP,
|
||||||
} from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
} from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||||
import { getChartSettingsDropdownContent } from '@/command-menu/pages/page-layout/utils/getChartSettingsDropdownContent';
|
|
||||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
|
||||||
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
|
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
|
||||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||||
|
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
|
||||||
import { t } from '@lingui/core/macro';
|
import { t } from '@lingui/core/macro';
|
||||||
import { isNonEmptyString } from '@sniptt/guards';
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
|
|
||||||
@@ -62,6 +62,10 @@ export const ChartSettings = ({ widget }: { widget: PageLayoutWidget }) => {
|
|||||||
|
|
||||||
const chartSettings = GRAPH_TYPE_INFORMATION[currentGraphType].settings;
|
const chartSettings = GRAPH_TYPE_INFORMATION[currentGraphType].settings;
|
||||||
|
|
||||||
|
const { setSelectedItemId } = useSelectableList(
|
||||||
|
COMMAND_MENU_LIST_SELECTABLE_LIST_ID,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CommandMenuList
|
<CommandMenuList
|
||||||
commandGroups={[]}
|
commandGroups={[]}
|
||||||
@@ -91,6 +95,8 @@ export const ChartSettings = ({ widget }: { widget: PageLayoutWidget }) => {
|
|||||||
]
|
]
|
||||||
: item.id;
|
: item.id;
|
||||||
|
|
||||||
|
setSelectedItemId(item.id);
|
||||||
|
|
||||||
updateCurrentWidgetConfig({
|
updateCurrentWidgetConfig({
|
||||||
configToUpdate: {
|
configToUpdate: {
|
||||||
[configKey]: !getChartSettingsValues(item.id),
|
[configKey]: !getChartSettingsValues(item.id),
|
||||||
@@ -131,9 +137,7 @@ export const ChartSettings = ({ widget }: { widget: PageLayoutWidget }) => {
|
|||||||
dropdownId={item.id}
|
dropdownId={item.id}
|
||||||
dropdownComponents={
|
dropdownComponents={
|
||||||
<DropdownContent>
|
<DropdownContent>
|
||||||
<DropdownMenuItemsContainer>
|
{item.DropdownContent && <item.DropdownContent />}
|
||||||
{getChartSettingsDropdownContent(item.id)}
|
|
||||||
</DropdownMenuItemsContainer>
|
|
||||||
</DropdownContent>
|
</DropdownContent>
|
||||||
}
|
}
|
||||||
dropdownPlacement="bottom-end"
|
dropdownPlacement="bottom-end"
|
||||||
|
|||||||
+1
-2
@@ -19,7 +19,6 @@ import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states
|
|||||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||||
import { t } from '@lingui/core/macro';
|
import { t } from '@lingui/core/macro';
|
||||||
import { Trans } from '@lingui/react/macro';
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { isDefined } from 'twenty-shared/utils';
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
import { IconChevronLeft } from 'twenty-ui/display';
|
import { IconChevronLeft } from 'twenty-ui/display';
|
||||||
@@ -116,7 +115,7 @@ export const ChartAggregateOperationSelectionDropdownContent = ({
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Trans>Y-Axis Aggregate Operation</Trans>
|
{`${selectedField.label}`}
|
||||||
</DropdownMenuHeader>
|
</DropdownMenuHeader>
|
||||||
<DropdownMenuSearchInput
|
<DropdownMenuSearchInput
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|||||||
-5
@@ -2,7 +2,6 @@ import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pa
|
|||||||
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
||||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||||
import { getChartAxisNameDisplayOptions } from '@/command-menu/pages/page-layout/utils/getChartAxisNameDisplayOptions';
|
import { getChartAxisNameDisplayOptions } from '@/command-menu/pages/page-layout/utils/getChartAxisNameDisplayOptions';
|
||||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||||
@@ -11,7 +10,6 @@ import { SelectableListItem } from '@/ui/layout/selectable-list/components/Selec
|
|||||||
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
||||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||||
import { Trans } from '@lingui/react/macro';
|
|
||||||
import { MenuItemSelect } from 'twenty-ui/navigation';
|
import { MenuItemSelect } from 'twenty-ui/navigation';
|
||||||
import { AxisNameDisplay } from '~/generated/graphql';
|
import { AxisNameDisplay } from '~/generated/graphql';
|
||||||
|
|
||||||
@@ -60,9 +58,6 @@ export const ChartAxisNameSelectionDropdownContent = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DropdownMenuHeader>
|
|
||||||
<Trans>Axis Name</Trans>
|
|
||||||
</DropdownMenuHeader>
|
|
||||||
<DropdownMenuItemsContainer>
|
<DropdownMenuItemsContainer>
|
||||||
<SelectableList
|
<SelectableList
|
||||||
selectableListInstanceId={dropdownId}
|
selectableListInstanceId={dropdownId}
|
||||||
|
|||||||
-5
@@ -2,7 +2,6 @@ import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pa
|
|||||||
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
||||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||||
@@ -13,7 +12,6 @@ import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states
|
|||||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||||
import { t } from '@lingui/core/macro';
|
import { t } from '@lingui/core/macro';
|
||||||
import { Trans } from '@lingui/react/macro';
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||||
import { ColorSample } from 'twenty-ui/display';
|
import { ColorSample } from 'twenty-ui/display';
|
||||||
@@ -75,9 +73,6 @@ export const ChartColorSelectionDropdownContent = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DropdownMenuHeader>
|
|
||||||
<Trans>Color</Trans>
|
|
||||||
</DropdownMenuHeader>
|
|
||||||
<DropdownMenuSearchInput
|
<DropdownMenuSearchInput
|
||||||
autoFocus
|
autoFocus
|
||||||
type="text"
|
type="text"
|
||||||
|
|||||||
-5
@@ -3,7 +3,6 @@ import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/h
|
|||||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||||
@@ -15,7 +14,6 @@ import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states
|
|||||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||||
import { t } from '@lingui/core/macro';
|
import { t } from '@lingui/core/macro';
|
||||||
import { Trans } from '@lingui/react/macro';
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { isDefined } from 'twenty-shared/utils';
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
import { useIcons } from 'twenty-ui/display';
|
import { useIcons } from 'twenty-ui/display';
|
||||||
@@ -74,9 +72,6 @@ export const ChartDataSourceDropdownContent = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DropdownMenuHeader>
|
|
||||||
<Trans>Source</Trans>
|
|
||||||
</DropdownMenuHeader>
|
|
||||||
<DropdownMenuSearchInput
|
<DropdownMenuSearchInput
|
||||||
autoFocus
|
autoFocus
|
||||||
type="text"
|
type="text"
|
||||||
|
|||||||
-123
@@ -1,123 +0,0 @@
|
|||||||
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 { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
|
||||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
|
||||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
|
||||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
|
||||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
|
||||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
|
||||||
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
|
|
||||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
|
||||||
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
|
||||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
|
||||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
|
||||||
import { t } from '@lingui/core/macro';
|
|
||||||
import { Trans } from '@lingui/react/macro';
|
|
||||||
import { useState } from 'react';
|
|
||||||
import { isDefined } from 'twenty-shared/utils';
|
|
||||||
import { useIcons } from 'twenty-ui/display';
|
|
||||||
import { MenuItemSelect } from 'twenty-ui/navigation';
|
|
||||||
import { filterBySearchQuery } from '~/utils/filterBySearchQuery';
|
|
||||||
|
|
||||||
export const ChartFieldSelectionDropdownContent = () => {
|
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
|
||||||
const { objectMetadataItems } = useObjectMetadataItems();
|
|
||||||
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
|
|
||||||
const { widgetInEditMode } = useWidgetInEditMode(pageLayoutId);
|
|
||||||
|
|
||||||
if (
|
|
||||||
widgetInEditMode?.configuration?.__typename !== 'BarChartConfiguration' &&
|
|
||||||
widgetInEditMode?.configuration?.__typename !== 'LineChartConfiguration'
|
|
||||||
) {
|
|
||||||
throw new Error('Invalid configuration type');
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentXAxisFieldMetadataId =
|
|
||||||
widgetInEditMode.configuration.groupByFieldMetadataIdX;
|
|
||||||
|
|
||||||
const sourceObjectMetadataItem = objectMetadataItems.find(
|
|
||||||
(item) => item.id === widgetInEditMode.objectMetadataId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const dropdownId = useAvailableComponentInstanceIdOrThrow(
|
|
||||||
DropdownComponentInstanceContext,
|
|
||||||
);
|
|
||||||
|
|
||||||
const selectedItemId = useRecoilComponentValue(
|
|
||||||
selectedItemIdComponentState,
|
|
||||||
dropdownId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const availableFieldMetadataItems = filterBySearchQuery({
|
|
||||||
items: sourceObjectMetadataItem?.fields || [],
|
|
||||||
searchQuery,
|
|
||||||
getSearchableValues: (item) => [item.label, item.name],
|
|
||||||
});
|
|
||||||
|
|
||||||
const { updateCurrentWidgetConfig } =
|
|
||||||
useUpdateCurrentWidgetConfig(pageLayoutId);
|
|
||||||
|
|
||||||
const { closeDropdown } = useCloseDropdown();
|
|
||||||
|
|
||||||
const { getIcon } = useIcons();
|
|
||||||
|
|
||||||
if (!isDefined(sourceObjectMetadataItem)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSelectField = (fieldMetadataId: string) => {
|
|
||||||
updateCurrentWidgetConfig({
|
|
||||||
configToUpdate: {
|
|
||||||
groupByFieldMetadataIdX: fieldMetadataId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
closeDropdown();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<DropdownMenuHeader>
|
|
||||||
<Trans>X-Axis Field</Trans>
|
|
||||||
</DropdownMenuHeader>
|
|
||||||
<DropdownMenuSearchInput
|
|
||||||
autoFocus
|
|
||||||
type="text"
|
|
||||||
placeholder={t`Search fields`}
|
|
||||||
onChange={(event) => setSearchQuery(event.target.value)}
|
|
||||||
value={searchQuery}
|
|
||||||
/>
|
|
||||||
<DropdownMenuSeparator />
|
|
||||||
<DropdownMenuItemsContainer>
|
|
||||||
<SelectableList
|
|
||||||
selectableListInstanceId={dropdownId}
|
|
||||||
focusId={dropdownId}
|
|
||||||
selectableItemIdArray={availableFieldMetadataItems.map(
|
|
||||||
(item) => item.id,
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{availableFieldMetadataItems.map((fieldMetadataItem) => (
|
|
||||||
<SelectableListItem
|
|
||||||
key={fieldMetadataItem.id}
|
|
||||||
itemId={fieldMetadataItem.id}
|
|
||||||
onEnter={() => {
|
|
||||||
handleSelectField(fieldMetadataItem.id);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MenuItemSelect
|
|
||||||
text={fieldMetadataItem.label}
|
|
||||||
selected={currentXAxisFieldMetadataId === fieldMetadataItem.id}
|
|
||||||
focused={selectedItemId === fieldMetadataItem.id}
|
|
||||||
LeftIcon={getIcon(fieldMetadataItem.icon)}
|
|
||||||
onClick={() => {
|
|
||||||
handleSelectField(fieldMetadataItem.id);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</SelectableListItem>
|
|
||||||
))}
|
|
||||||
</SelectableList>
|
|
||||||
</DropdownMenuItemsContainer>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
+3
-6
@@ -2,7 +2,7 @@ import { ChartAggregateOperationSelectionDropdownContent } from '@/command-menu/
|
|||||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
import { isFieldRelation } from '@/object-record/record-field/ui/types/guards/isFieldRelation';
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||||
@@ -13,7 +13,6 @@ import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states
|
|||||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||||
import { t } from '@lingui/core/macro';
|
import { t } from '@lingui/core/macro';
|
||||||
import { Trans } from '@lingui/react/macro';
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { isDefined } from 'twenty-shared/utils';
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
import { useIcons } from 'twenty-ui/display';
|
import { useIcons } from 'twenty-ui/display';
|
||||||
@@ -59,7 +58,8 @@ export const ChartFieldSelectionForAggregateOperationDropdownContent = () => {
|
|||||||
items: sourceObjectMetadataItem?.fields || [],
|
items: sourceObjectMetadataItem?.fields || [],
|
||||||
searchQuery,
|
searchQuery,
|
||||||
getSearchableValues: (item) => [item.label, item.name],
|
getSearchableValues: (item) => [item.label, item.name],
|
||||||
});
|
// TODO: remove this once group by is supported for relation fields
|
||||||
|
}).filter((field) => !isFieldRelation(field));
|
||||||
|
|
||||||
const { getIcon } = useIcons();
|
const { getIcon } = useIcons();
|
||||||
|
|
||||||
@@ -78,9 +78,6 @@ export const ChartFieldSelectionForAggregateOperationDropdownContent = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DropdownMenuHeader>
|
|
||||||
<Trans>Y-Axis Field</Trans>
|
|
||||||
</DropdownMenuHeader>
|
|
||||||
<DropdownMenuSearchInput
|
<DropdownMenuSearchInput
|
||||||
autoFocus
|
autoFocus
|
||||||
type="text"
|
type="text"
|
||||||
|
|||||||
+94
@@ -0,0 +1,94 @@
|
|||||||
|
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||||
|
import { getCompositeSubFieldLabel } from '@/object-record/object-filter-dropdown/utils/getCompositeSubFieldLabel';
|
||||||
|
import { ICON_NAME_BY_SUB_FIELD } from '@/object-record/record-filter/constants/IconNameBySubField';
|
||||||
|
import { SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsCompositeFieldTypeConfigs';
|
||||||
|
import { type CompositeFieldType } from '@/settings/data-model/types/CompositeFieldType';
|
||||||
|
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
||||||
|
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
|
||||||
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
|
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||||
|
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
|
||||||
|
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||||
|
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
||||||
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
|
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||||
|
import { IconChevronLeft, useIcons } from 'twenty-ui/display';
|
||||||
|
import { MenuItemSelect } from 'twenty-ui/navigation';
|
||||||
|
|
||||||
|
type ChartGroupByFieldSelectionCompositeFieldViewProps = {
|
||||||
|
compositeField: FieldMetadataItem;
|
||||||
|
currentSubFieldName: string | undefined;
|
||||||
|
onBack: () => void;
|
||||||
|
onSelectSubField: (subFieldName: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ChartGroupByFieldSelectionCompositeFieldView = ({
|
||||||
|
compositeField,
|
||||||
|
currentSubFieldName,
|
||||||
|
onBack,
|
||||||
|
onSelectSubField,
|
||||||
|
}: ChartGroupByFieldSelectionCompositeFieldViewProps) => {
|
||||||
|
const { getIcon } = useIcons();
|
||||||
|
|
||||||
|
const dropdownId = useAvailableComponentInstanceIdOrThrow(
|
||||||
|
DropdownComponentInstanceContext,
|
||||||
|
);
|
||||||
|
|
||||||
|
const selectedItemId = useRecoilComponentValue(
|
||||||
|
selectedItemIdComponentState,
|
||||||
|
dropdownId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const compositeFieldType = compositeField.type as CompositeFieldType;
|
||||||
|
|
||||||
|
const subFieldNames = SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[
|
||||||
|
compositeFieldType
|
||||||
|
].subFields.map((subField) => subField.subFieldName);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<DropdownMenuHeader
|
||||||
|
StartComponent={
|
||||||
|
<DropdownMenuHeaderLeftComponent
|
||||||
|
onClick={onBack}
|
||||||
|
Icon={IconChevronLeft}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{compositeField.label}
|
||||||
|
</DropdownMenuHeader>
|
||||||
|
<DropdownMenuItemsContainer>
|
||||||
|
<SelectableList
|
||||||
|
selectableListInstanceId={dropdownId}
|
||||||
|
focusId={dropdownId}
|
||||||
|
selectableItemIdArray={subFieldNames}
|
||||||
|
>
|
||||||
|
{subFieldNames.map((subFieldName) => (
|
||||||
|
<SelectableListItem
|
||||||
|
key={subFieldName}
|
||||||
|
itemId={subFieldName}
|
||||||
|
onEnter={() => {
|
||||||
|
onSelectSubField(subFieldName);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MenuItemSelect
|
||||||
|
text={getCompositeSubFieldLabel(
|
||||||
|
compositeFieldType,
|
||||||
|
subFieldName,
|
||||||
|
)}
|
||||||
|
selected={currentSubFieldName === subFieldName}
|
||||||
|
focused={selectedItemId === subFieldName}
|
||||||
|
onClick={() => {
|
||||||
|
onSelectSubField(subFieldName);
|
||||||
|
}}
|
||||||
|
LeftIcon={getIcon(
|
||||||
|
ICON_NAME_BY_SUB_FIELD[subFieldName] ?? compositeField.icon,
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</SelectableListItem>
|
||||||
|
))}
|
||||||
|
</SelectableList>
|
||||||
|
</DropdownMenuItemsContainer>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
+11
-120
@@ -1,125 +1,16 @@
|
|||||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
import { ChartGroupByFieldSelectionDropdownContentBase } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartGroupByFieldSelectionDropdownContentBase';
|
||||||
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
import {
|
||||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
type BarChartConfiguration,
|
||||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
type LineChartConfiguration,
|
||||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
} from '~/generated/graphql';
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
|
||||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
|
||||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
|
||||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
|
||||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
|
||||||
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
|
|
||||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
|
||||||
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
|
||||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
|
||||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
|
||||||
import { t } from '@lingui/core/macro';
|
|
||||||
import { Trans } from '@lingui/react/macro';
|
|
||||||
import { useState } from 'react';
|
|
||||||
import { isDefined } from 'twenty-shared/utils';
|
|
||||||
import { useIcons } from 'twenty-ui/display';
|
|
||||||
import { MenuItemSelect } from 'twenty-ui/navigation';
|
|
||||||
import { filterBySearchQuery } from '~/utils/filterBySearchQuery';
|
|
||||||
|
|
||||||
export const ChartGroupByFieldSelectionDropdownContent = () => {
|
export const ChartGroupByFieldSelectionDropdownContent = () => {
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
|
||||||
const { objectMetadataItems } = useObjectMetadataItems();
|
|
||||||
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
|
|
||||||
const { widgetInEditMode } = useWidgetInEditMode(pageLayoutId);
|
|
||||||
|
|
||||||
if (
|
|
||||||
widgetInEditMode?.configuration?.__typename !== 'BarChartConfiguration' &&
|
|
||||||
widgetInEditMode?.configuration?.__typename !== 'LineChartConfiguration'
|
|
||||||
) {
|
|
||||||
throw new Error('Invalid configuration type');
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentGroupByFieldMetadataId =
|
|
||||||
widgetInEditMode.configuration.groupByFieldMetadataIdY;
|
|
||||||
|
|
||||||
const sourceObjectMetadataItem = objectMetadataItems.find(
|
|
||||||
(item) => item.id === widgetInEditMode.objectMetadataId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const dropdownId = useAvailableComponentInstanceIdOrThrow(
|
|
||||||
DropdownComponentInstanceContext,
|
|
||||||
);
|
|
||||||
|
|
||||||
const selectedItemId = useRecoilComponentValue(
|
|
||||||
selectedItemIdComponentState,
|
|
||||||
dropdownId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const availableFieldMetadataItems = filterBySearchQuery({
|
|
||||||
items: sourceObjectMetadataItem?.fields || [],
|
|
||||||
searchQuery,
|
|
||||||
getSearchableValues: (item) => [item.label, item.name],
|
|
||||||
});
|
|
||||||
|
|
||||||
const { updateCurrentWidgetConfig } =
|
|
||||||
useUpdateCurrentWidgetConfig(pageLayoutId);
|
|
||||||
|
|
||||||
const { closeDropdown } = useCloseDropdown();
|
|
||||||
|
|
||||||
const { getIcon } = useIcons();
|
|
||||||
|
|
||||||
if (!isDefined(sourceObjectMetadataItem)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSelectField = (fieldMetadataId: string) => {
|
|
||||||
updateCurrentWidgetConfig({
|
|
||||||
configToUpdate: {
|
|
||||||
groupByFieldMetadataIdY: fieldMetadataId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
closeDropdown();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<ChartGroupByFieldSelectionDropdownContentBase<
|
||||||
<DropdownMenuHeader>
|
BarChartConfiguration | LineChartConfiguration
|
||||||
<Trans>Y-Axis Group By Field</Trans>
|
>
|
||||||
</DropdownMenuHeader>
|
fieldMetadataIdKey="groupByFieldMetadataIdY"
|
||||||
<DropdownMenuSearchInput
|
subFieldNameKey="groupBySubFieldNameY"
|
||||||
autoFocus
|
/>
|
||||||
type="text"
|
|
||||||
placeholder={t`Search fields`}
|
|
||||||
onChange={(event) => setSearchQuery(event.target.value)}
|
|
||||||
value={searchQuery}
|
|
||||||
/>
|
|
||||||
<DropdownMenuSeparator />
|
|
||||||
<DropdownMenuItemsContainer>
|
|
||||||
<SelectableList
|
|
||||||
selectableListInstanceId={dropdownId}
|
|
||||||
focusId={dropdownId}
|
|
||||||
selectableItemIdArray={availableFieldMetadataItems.map(
|
|
||||||
(item) => item.id,
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{availableFieldMetadataItems.map((fieldMetadataItem) => (
|
|
||||||
<SelectableListItem
|
|
||||||
key={fieldMetadataItem.id}
|
|
||||||
itemId={fieldMetadataItem.id}
|
|
||||||
onEnter={() => {
|
|
||||||
handleSelectField(fieldMetadataItem.id);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MenuItemSelect
|
|
||||||
text={fieldMetadataItem.label}
|
|
||||||
selected={
|
|
||||||
currentGroupByFieldMetadataId === fieldMetadataItem.id
|
|
||||||
}
|
|
||||||
focused={selectedItemId === fieldMetadataItem.id}
|
|
||||||
LeftIcon={getIcon(fieldMetadataItem.icon)}
|
|
||||||
onClick={() => {
|
|
||||||
handleSelectField(fieldMetadataItem.id);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</SelectableListItem>
|
|
||||||
))}
|
|
||||||
</SelectableList>
|
|
||||||
</DropdownMenuItemsContainer>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
+187
@@ -0,0 +1,187 @@
|
|||||||
|
import { ChartGroupByFieldSelectionCompositeFieldView } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartGroupByFieldSelectionCompositeFieldView';
|
||||||
|
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 { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
||||||
|
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||||
|
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||||
|
import { isCompositeFieldType } from '@/object-record/object-filter-dropdown/utils/isCompositeFieldType';
|
||||||
|
import { isFieldRelation } from '@/object-record/record-field/ui/types/guards/isFieldRelation';
|
||||||
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
|
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||||
|
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||||
|
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||||
|
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||||
|
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
|
||||||
|
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||||
|
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
||||||
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
|
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||||
|
import { t } from '@lingui/core/macro';
|
||||||
|
import { useMemo, useState } from 'react';
|
||||||
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
|
import { useIcons } from 'twenty-ui/display';
|
||||||
|
import { MenuItemSelect } from 'twenty-ui/navigation';
|
||||||
|
import { filterBySearchQuery } from '~/utils/filterBySearchQuery';
|
||||||
|
|
||||||
|
type ChartGroupByFieldSelectionDropdownContentBaseProps<
|
||||||
|
T extends ChartConfiguration,
|
||||||
|
> = {
|
||||||
|
fieldMetadataIdKey: keyof T;
|
||||||
|
subFieldNameKey: keyof T;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ChartGroupByFieldSelectionDropdownContentBase = <
|
||||||
|
T extends ChartConfiguration,
|
||||||
|
>({
|
||||||
|
fieldMetadataIdKey,
|
||||||
|
subFieldNameKey,
|
||||||
|
}: ChartGroupByFieldSelectionDropdownContentBaseProps<T>) => {
|
||||||
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
|
|
||||||
|
const [selectedCompositeField, setSelectedCompositeField] =
|
||||||
|
useState<FieldMetadataItem | null>(null);
|
||||||
|
|
||||||
|
const { objectMetadataItems } = useObjectMetadataItems();
|
||||||
|
|
||||||
|
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
|
||||||
|
|
||||||
|
const { widgetInEditMode } = useWidgetInEditMode(pageLayoutId);
|
||||||
|
|
||||||
|
const configuration = widgetInEditMode?.configuration as T;
|
||||||
|
|
||||||
|
const currentGroupByFieldMetadataId = configuration?.[fieldMetadataIdKey] as
|
||||||
|
| string
|
||||||
|
| undefined;
|
||||||
|
const currentSubFieldName = configuration?.[subFieldNameKey] as
|
||||||
|
| string
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
const sourceObjectMetadataItem = objectMetadataItems.find(
|
||||||
|
(item) => item.id === widgetInEditMode?.objectMetadataId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const dropdownId = useAvailableComponentInstanceIdOrThrow(
|
||||||
|
DropdownComponentInstanceContext,
|
||||||
|
);
|
||||||
|
|
||||||
|
const selectedItemId = useRecoilComponentValue(
|
||||||
|
selectedItemIdComponentState,
|
||||||
|
dropdownId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const availableFieldMetadataItems = useMemo(
|
||||||
|
() =>
|
||||||
|
filterBySearchQuery({
|
||||||
|
items: sourceObjectMetadataItem?.fields || [],
|
||||||
|
searchQuery,
|
||||||
|
getSearchableValues: (item) => [item.label, item.name],
|
||||||
|
// TODO: remove this once group by is supported for relation fields
|
||||||
|
}).filter((field) => !isFieldRelation(field)),
|
||||||
|
[sourceObjectMetadataItem?.fields, searchQuery],
|
||||||
|
);
|
||||||
|
|
||||||
|
const { updateCurrentWidgetConfig } =
|
||||||
|
useUpdateCurrentWidgetConfig(pageLayoutId);
|
||||||
|
|
||||||
|
const { closeDropdown } = useCloseDropdown();
|
||||||
|
|
||||||
|
const { getIcon } = useIcons();
|
||||||
|
|
||||||
|
if (!isDefined(sourceObjectMetadataItem)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSelectField = (fieldMetadataItem: FieldMetadataItem) => {
|
||||||
|
if (isCompositeFieldType(fieldMetadataItem.type)) {
|
||||||
|
setSelectedCompositeField(fieldMetadataItem);
|
||||||
|
} else {
|
||||||
|
updateCurrentWidgetConfig({
|
||||||
|
configToUpdate: {
|
||||||
|
[fieldMetadataIdKey]: fieldMetadataItem.id,
|
||||||
|
[subFieldNameKey]: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
closeDropdown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBack = () => {
|
||||||
|
setSelectedCompositeField(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectSubField = (subFieldName: string) => {
|
||||||
|
if (!isDefined(selectedCompositeField)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCurrentWidgetConfig({
|
||||||
|
configToUpdate: {
|
||||||
|
[fieldMetadataIdKey]: selectedCompositeField.id,
|
||||||
|
[subFieldNameKey]: subFieldName,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
closeDropdown();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isDefined(selectedCompositeField)) {
|
||||||
|
return (
|
||||||
|
<ChartGroupByFieldSelectionCompositeFieldView
|
||||||
|
compositeField={selectedCompositeField}
|
||||||
|
currentSubFieldName={currentSubFieldName}
|
||||||
|
onBack={handleBack}
|
||||||
|
onSelectSubField={handleSelectSubField}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<DropdownMenuSearchInput
|
||||||
|
autoFocus
|
||||||
|
type="text"
|
||||||
|
placeholder={t`Search fields`}
|
||||||
|
onChange={(event) => setSearchQuery(event.target.value)}
|
||||||
|
value={searchQuery}
|
||||||
|
/>
|
||||||
|
<DropdownMenuSeparator />
|
||||||
|
<DropdownMenuItemsContainer>
|
||||||
|
{availableFieldMetadataItems.length === 0 ? (
|
||||||
|
<MenuItemSelect text={t`No fields found`} selected={false} disabled />
|
||||||
|
) : (
|
||||||
|
<SelectableList
|
||||||
|
selectableListInstanceId={dropdownId}
|
||||||
|
focusId={dropdownId}
|
||||||
|
selectableItemIdArray={availableFieldMetadataItems.map(
|
||||||
|
(item) => item.id,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{availableFieldMetadataItems.map((fieldMetadataItem) => (
|
||||||
|
<SelectableListItem
|
||||||
|
key={fieldMetadataItem.id}
|
||||||
|
itemId={fieldMetadataItem.id}
|
||||||
|
onEnter={() => {
|
||||||
|
handleSelectField(fieldMetadataItem);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MenuItemSelect
|
||||||
|
text={fieldMetadataItem.label}
|
||||||
|
selected={
|
||||||
|
!isCompositeFieldType(fieldMetadataItem.type) &&
|
||||||
|
currentGroupByFieldMetadataId === fieldMetadataItem.id
|
||||||
|
}
|
||||||
|
focused={selectedItemId === fieldMetadataItem.id}
|
||||||
|
LeftIcon={getIcon(fieldMetadataItem.icon)}
|
||||||
|
hasSubMenu={isCompositeFieldType(fieldMetadataItem.type)}
|
||||||
|
onClick={() => {
|
||||||
|
handleSelectField(fieldMetadataItem);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SelectableListItem>
|
||||||
|
))}
|
||||||
|
</SelectableList>
|
||||||
|
)}
|
||||||
|
</DropdownMenuItemsContainer>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
import { ChartGroupByFieldSelectionDropdownContentBase } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartGroupByFieldSelectionDropdownContentBase';
|
||||||
|
import { type PieChartConfiguration } from '~/generated/graphql';
|
||||||
|
|
||||||
|
export const ChartPieFieldSelectionDropdownContent = () => {
|
||||||
|
return (
|
||||||
|
<ChartGroupByFieldSelectionDropdownContentBase<PieChartConfiguration>
|
||||||
|
fieldMetadataIdKey="groupByFieldMetadataId"
|
||||||
|
subFieldNameKey="groupBySubFieldName"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
+1
-9
@@ -3,7 +3,6 @@ import { useGraphGroupBySortOptionLabels } from '@/command-menu/pages/page-layou
|
|||||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||||
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
||||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||||
@@ -21,13 +20,7 @@ import {
|
|||||||
type NumberChartConfiguration,
|
type NumberChartConfiguration,
|
||||||
} from '~/generated/graphql';
|
} from '~/generated/graphql';
|
||||||
|
|
||||||
type ChartSortByGroupByFieldDropdownContentProps = {
|
export const ChartSortByGroupByFieldDropdownContent = () => {
|
||||||
title: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ChartSortByGroupByFieldDropdownContent = ({
|
|
||||||
title,
|
|
||||||
}: ChartSortByGroupByFieldDropdownContentProps) => {
|
|
||||||
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
|
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
|
||||||
const { widgetInEditMode } = useWidgetInEditMode(pageLayoutId);
|
const { widgetInEditMode } = useWidgetInEditMode(pageLayoutId);
|
||||||
|
|
||||||
@@ -74,7 +67,6 @@ export const ChartSortByGroupByFieldDropdownContent = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DropdownMenuHeader>{title}</DropdownMenuHeader>
|
|
||||||
<DropdownMenuItemsContainer>
|
<DropdownMenuItemsContainer>
|
||||||
<SelectableList
|
<SelectableList
|
||||||
selectableListInstanceId={dropdownId}
|
selectableListInstanceId={dropdownId}
|
||||||
|
|||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
import { ChartGroupByFieldSelectionDropdownContentBase } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartGroupByFieldSelectionDropdownContentBase';
|
||||||
|
import {
|
||||||
|
type BarChartConfiguration,
|
||||||
|
type LineChartConfiguration,
|
||||||
|
} from '~/generated/graphql';
|
||||||
|
|
||||||
|
export const ChartXAxisFieldSelectionDropdownContent = () => {
|
||||||
|
return (
|
||||||
|
<ChartGroupByFieldSelectionDropdownContentBase<
|
||||||
|
BarChartConfiguration | LineChartConfiguration
|
||||||
|
>
|
||||||
|
fieldMetadataIdKey="groupByFieldMetadataIdX"
|
||||||
|
subFieldNameKey="groupBySubFieldNameX"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
+31
-41
@@ -3,7 +3,6 @@ import { useGraphXSortOptionLabels } from '@/command-menu/pages/page-layout/hook
|
|||||||
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
import { usePageLayoutIdFromContextStoreTargetedRecord } from '@/command-menu/pages/page-layout/hooks/usePageLayoutFromContextStoreTargetedRecord';
|
||||||
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/hooks/useUpdateCurrentWidgetConfig';
|
||||||
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
|
||||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader/DropdownMenuHeader';
|
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
|
||||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||||
@@ -12,7 +11,6 @@ import { SelectableListItem } from '@/ui/layout/selectable-list/components/Selec
|
|||||||
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
||||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||||
import { Trans } from '@lingui/react/macro';
|
|
||||||
|
|
||||||
import { MenuItemSelect } from 'twenty-ui/navigation';
|
import { MenuItemSelect } from 'twenty-ui/navigation';
|
||||||
import { type GraphOrderBy } from '~/generated/graphql';
|
import { type GraphOrderBy } from '~/generated/graphql';
|
||||||
@@ -59,46 +57,38 @@ export const ChartXAxisSortBySelectionDropdownContent = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<DropdownMenuItemsContainer>
|
||||||
<DropdownMenuHeader>
|
<SelectableList
|
||||||
<Trans>X-Axis Sort By</Trans>
|
selectableListInstanceId={dropdownId}
|
||||||
</DropdownMenuHeader>
|
focusId={dropdownId}
|
||||||
<DropdownMenuItemsContainer>
|
selectableItemIdArray={X_SORT_BY_OPTIONS.map((option) => option.value)}
|
||||||
<SelectableList
|
>
|
||||||
selectableListInstanceId={dropdownId}
|
{X_SORT_BY_OPTIONS.map((sortOption) => (
|
||||||
focusId={dropdownId}
|
<SelectableListItem
|
||||||
selectableItemIdArray={X_SORT_BY_OPTIONS.map(
|
key={sortOption.value}
|
||||||
(option) => option.value,
|
itemId={sortOption.value}
|
||||||
)}
|
onEnter={() => {
|
||||||
>
|
handleSelectSortOption(sortOption.value);
|
||||||
{X_SORT_BY_OPTIONS.map((sortOption) => (
|
}}
|
||||||
<SelectableListItem
|
>
|
||||||
key={sortOption.value}
|
<MenuItemSelect
|
||||||
itemId={sortOption.value}
|
text={getXSortOptionLabel({
|
||||||
onEnter={() => {
|
graphOrderBy: sortOption.value,
|
||||||
|
groupByFieldMetadataIdX: configuration.groupByFieldMetadataIdX,
|
||||||
|
aggregateFieldMetadataId:
|
||||||
|
configuration.aggregateFieldMetadataId,
|
||||||
|
aggregateOperation: configuration.aggregateOperation,
|
||||||
|
})}
|
||||||
|
selected={currentOrderByX === sortOption.value}
|
||||||
|
focused={selectedItemId === sortOption.value}
|
||||||
|
LeftIcon={sortOption.icon}
|
||||||
|
onClick={() => {
|
||||||
handleSelectSortOption(sortOption.value);
|
handleSelectSortOption(sortOption.value);
|
||||||
}}
|
}}
|
||||||
>
|
/>
|
||||||
<MenuItemSelect
|
</SelectableListItem>
|
||||||
text={getXSortOptionLabel({
|
))}
|
||||||
graphOrderBy: sortOption.value,
|
</SelectableList>
|
||||||
groupByFieldMetadataIdX:
|
</DropdownMenuItemsContainer>
|
||||||
configuration.groupByFieldMetadataIdX,
|
|
||||||
aggregateFieldMetadataId:
|
|
||||||
configuration.aggregateFieldMetadataId,
|
|
||||||
aggregateOperation: configuration.aggregateOperation,
|
|
||||||
})}
|
|
||||||
selected={currentOrderByX === sortOption.value}
|
|
||||||
focused={selectedItemId === sortOption.value}
|
|
||||||
LeftIcon={sortOption.icon}
|
|
||||||
onClick={() => {
|
|
||||||
handleSelectSortOption(sortOption.value);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</SelectableListItem>
|
|
||||||
))}
|
|
||||||
</SelectableList>
|
|
||||||
</DropdownMenuItemsContainer>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
+2
@@ -1,3 +1,4 @@
|
|||||||
|
import { ChartAxisNameSelectionDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartAxisNameSelectionDropdownContent';
|
||||||
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
||||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||||
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||||
@@ -8,4 +9,5 @@ export const AXIS_NAME_SETTING: ChartSettingsItem = {
|
|||||||
Icon: IconGizmo,
|
Icon: IconGizmo,
|
||||||
label: CHART_CONFIGURATION_SETTING_LABELS.AXIS_NAME,
|
label: CHART_CONFIGURATION_SETTING_LABELS.AXIS_NAME,
|
||||||
id: CHART_CONFIGURATION_SETTING_IDS.AXIS_NAME,
|
id: CHART_CONFIGURATION_SETTING_IDS.AXIS_NAME,
|
||||||
|
DropdownContent: ChartAxisNameSelectionDropdownContent,
|
||||||
};
|
};
|
||||||
|
|||||||
+2
@@ -1,3 +1,4 @@
|
|||||||
|
import { ChartDataSourceDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartDataSourceDropdownContent';
|
||||||
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
||||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||||
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||||
@@ -8,4 +9,5 @@ export const CHART_DATA_SOURCE_SETTING: ChartSettingsItem = {
|
|||||||
Icon: IconDatabase,
|
Icon: IconDatabase,
|
||||||
label: CHART_CONFIGURATION_SETTING_LABELS.SOURCE,
|
label: CHART_CONFIGURATION_SETTING_LABELS.SOURCE,
|
||||||
id: CHART_CONFIGURATION_SETTING_IDS.SOURCE,
|
id: CHART_CONFIGURATION_SETTING_IDS.SOURCE,
|
||||||
|
DropdownContent: ChartDataSourceDropdownContent,
|
||||||
};
|
};
|
||||||
|
|||||||
+2
@@ -1,3 +1,4 @@
|
|||||||
|
import { ChartColorSelectionDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartColorSelectionDropdownContent';
|
||||||
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
||||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||||
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||||
@@ -8,4 +9,5 @@ export const COLORS_SETTING: ChartSettingsItem = {
|
|||||||
Icon: IconColorSwatch,
|
Icon: IconColorSwatch,
|
||||||
label: CHART_CONFIGURATION_SETTING_LABELS.COLORS,
|
label: CHART_CONFIGURATION_SETTING_LABELS.COLORS,
|
||||||
id: CHART_CONFIGURATION_SETTING_IDS.COLORS,
|
id: CHART_CONFIGURATION_SETTING_IDS.COLORS,
|
||||||
|
DropdownContent: ChartColorSelectionDropdownContent,
|
||||||
};
|
};
|
||||||
|
|||||||
+2
@@ -1,3 +1,4 @@
|
|||||||
|
import { ChartXAxisFieldSelectionDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartXAxisFieldSelectionDropdownContent';
|
||||||
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
||||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||||
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||||
@@ -9,4 +10,5 @@ export const DATA_DISPLAY_X_SETTING: ChartSettingsItem = {
|
|||||||
label: CHART_CONFIGURATION_SETTING_LABELS.DATA_ON_DISPLAY_X,
|
label: CHART_CONFIGURATION_SETTING_LABELS.DATA_ON_DISPLAY_X,
|
||||||
id: CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X,
|
id: CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X,
|
||||||
dependsOn: [CHART_CONFIGURATION_SETTING_IDS.SOURCE],
|
dependsOn: [CHART_CONFIGURATION_SETTING_IDS.SOURCE],
|
||||||
|
DropdownContent: ChartXAxisFieldSelectionDropdownContent,
|
||||||
};
|
};
|
||||||
|
|||||||
+2
@@ -1,3 +1,4 @@
|
|||||||
|
import { ChartFieldSelectionForAggregateOperationDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartFieldSelectionForAggregateOperationDropdownContent';
|
||||||
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
||||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||||
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||||
@@ -9,4 +10,5 @@ export const DATA_DISPLAY_Y_SETTING: ChartSettingsItem = {
|
|||||||
label: CHART_CONFIGURATION_SETTING_LABELS.DATA_ON_DISPLAY_Y,
|
label: CHART_CONFIGURATION_SETTING_LABELS.DATA_ON_DISPLAY_Y,
|
||||||
id: CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_Y,
|
id: CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_Y,
|
||||||
dependsOn: [CHART_CONFIGURATION_SETTING_IDS.SOURCE],
|
dependsOn: [CHART_CONFIGURATION_SETTING_IDS.SOURCE],
|
||||||
|
DropdownContent: ChartFieldSelectionForAggregateOperationDropdownContent,
|
||||||
};
|
};
|
||||||
|
|||||||
+2
@@ -1,3 +1,4 @@
|
|||||||
|
import { ChartPieFieldSelectionDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartPieFieldSelectionDropdownContent';
|
||||||
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
||||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||||
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||||
@@ -8,4 +9,5 @@ export const EACH_SLICE_REPRESENTS_SETTING: ChartSettingsItem = {
|
|||||||
Icon: IconChartPie,
|
Icon: IconChartPie,
|
||||||
label: CHART_CONFIGURATION_SETTING_LABELS.EACH_SLICE_REPRESENTS,
|
label: CHART_CONFIGURATION_SETTING_LABELS.EACH_SLICE_REPRESENTS,
|
||||||
id: CHART_CONFIGURATION_SETTING_IDS.EACH_SLICE_REPRESENTS,
|
id: CHART_CONFIGURATION_SETTING_IDS.EACH_SLICE_REPRESENTS,
|
||||||
|
DropdownContent: ChartPieFieldSelectionDropdownContent,
|
||||||
};
|
};
|
||||||
|
|||||||
+2
@@ -1,3 +1,4 @@
|
|||||||
|
import { ChartGroupByFieldSelectionDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartGroupByFieldSelectionDropdownContent';
|
||||||
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
||||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||||
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||||
@@ -9,4 +10,5 @@ export const GROUP_BY_SETTING: ChartSettingsItem = {
|
|||||||
label: CHART_CONFIGURATION_SETTING_LABELS.GROUP_BY,
|
label: CHART_CONFIGURATION_SETTING_LABELS.GROUP_BY,
|
||||||
id: CHART_CONFIGURATION_SETTING_IDS.GROUP_BY,
|
id: CHART_CONFIGURATION_SETTING_IDS.GROUP_BY,
|
||||||
dependsOn: [CHART_CONFIGURATION_SETTING_IDS.SOURCE],
|
dependsOn: [CHART_CONFIGURATION_SETTING_IDS.SOURCE],
|
||||||
|
DropdownContent: ChartGroupByFieldSelectionDropdownContent,
|
||||||
};
|
};
|
||||||
|
|||||||
+2
@@ -1,3 +1,4 @@
|
|||||||
|
import { ChartSortByGroupByFieldDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartSortByGroupByFieldDropdownContent';
|
||||||
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
||||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||||
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||||
@@ -8,4 +9,5 @@ export const SORT_BY_GROUP_BY_FIELD_SETTING: ChartSettingsItem = {
|
|||||||
Icon: IconArrowsSort,
|
Icon: IconArrowsSort,
|
||||||
label: CHART_CONFIGURATION_SETTING_LABELS.SORT_BY_GROUP_BY_FIELD,
|
label: CHART_CONFIGURATION_SETTING_LABELS.SORT_BY_GROUP_BY_FIELD,
|
||||||
id: CHART_CONFIGURATION_SETTING_IDS.SORT_BY_GROUP_BY_FIELD,
|
id: CHART_CONFIGURATION_SETTING_IDS.SORT_BY_GROUP_BY_FIELD,
|
||||||
|
DropdownContent: ChartSortByGroupByFieldDropdownContent,
|
||||||
};
|
};
|
||||||
|
|||||||
+2
@@ -1,3 +1,4 @@
|
|||||||
|
import { ChartXAxisSortBySelectionDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartXAxisSortBySelectionDropdownContent';
|
||||||
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
import { CHART_CONFIGURATION_SETTING_LABELS } from '@/command-menu/pages/page-layout/constants/settings/ChartConfigurationSettingLabels';
|
||||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||||
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
import { type ChartSettingsItem } from '@/command-menu/pages/page-layout/types/ChartSettingsGroup';
|
||||||
@@ -8,4 +9,5 @@ export const SORT_BY_X_SETTING: ChartSettingsItem = {
|
|||||||
Icon: IconArrowsSort,
|
Icon: IconArrowsSort,
|
||||||
label: CHART_CONFIGURATION_SETTING_LABELS.SORT_BY_X,
|
label: CHART_CONFIGURATION_SETTING_LABELS.SORT_BY_X,
|
||||||
id: CHART_CONFIGURATION_SETTING_IDS.SORT_BY_X,
|
id: CHART_CONFIGURATION_SETTING_IDS.SORT_BY_X,
|
||||||
|
DropdownContent: ChartXAxisSortBySelectionDropdownContent,
|
||||||
};
|
};
|
||||||
|
|||||||
+20
-1
@@ -3,9 +3,11 @@ import { useGraphXSortOptionLabels } from '@/command-menu/pages/page-layout/hook
|
|||||||
import { type ChartConfiguration } from '@/command-menu/pages/page-layout/types/ChartConfiguration';
|
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 { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||||
import { getChartAxisNameDisplayOptions } from '@/command-menu/pages/page-layout/utils/getChartAxisNameDisplayOptions';
|
import { getChartAxisNameDisplayOptions } from '@/command-menu/pages/page-layout/utils/getChartAxisNameDisplayOptions';
|
||||||
|
import { getFieldLabelWithSubField } from '@/command-menu/pages/page-layout/utils/getFieldLabelWithSubField';
|
||||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||||
import { getAggregateOperationLabel } from '@/object-record/record-board/record-board-column/utils/getAggregateOperationLabel';
|
import { getAggregateOperationLabel } from '@/object-record/record-board/record-board-column/utils/getAggregateOperationLabel';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import { type CompositeFieldSubFieldName } from 'twenty-shared/types';
|
||||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||||
|
|
||||||
export const useChartSettingsValues = ({
|
export const useChartSettingsValues = ({
|
||||||
@@ -43,6 +45,15 @@ export const useChartSettingsValues = ({
|
|||||||
)
|
)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
const groupBySubFieldNameXLabel =
|
||||||
|
'groupBySubFieldNameX' in configuration && isDefined(groupByFieldX)
|
||||||
|
? getFieldLabelWithSubField({
|
||||||
|
field: groupByFieldX,
|
||||||
|
subFieldName:
|
||||||
|
configuration.groupBySubFieldNameX as CompositeFieldSubFieldName,
|
||||||
|
})
|
||||||
|
: undefined;
|
||||||
|
|
||||||
const aggregateField = objectMetadataItem?.fields.find(
|
const aggregateField = objectMetadataItem?.fields.find(
|
||||||
(fieldMetadataItem) =>
|
(fieldMetadataItem) =>
|
||||||
fieldMetadataItem.id === configuration.aggregateFieldMetadataId,
|
fieldMetadataItem.id === configuration.aggregateFieldMetadataId,
|
||||||
@@ -66,6 +77,8 @@ export const useChartSettingsValues = ({
|
|||||||
? getXSortOptionLabel({
|
? getXSortOptionLabel({
|
||||||
graphOrderBy: xAxisOrderBy,
|
graphOrderBy: xAxisOrderBy,
|
||||||
groupByFieldMetadataIdX: configuration.groupByFieldMetadataIdX,
|
groupByFieldMetadataIdX: configuration.groupByFieldMetadataIdX,
|
||||||
|
groupBySubFieldNameX:
|
||||||
|
configuration.groupBySubFieldNameX as CompositeFieldSubFieldName,
|
||||||
aggregateFieldMetadataId: configuration.aggregateFieldMetadataId,
|
aggregateFieldMetadataId: configuration.aggregateFieldMetadataId,
|
||||||
aggregateOperation: configuration.aggregateOperation,
|
aggregateOperation: configuration.aggregateOperation,
|
||||||
})
|
})
|
||||||
@@ -88,6 +101,12 @@ export const useChartSettingsValues = ({
|
|||||||
: 'groupByFieldMetadataId' in configuration
|
: 'groupByFieldMetadataId' in configuration
|
||||||
? configuration.groupByFieldMetadataId
|
? configuration.groupByFieldMetadataId
|
||||||
: undefined,
|
: undefined,
|
||||||
|
groupBySubFieldName:
|
||||||
|
'groupBySubFieldNameY' in configuration
|
||||||
|
? (configuration.groupBySubFieldNameY as CompositeFieldSubFieldName)
|
||||||
|
: 'groupBySubFieldName' in configuration
|
||||||
|
? (configuration.groupBySubFieldName as CompositeFieldSubFieldName)
|
||||||
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const getChartSettingsValues = (
|
const getChartSettingsValues = (
|
||||||
@@ -97,7 +116,7 @@ export const useChartSettingsValues = ({
|
|||||||
case CHART_CONFIGURATION_SETTING_IDS.SOURCE:
|
case CHART_CONFIGURATION_SETTING_IDS.SOURCE:
|
||||||
return objectMetadataItem?.labelPlural;
|
return objectMetadataItem?.labelPlural;
|
||||||
case CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X:
|
case CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X:
|
||||||
return groupByFieldX?.label;
|
return groupBySubFieldNameXLabel;
|
||||||
case CHART_CONFIGURATION_SETTING_IDS.COLORS:
|
case CHART_CONFIGURATION_SETTING_IDS.COLORS:
|
||||||
return isDefined(configuration.color) && 'color' in configuration
|
return isDefined(configuration.color) && 'color' in configuration
|
||||||
? capitalize(configuration.color)
|
? capitalize(configuration.color)
|
||||||
|
|||||||
+8
-1
@@ -1,6 +1,8 @@
|
|||||||
|
import { getFieldLabelWithSubField } from '@/command-menu/pages/page-layout/utils/getFieldLabelWithSubField';
|
||||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||||
import { t } from '@lingui/core/macro';
|
import { t } from '@lingui/core/macro';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import { type CompositeFieldSubFieldName } from 'twenty-shared/types';
|
||||||
import { GraphOrderBy } from '~/generated/graphql';
|
import { GraphOrderBy } from '~/generated/graphql';
|
||||||
|
|
||||||
export const useGraphGroupBySortOptionLabels = ({
|
export const useGraphGroupBySortOptionLabels = ({
|
||||||
@@ -17,15 +19,20 @@ export const useGraphGroupBySortOptionLabels = ({
|
|||||||
const getGroupBySortOptionLabel = ({
|
const getGroupBySortOptionLabel = ({
|
||||||
graphOrderBy,
|
graphOrderBy,
|
||||||
groupByFieldMetadataId,
|
groupByFieldMetadataId,
|
||||||
|
groupBySubFieldName,
|
||||||
}: {
|
}: {
|
||||||
graphOrderBy: GraphOrderBy;
|
graphOrderBy: GraphOrderBy;
|
||||||
groupByFieldMetadataId: string;
|
groupByFieldMetadataId: string;
|
||||||
|
groupBySubFieldName?: CompositeFieldSubFieldName;
|
||||||
}): string => {
|
}): string => {
|
||||||
const field = objectMetadataItem?.fields.find(
|
const field = objectMetadataItem?.fields.find(
|
||||||
(fieldMetadataItem) => fieldMetadataItem.id === groupByFieldMetadataId,
|
(fieldMetadataItem) => fieldMetadataItem.id === groupByFieldMetadataId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const fieldLabel = field?.label || t`Field`;
|
const fieldLabel = getFieldLabelWithSubField({
|
||||||
|
field,
|
||||||
|
subFieldName: groupBySubFieldName,
|
||||||
|
});
|
||||||
|
|
||||||
switch (graphOrderBy) {
|
switch (graphOrderBy) {
|
||||||
case GraphOrderBy.FIELD_ASC:
|
case GraphOrderBy.FIELD_ASC:
|
||||||
|
|||||||
+8
-1
@@ -1,7 +1,9 @@
|
|||||||
|
import { getFieldLabelWithSubField } from '@/command-menu/pages/page-layout/utils/getFieldLabelWithSubField';
|
||||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||||
import { getAggregateOperationLabel } from '@/object-record/record-board/record-board-column/utils/getAggregateOperationLabel';
|
import { getAggregateOperationLabel } from '@/object-record/record-board/record-board-column/utils/getAggregateOperationLabel';
|
||||||
import { t } from '@lingui/core/macro';
|
import { t } from '@lingui/core/macro';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
|
import { type CompositeFieldSubFieldName } from 'twenty-shared/types';
|
||||||
import { assertUnreachable, isDefined } from 'twenty-shared/utils';
|
import { assertUnreachable, isDefined } from 'twenty-shared/utils';
|
||||||
import {
|
import {
|
||||||
type ExtendedAggregateOperations,
|
type ExtendedAggregateOperations,
|
||||||
@@ -22,11 +24,13 @@ export const useGraphXSortOptionLabels = ({
|
|||||||
const getXSortOptionLabel = ({
|
const getXSortOptionLabel = ({
|
||||||
graphOrderBy,
|
graphOrderBy,
|
||||||
groupByFieldMetadataIdX,
|
groupByFieldMetadataIdX,
|
||||||
|
groupBySubFieldNameX,
|
||||||
aggregateFieldMetadataId,
|
aggregateFieldMetadataId,
|
||||||
aggregateOperation,
|
aggregateOperation,
|
||||||
}: {
|
}: {
|
||||||
graphOrderBy: GraphOrderBy;
|
graphOrderBy: GraphOrderBy;
|
||||||
groupByFieldMetadataIdX: string;
|
groupByFieldMetadataIdX: string;
|
||||||
|
groupBySubFieldNameX?: CompositeFieldSubFieldName;
|
||||||
aggregateFieldMetadataId?: string;
|
aggregateFieldMetadataId?: string;
|
||||||
aggregateOperation?: ExtendedAggregateOperations;
|
aggregateOperation?: ExtendedAggregateOperations;
|
||||||
}): string => {
|
}): string => {
|
||||||
@@ -34,7 +38,10 @@ export const useGraphXSortOptionLabels = ({
|
|||||||
(fieldMetadataItem) => fieldMetadataItem.id === groupByFieldMetadataIdX,
|
(fieldMetadataItem) => fieldMetadataItem.id === groupByFieldMetadataIdX,
|
||||||
);
|
);
|
||||||
|
|
||||||
const fieldLabel = groupByField?.label || t`Field`;
|
const fieldLabel = getFieldLabelWithSubField({
|
||||||
|
field: groupByField,
|
||||||
|
subFieldName: groupBySubFieldNameX,
|
||||||
|
});
|
||||||
|
|
||||||
const aggregateField = objectMetadataItem?.fields.find(
|
const aggregateField = objectMetadataItem?.fields.find(
|
||||||
(fieldMetadataItem) =>
|
(fieldMetadataItem) =>
|
||||||
|
|||||||
+2
@@ -1,5 +1,6 @@
|
|||||||
import { type CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
import { type CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
||||||
import { type MessageDescriptor } from '@lingui/core';
|
import { type MessageDescriptor } from '@lingui/core';
|
||||||
|
import { type ComponentType } from 'react';
|
||||||
import { type IconComponent } from 'twenty-ui/display';
|
import { type IconComponent } from 'twenty-ui/display';
|
||||||
|
|
||||||
export type ChartSettingsGroup = {
|
export type ChartSettingsGroup = {
|
||||||
@@ -14,4 +15,5 @@ export type ChartSettingsItem = {
|
|||||||
description?: string;
|
description?: string;
|
||||||
isBoolean: boolean;
|
isBoolean: boolean;
|
||||||
dependsOn?: CHART_CONFIGURATION_SETTING_IDS[];
|
dependsOn?: CHART_CONFIGURATION_SETTING_IDS[];
|
||||||
|
DropdownContent?: ComponentType;
|
||||||
};
|
};
|
||||||
|
|||||||
-35
@@ -1,35 +0,0 @@
|
|||||||
import { ChartAxisNameSelectionDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartAxisNameSelectionDropdownContent';
|
|
||||||
import { ChartColorSelectionDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartColorSelectionDropdownContent';
|
|
||||||
import { ChartDataSourceDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartDataSourceDropdownContent';
|
|
||||||
import { ChartFieldSelectionDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartFieldSelectionDropdownContent';
|
|
||||||
import { ChartFieldSelectionForAggregateOperationDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartFieldSelectionForAggregateOperationDropdownContent';
|
|
||||||
import { ChartGroupByFieldSelectionDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartGroupByFieldSelectionDropdownContent';
|
|
||||||
import { ChartSortByGroupByFieldDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartSortByGroupByFieldDropdownContent';
|
|
||||||
import { ChartXAxisSortBySelectionDropdownContent } from '@/command-menu/pages/page-layout/components/dropdown-content/ChartXAxisSortBySelectionDropdownContent';
|
|
||||||
import { CHART_CONFIGURATION_SETTING_IDS } from '@/command-menu/pages/page-layout/types/ChartConfigurationSettingIds';
|
|
||||||
import { t } from '@lingui/core/macro';
|
|
||||||
|
|
||||||
export const getChartSettingsDropdownContent = (itemId: string) => {
|
|
||||||
switch (itemId) {
|
|
||||||
case CHART_CONFIGURATION_SETTING_IDS.SOURCE:
|
|
||||||
return <ChartDataSourceDropdownContent />;
|
|
||||||
case CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_X:
|
|
||||||
return <ChartFieldSelectionDropdownContent />;
|
|
||||||
case CHART_CONFIGURATION_SETTING_IDS.SORT_BY_X:
|
|
||||||
return <ChartXAxisSortBySelectionDropdownContent />;
|
|
||||||
case CHART_CONFIGURATION_SETTING_IDS.DATA_ON_DISPLAY_Y:
|
|
||||||
return <ChartFieldSelectionForAggregateOperationDropdownContent />;
|
|
||||||
case CHART_CONFIGURATION_SETTING_IDS.SORT_BY_GROUP_BY_FIELD:
|
|
||||||
return (
|
|
||||||
<ChartSortByGroupByFieldDropdownContent title={t`Y-Axis Sort By`} />
|
|
||||||
);
|
|
||||||
case CHART_CONFIGURATION_SETTING_IDS.GROUP_BY:
|
|
||||||
return <ChartGroupByFieldSelectionDropdownContent />;
|
|
||||||
case CHART_CONFIGURATION_SETTING_IDS.COLORS:
|
|
||||||
return <ChartColorSelectionDropdownContent />;
|
|
||||||
case CHART_CONFIGURATION_SETTING_IDS.AXIS_NAME:
|
|
||||||
return <ChartAxisNameSelectionDropdownContent />;
|
|
||||||
default:
|
|
||||||
return <div>Configuration options will be implemented here</div>;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||||
|
import { getCompositeSubFieldLabel } from '@/object-record/object-filter-dropdown/utils/getCompositeSubFieldLabel';
|
||||||
|
import { type CompositeFieldType } from '@/settings/data-model/types/CompositeFieldType';
|
||||||
|
import { t } from '@lingui/core/macro';
|
||||||
|
import { type CompositeFieldSubFieldName } from 'twenty-shared/types';
|
||||||
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
|
|
||||||
|
export const getFieldLabelWithSubField = ({
|
||||||
|
field,
|
||||||
|
subFieldName,
|
||||||
|
}: {
|
||||||
|
field: FieldMetadataItem | undefined;
|
||||||
|
subFieldName?: CompositeFieldSubFieldName;
|
||||||
|
}): string => {
|
||||||
|
const subFieldNameLabel = isDefined(subFieldName)
|
||||||
|
? getCompositeSubFieldLabel(field?.type as CompositeFieldType, subFieldName)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const fieldLabel =
|
||||||
|
isDefined(subFieldNameLabel) && isDefined(field?.label)
|
||||||
|
? `${field.label} ${subFieldNameLabel}`
|
||||||
|
: isDefined(field?.label)
|
||||||
|
? field.label
|
||||||
|
: t`Field`;
|
||||||
|
|
||||||
|
return fieldLabel;
|
||||||
|
};
|
||||||
+10
@@ -42,6 +42,11 @@ export class BarChartConfigurationDTO {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
groupByFieldMetadataIdX: string;
|
groupByFieldMetadataIdX: string;
|
||||||
|
|
||||||
|
@Field(() => String, { nullable: true })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
groupBySubFieldNameX?: string;
|
||||||
|
|
||||||
@Field(() => GraphOrderBy)
|
@Field(() => GraphOrderBy)
|
||||||
@IsEnum(GraphOrderBy)
|
@IsEnum(GraphOrderBy)
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@@ -52,6 +57,11 @@ export class BarChartConfigurationDTO {
|
|||||||
@IsOptional()
|
@IsOptional()
|
||||||
groupByFieldMetadataIdY?: string;
|
groupByFieldMetadataIdY?: string;
|
||||||
|
|
||||||
|
@Field(() => String, { nullable: true })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
groupBySubFieldNameY?: string;
|
||||||
|
|
||||||
@Field(() => GraphOrderBy, { nullable: true })
|
@Field(() => GraphOrderBy, { nullable: true })
|
||||||
@IsEnum(GraphOrderBy)
|
@IsEnum(GraphOrderBy)
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
|
|||||||
+10
@@ -42,6 +42,11 @@ export class LineChartConfigurationDTO {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
groupByFieldMetadataIdX: string;
|
groupByFieldMetadataIdX: string;
|
||||||
|
|
||||||
|
@Field(() => String, { nullable: true })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
groupBySubFieldNameX?: string;
|
||||||
|
|
||||||
@Field(() => GraphOrderBy)
|
@Field(() => GraphOrderBy)
|
||||||
@IsEnum(GraphOrderBy)
|
@IsEnum(GraphOrderBy)
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
@@ -52,6 +57,11 @@ export class LineChartConfigurationDTO {
|
|||||||
@IsOptional()
|
@IsOptional()
|
||||||
groupByFieldMetadataIdY?: string;
|
groupByFieldMetadataIdY?: string;
|
||||||
|
|
||||||
|
@Field(() => String, { nullable: true })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
groupBySubFieldNameY?: string;
|
||||||
|
|
||||||
@Field(() => GraphOrderBy, { nullable: true })
|
@Field(() => GraphOrderBy, { nullable: true })
|
||||||
@IsEnum(GraphOrderBy)
|
@IsEnum(GraphOrderBy)
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
|
|||||||
+5
@@ -40,6 +40,11 @@ export class PieChartConfigurationDTO {
|
|||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
groupByFieldMetadataId: string;
|
groupByFieldMetadataId: string;
|
||||||
|
|
||||||
|
@Field(() => String, { nullable: true })
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
groupBySubFieldName?: string;
|
||||||
|
|
||||||
@Field(() => GraphOrderBy)
|
@Field(() => GraphOrderBy)
|
||||||
@IsEnum(GraphOrderBy)
|
@IsEnum(GraphOrderBy)
|
||||||
@IsNotEmpty()
|
@IsNotEmpty()
|
||||||
|
|||||||
Reference in New Issue
Block a user