fix: view group followup (#9162)
This PR fixes all followup that @Bonapara add on Discord. - [x] When no group by is set, clicking on group by should open the "field selection" menu - [x] When closed, chevron should be "chevron-right" instead of "chevron-up" - [x] Sort : Add ability to switch from alphabetical to manual when moving a option in sort alphabetical - [x] Add subtext for group by and sort - [x] Group by menu display bug - [x] Changing the sort should not close the menu - [x] Group by Activation -> shows empty state + is slow - [x] Switching from Kanban view Settings to Table Options menu displays an empty menu - [x] Unnecessary spacing under groups - [x] When no "select" are set on an object, redirect the user directly to the new Select field page - [x] Sort : Default should be manual - [x] Hidding "no value" displays all options and remove the "hide empty group" toggle - [x] Hide Empty group option disappeared - [x] Group by should not be persisted on "Locked/Main view" (**For now we just disable the group by on main view**) - [x] Hide Empty group should not be activated by default on Opportunities Kanban view - [ ] Animate the group opening/closing (**We'll be done later**) Performance improvement: https://github.com/user-attachments/assets/fd2acf66-0e56-45d0-8b2f-99c62e57d6f7 https://github.com/user-attachments/assets/80f1a2e1-9f77-4923-b85d-acb9cad96886 Also fix #9036 --------- Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
@ -34,6 +34,7 @@ export const ObjectOptionsDropdown = ({
|
||||
clickableComponent={
|
||||
<StyledHeaderDropdownButton>Options</StyledHeaderDropdownButton>
|
||||
}
|
||||
onClose={handleResetContent}
|
||||
dropdownComponents={
|
||||
<ObjectOptionsDropdownContext.Provider
|
||||
value={{
|
||||
|
||||
@ -25,6 +25,7 @@ import { useSetRecoilState } from 'recoil';
|
||||
|
||||
export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
|
||||
const {
|
||||
viewType,
|
||||
currentContentId,
|
||||
recordIndexId,
|
||||
objectMetadataItem,
|
||||
@ -47,6 +48,7 @@ export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
|
||||
const { handleVisibilityChange: handleRecordGroupVisibilityChange } =
|
||||
useRecordGroupVisibility({
|
||||
viewBarId: recordIndexId,
|
||||
viewType,
|
||||
});
|
||||
|
||||
const viewGroupSettingsUrl = getSettingsPagePath(
|
||||
|
||||
@ -30,8 +30,7 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { FeatureFlagKey } from '~/generated/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const ObjectOptionsDropdownMenuContent = () => {
|
||||
const {
|
||||
@ -42,10 +41,6 @@ export const ObjectOptionsDropdownMenuContent = () => {
|
||||
closeDropdown,
|
||||
} = useOptionsDropdown();
|
||||
|
||||
const isViewGroupEnabled = useIsFeatureEnabled(
|
||||
FeatureFlagKey.IsViewGroupsEnabled,
|
||||
);
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
const { currentViewWithCombinedFiltersAndSorts: currentView } =
|
||||
useGetCurrentView();
|
||||
@ -120,9 +115,13 @@ export const ObjectOptionsDropdownMenuContent = () => {
|
||||
contextualText={`${visibleBoardFields.length} shown`}
|
||||
hasSubMenu
|
||||
/>
|
||||
{(viewType === ViewType.Kanban || isViewGroupEnabled) && (
|
||||
{viewType === ViewType.Kanban && currentView?.key !== 'INDEX' && (
|
||||
<MenuItem
|
||||
onClick={() => onContentChange('recordGroups')}
|
||||
onClick={() =>
|
||||
isDefined(recordGroupFieldMetadata)
|
||||
? onContentChange('recordGroups')
|
||||
: onContentChange('recordGroupFields')
|
||||
}
|
||||
LeftIcon={IconLayoutList}
|
||||
text="Group by"
|
||||
contextualText={recordGroupFieldMetadata?.label}
|
||||
|
||||
@ -26,6 +26,7 @@ import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMe
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
@ -36,6 +37,7 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
recordIndexId,
|
||||
objectMetadataItem,
|
||||
onContentChange,
|
||||
resetContent,
|
||||
closeDropdown,
|
||||
} = useOptionsDropdown();
|
||||
|
||||
@ -47,7 +49,7 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
hiddenRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const recordGroupFieldMetadataItem = useRecoilComponentValueV2(
|
||||
const recordGroupFieldMetadata = useRecoilComponentValueV2(
|
||||
recordGroupFieldMetadataComponentState,
|
||||
);
|
||||
|
||||
@ -64,11 +66,14 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
viewBarComponentId: recordIndexId,
|
||||
});
|
||||
|
||||
const newFieldSettingsUrl = getSettingsPagePath(
|
||||
SettingsPath.ObjectNewFieldSelect,
|
||||
const newSelectFieldSettingsUrl = getSettingsPagePath(
|
||||
SettingsPath.ObjectNewFieldConfigure,
|
||||
{
|
||||
objectSlug: objectNamePlural,
|
||||
},
|
||||
{
|
||||
fieldType: FieldMetadataType.Select,
|
||||
},
|
||||
);
|
||||
|
||||
const location = useLocation();
|
||||
@ -101,7 +106,11 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
<>
|
||||
<DropdownMenuHeader
|
||||
StartIcon={IconChevronLeft}
|
||||
onClick={() => onContentChange('recordGroups')}
|
||||
onClick={() =>
|
||||
isDefined(recordGroupFieldMetadata)
|
||||
? onContentChange('recordGroups')
|
||||
: resetContent()
|
||||
}
|
||||
>
|
||||
Group by
|
||||
</DropdownMenuHeader>
|
||||
@ -114,13 +123,13 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
<DropdownMenuItemsContainer>
|
||||
<MenuItemSelect
|
||||
text="None"
|
||||
selected={!isDefined(recordGroupFieldMetadataItem)}
|
||||
selected={!isDefined(recordGroupFieldMetadata)}
|
||||
onClick={handleResetRecordGroupField}
|
||||
/>
|
||||
{filteredRecordGroupFieldMetadataItems.map((fieldMetadataItem) => (
|
||||
<MenuItemSelect
|
||||
key={fieldMetadataItem.id}
|
||||
selected={fieldMetadataItem.id === recordGroupFieldMetadataItem?.id}
|
||||
selected={fieldMetadataItem.id === recordGroupFieldMetadata?.id}
|
||||
onClick={() => handleRecordGroupFieldChange(fieldMetadataItem)}
|
||||
LeftIcon={getIcon(fieldMetadataItem.icon)}
|
||||
text={fieldMetadataItem.label}
|
||||
@ -130,7 +139,7 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItemsContainer>
|
||||
<UndecoratedLink
|
||||
to={newFieldSettingsUrl}
|
||||
to={newSelectFieldSettingsUrl}
|
||||
onClick={() => {
|
||||
setNavigationMemorizedUrl(location.pathname + location.search);
|
||||
closeDropdown();
|
||||
|
||||
@ -17,8 +17,7 @@ import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const ObjectOptionsDropdownRecordGroupSortContent = () => {
|
||||
const { currentContentId, onContentChange, closeDropdown } =
|
||||
useOptionsDropdown();
|
||||
const { currentContentId, onContentChange } = useOptionsDropdown();
|
||||
|
||||
const hiddenRecordGroupIds = useRecoilComponentValueV2(
|
||||
hiddenRecordGroupIdsComponentSelector,
|
||||
@ -30,7 +29,6 @@ export const ObjectOptionsDropdownRecordGroupSortContent = () => {
|
||||
|
||||
const handleRecordGroupSortChange = (sort: RecordGroupSort) => {
|
||||
setRecordGroupSort(sort);
|
||||
closeDropdown();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@ -11,47 +11,54 @@ import {
|
||||
} from 'twenty-ui';
|
||||
|
||||
import { useOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useOptionsDropdown';
|
||||
import { RecordGroupReorderConfirmationModal } from '@/object-record/record-group/components/RecordGroupReorderConfirmationModal';
|
||||
import { RecordGroupsVisibilityDropdownSection } from '@/object-record/record-group/components/RecordGroupsVisibilityDropdownSection';
|
||||
import { useRecordGroupReorder } from '@/object-record/record-group/hooks/useRecordGroupReorder';
|
||||
import { useRecordGroupReorderConfirmationModal } from '@/object-record/record-group/hooks/useRecordGroupReorderConfirmationModal';
|
||||
import { useRecordGroupVisibility } from '@/object-record/record-group/hooks/useRecordGroupVisibility';
|
||||
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
|
||||
import { hiddenRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/hiddenRecordGroupIdsComponentSelector';
|
||||
import { visibleRecordGroupIdsComponentSelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentSelector';
|
||||
import { recordIndexRecordGroupHideComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupHideComponentState';
|
||||
import { recordIndexRecordGroupIsDraggableSortComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexRecordGroupIsDraggableSortComponentSelector';
|
||||
import { visibleRecordGroupIdsComponentFamilySelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentFamilySelector';
|
||||
import { recordIndexRecordGroupHideComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordGroupHideComponentFamilyState';
|
||||
import { recordIndexRecordGroupSortComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupSortComponentState';
|
||||
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { FeatureFlagKey } from '~/generated/graphql';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
|
||||
export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
const isViewGroupEnabled = useIsFeatureEnabled(
|
||||
FeatureFlagKey.IsViewGroupsEnabled,
|
||||
);
|
||||
const {
|
||||
viewType,
|
||||
currentContentId,
|
||||
recordIndexId,
|
||||
onContentChange,
|
||||
resetContent,
|
||||
} = useOptionsDropdown();
|
||||
|
||||
const { currentContentId, recordIndexId, onContentChange, resetContent } =
|
||||
useOptionsDropdown();
|
||||
const { currentViewWithCombinedFiltersAndSorts: currentView } =
|
||||
useGetCurrentView();
|
||||
|
||||
const recordGroupFieldMetadata = useRecoilComponentValueV2(
|
||||
recordGroupFieldMetadataComponentState,
|
||||
);
|
||||
|
||||
const visibleRecordGroupIds = useRecoilComponentValueV2(
|
||||
visibleRecordGroupIdsComponentSelector,
|
||||
const visibleRecordGroupIds = useRecoilComponentFamilyValueV2(
|
||||
visibleRecordGroupIdsComponentFamilySelector,
|
||||
viewType,
|
||||
);
|
||||
|
||||
const hiddenRecordGroupIds = useRecoilComponentValueV2(
|
||||
hiddenRecordGroupIdsComponentSelector,
|
||||
);
|
||||
|
||||
const isDragableSortRecordGroup = useRecoilComponentValueV2(
|
||||
recordIndexRecordGroupIsDraggableSortComponentSelector,
|
||||
const hideEmptyRecordGroup = useRecoilComponentFamilyValueV2(
|
||||
recordIndexRecordGroupHideComponentFamilyState,
|
||||
viewType,
|
||||
);
|
||||
|
||||
const hideEmptyRecordGroup = useRecoilComponentValueV2(
|
||||
recordIndexRecordGroupHideComponentState,
|
||||
const recordGroupSort = useRecoilComponentValueV2(
|
||||
recordIndexRecordGroupSortComponentState,
|
||||
);
|
||||
|
||||
const {
|
||||
@ -59,12 +66,16 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
handleHideEmptyRecordGroupChange,
|
||||
} = useRecordGroupVisibility({
|
||||
viewBarId: recordIndexId,
|
||||
viewType,
|
||||
});
|
||||
|
||||
const { handleOrderChange: handleRecordGroupOrderChange } =
|
||||
useRecordGroupReorder({
|
||||
viewBarId: recordIndexId,
|
||||
});
|
||||
const {
|
||||
handleRecordGroupOrderChangeWithModal,
|
||||
handleRecordGroupReorderConfirmClick,
|
||||
} = useRecordGroupReorderConfirmationModal({
|
||||
recordIndexId,
|
||||
viewType,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
@ -81,22 +92,20 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
Group by
|
||||
</DropdownMenuHeader>
|
||||
<DropdownMenuItemsContainer>
|
||||
{isViewGroupEnabled && (
|
||||
{currentView?.key !== 'INDEX' && (
|
||||
<>
|
||||
<MenuItem
|
||||
onClick={() => onContentChange('recordGroupFields')}
|
||||
LeftIcon={IconLayoutList}
|
||||
text={
|
||||
!recordGroupFieldMetadata
|
||||
? 'Group by'
|
||||
: `Group by "${recordGroupFieldMetadata.label}"`
|
||||
}
|
||||
text="Group by"
|
||||
contextualText={recordGroupFieldMetadata?.label}
|
||||
hasSubMenu
|
||||
/>
|
||||
<MenuItem
|
||||
onClick={() => onContentChange('recordGroupSort')}
|
||||
LeftIcon={IconSortDescending}
|
||||
text="Sort"
|
||||
contextualText={recordGroupSort}
|
||||
hasSubMenu
|
||||
/>
|
||||
</>
|
||||
@ -115,9 +124,9 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
<RecordGroupsVisibilityDropdownSection
|
||||
title="Visible groups"
|
||||
recordGroupIds={visibleRecordGroupIds}
|
||||
onDragEnd={handleRecordGroupOrderChange}
|
||||
onDragEnd={handleRecordGroupOrderChangeWithModal}
|
||||
onVisibilityChange={handleRecordGroupVisibilityChange}
|
||||
isDraggable={isDragableSortRecordGroup}
|
||||
isDraggable={true}
|
||||
showDragGrip={true}
|
||||
/>
|
||||
</>
|
||||
@ -134,6 +143,9 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
|
||||
</DropdownMenuItemsContainer>
|
||||
</>
|
||||
)}
|
||||
<RecordGroupReorderConfirmationModal
|
||||
onConfirmClick={handleRecordGroupReorderConfirmClick}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user