Improve and fix source selection in charts (#15033)

- Improvements: Hide advanced objects in a subMenu and order objects
alphabetically

<img width="420" height="944" alt="CleanShot 2025-10-10 at 17 32 59@2x"
src="https://github.com/user-attachments/assets/52d70a97-b037-4ac1-9237-ef3262cac099"
/>

<img width="426" height="1140" alt="CleanShot 2025-10-10 at 17 33 24@2x"
src="https://github.com/user-attachments/assets/932501be-3c5a-45d9-b2fd-938c7f6b2ef9"
/>


- Fix: reset all fields when changing object
This commit is contained in:
Raphaël Bosi
2025-10-10 17:49:30 +02:00
committed by GitHub
parent d4b81dd20f
commit b567c6551a
@@ -3,6 +3,8 @@ import { useUpdateCurrentWidgetConfig } from '@/command-menu/pages/page-layout/h
import { useWidgetInEditMode } from '@/command-menu/pages/page-layout/hooks/useWidgetInEditMode';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
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 { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
@@ -14,14 +16,19 @@ import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states
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 { IconChevronLeft, IconSettings, useIcons } from 'twenty-ui/display';
import { MenuItem, MenuItemSelect } from 'twenty-ui/navigation';
import { filterBySearchQuery } from '~/utils/filterBySearchQuery';
const ADVANCED_OBJECTS_MENU_ITEM_ID = 'advanced-objects';
export const ChartDataSourceDropdownContent = () => {
const [searchQuery, setSearchQuery] = useState('');
const [isAdvancedObjectsMenuOpened, setIsAdvancedObjectsMenuOpened] =
useState(false);
const { objectMetadataItems } = useObjectMetadataItems();
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
const { pageLayoutId } = usePageLayoutIdFromContextStoreTargetedRecord();
@@ -45,13 +52,23 @@ export const ChartDataSourceDropdownContent = () => {
objectPermissionsByObjectMetadataId[objectMetadataItem.id];
return (
isDefined(objectPermissions) && objectPermissions.canReadObjectRecords
isDefined(objectPermissions) &&
objectPermissions.canReadObjectRecords &&
objectMetadataItem.isActive
);
},
);
const regularObjects = objectsWithReadAccess
.filter((item) => !item.isSystem)
.sort((a, b) => a.labelPlural.localeCompare(b.labelPlural));
const systemObjects = objectsWithReadAccess
.filter((item) => item.isSystem)
.sort((a, b) => a.labelPlural.localeCompare(b.labelPlural));
const availableObjectMetadataItems = filterBySearchQuery({
items: objectsWithReadAccess,
items: isAdvancedObjectsMenuOpened ? systemObjects : regularObjects,
searchQuery,
getSearchableValues: (item) => [item.labelPlural, item.namePlural],
});
@@ -64,14 +81,47 @@ export const ChartDataSourceDropdownContent = () => {
const { getIcon } = useIcons();
const handleSelectSource = (objectMetadataId: string) => {
updateCurrentWidgetConfig({
objectMetadataId,
});
if (currentSource !== objectMetadataId) {
updateCurrentWidgetConfig({
objectMetadataId,
configToUpdate: {
aggregateFieldMetadataId: null,
groupByFieldMetadataIdX: null,
groupByFieldMetadataIdY: null,
groupBySubFieldNameX: null,
groupBySubFieldNameY: null,
groupByFieldMetadataId: null,
groupBySubFieldName: null,
},
});
}
closeDropdown();
};
const handleAdvancedObjectsClick = () => {
setIsAdvancedObjectsMenuOpened(true);
setSearchQuery('');
};
const handleBack = () => {
setIsAdvancedObjectsMenuOpened(false);
setSearchQuery('');
};
return (
<>
{isAdvancedObjectsMenuOpened && (
<DropdownMenuHeader
StartComponent={
<DropdownMenuHeaderLeftComponent
onClick={handleBack}
Icon={IconChevronLeft}
/>
}
>
<Trans>Advanced objects</Trans>
</DropdownMenuHeader>
)}
<DropdownMenuSearchInput
autoFocus
type="text"
@@ -84,9 +134,14 @@ export const ChartDataSourceDropdownContent = () => {
<SelectableList
selectableListInstanceId={dropdownId}
focusId={dropdownId}
selectableItemIdArray={availableObjectMetadataItems.map(
(objectMetadataItem) => objectMetadataItem.id,
)}
selectableItemIdArray={[
...availableObjectMetadataItems.map(
(objectMetadataItem) => objectMetadataItem.id,
),
...(!isAdvancedObjectsMenuOpened
? [ADVANCED_OBJECTS_MENU_ITEM_ID]
: []),
]}
>
{availableObjectMetadataItems.map((objectMetadataItem) => (
<SelectableListItem
@@ -107,6 +162,19 @@ export const ChartDataSourceDropdownContent = () => {
/>
</SelectableListItem>
))}
{!isAdvancedObjectsMenuOpened && (
<SelectableListItem
itemId={ADVANCED_OBJECTS_MENU_ITEM_ID}
onEnter={handleAdvancedObjectsClick}
>
<MenuItem
text={t`Advanced objects`}
LeftIcon={IconSettings}
onClick={handleAdvancedObjectsClick}
hasSubMenu
/>
</SelectableListItem>
)}
</SelectableList>
</DropdownMenuItemsContainer>
</>