Add compact view to calendar (#14527)

<img width="1263" height="785" alt="Screenshot 2025-09-16 at 11 44 44"
src="https://github.com/user-attachments/assets/dc61e69f-b887-4a4d-9f9c-e50ffa076082"
/>
<img width="1263" height="785" alt="Screenshot 2025-09-16 at 11 43 45"
src="https://github.com/user-attachments/assets/2dd917b3-6e6d-40f2-bb10-6c82de83c15d"
/>
This commit is contained in:
Weiko
2025-09-16 12:47:55 +02:00
committed by GitHub
parent b8ae7ddad9
commit e505e9cf9f
13 changed files with 94 additions and 137 deletions
@@ -1,6 +1,5 @@
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
import { useObjectOptionsDropdown } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsDropdown';
import { useObjectOptionsForBoard } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard';
import { useSetViewTypeFromLayoutOptionsMenu } from '@/object-record/object-options-dropdown/hooks/useSetViewTypeFromLayoutOptionsMenu';
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
import { recordIndexCalendarLayoutState } from '@/object-record/record-index/states/recordIndexCalendarLayoutState';
@@ -16,12 +15,15 @@ import { SelectableListItem } from '@/ui/layout/selectable-list/components/Selec
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { useUpdateCurrentView } from '@/views/hooks/useUpdateCurrentView';
import { type GraphQLView } from '@/views/types/GraphQLView';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { ViewType, viewTypeIconMapping } from '@/views/types/ViewType';
import { useGetAvailableFieldsForCalendar } from '@/views/view-picker/hooks/useGetAvailableFieldsForCalendar';
import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban';
import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap';
import { useLingui } from '@lingui/react/macro';
import { useCallback } from 'react';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import {
@@ -40,22 +42,24 @@ import { FeatureFlagKey, ViewCalendarLayout } from '~/generated/graphql';
export const ObjectOptionsDropdownLayoutContent = () => {
const { t } = useLingui();
const { objectMetadataItem, resetContent, onContentChange, dropdownId } =
useObjectOptionsDropdown();
const { currentView } = useGetCurrentViewOnly();
const { updateCurrentView } = useUpdateCurrentView();
const {
recordIndexId,
objectMetadataItem,
resetContent,
onContentChange,
dropdownId,
} = useObjectOptionsDropdown();
const isCompactModeActive = currentView?.isCompact ?? false;
const { isCompactModeActive, setAndPersistIsCompactModeActive } =
useObjectOptionsForBoard({
objectNameSingular: objectMetadataItem.nameSingular,
recordBoardId: recordIndexId,
viewBarId: recordIndexId,
});
const setAndPersistIsCompactModeActive = useCallback(
(isCompactModeActive: boolean, view: GraphQLView | undefined) => {
if (!view) return;
updateCurrentView({
isCompact: isCompactModeActive,
});
},
[updateCurrentView],
);
const recordIndexOpenRecordIn = useRecoilValue(recordIndexOpenRecordInState);
const recordIndexCalendarLayout = useRecoilValue(
@@ -116,10 +120,11 @@ export const ObjectOptionsDropdownLayoutContent = () => {
...(isDefaultView ? [] : [ViewType.Kanban]),
...(!isDefaultView && hasCalendarViewEnabled ? [ViewType.Calendar] : []),
ViewOpenRecordInType.SIDE_PANEL,
...(currentView?.type === ViewType.Kanban ? ['Group', 'Compact view'] : []),
...(currentView?.type === ViewType.Kanban ? ['Group'] : []),
...(currentView?.type === ViewType.Calendar
? ['CalendarView', 'CalendarDateField']
: []),
...(currentView?.type !== ViewType.Table ? ['Compact view'] : []),
];
const selectedItemId = useRecoilComponentValue(
@@ -273,53 +278,52 @@ export const ObjectOptionsDropdownLayoutContent = () => {
/>
</SelectableListItem>
{currentView?.type === ViewType.Kanban && (
<>
<SelectableListItem
itemId="Group"
onEnter={() => {
<SelectableListItem
itemId="Group"
onEnter={() => {
isDefined(recordGroupFieldMetadata)
? onContentChange('recordGroups')
: onContentChange('recordGroupFields');
}}
>
<MenuItem
focused={selectedItemId === 'Group'}
onClick={() =>
isDefined(recordGroupFieldMetadata)
? onContentChange('recordGroups')
: onContentChange('recordGroupFields');
}}
>
<MenuItem
focused={selectedItemId === 'Group'}
onClick={() =>
isDefined(recordGroupFieldMetadata)
? onContentChange('recordGroups')
: onContentChange('recordGroupFields')
}
LeftIcon={IconLayoutList}
text={t`Group`}
contextualText={recordGroupFieldMetadata?.label}
hasSubMenu
/>
</SelectableListItem>
<SelectableListItem
itemId="Compact view"
onEnter={() => {
: onContentChange('recordGroupFields')
}
LeftIcon={IconLayoutList}
text={t`Group`}
contextualText={recordGroupFieldMetadata?.label}
hasSubMenu
/>
</SelectableListItem>
)}
{currentView?.type !== ViewType.Table && (
<SelectableListItem
itemId="Compact view"
onEnter={() => {
setAndPersistIsCompactModeActive(
!isCompactModeActive,
currentView,
);
}}
>
<MenuItemToggle
focused={selectedItemId === 'Compact view'}
LeftIcon={IconBaselineDensitySmall}
onToggleChange={() =>
setAndPersistIsCompactModeActive(
!isCompactModeActive,
currentView,
);
}}
>
<MenuItemToggle
focused={selectedItemId === 'Compact view'}
LeftIcon={IconBaselineDensitySmall}
onToggleChange={() =>
setAndPersistIsCompactModeActive(
!isCompactModeActive,
currentView,
)
}
toggled={isCompactModeActive}
text={t`Compact view`}
toggleSize="small"
/>
</SelectableListItem>
</>
)
}
toggled={isCompactModeActive}
text={t`Compact view`}
toggleSize="small"
/>
</SelectableListItem>
)}
</DropdownMenuItemsContainer>
</SelectableList>
@@ -4,7 +4,6 @@ import { useRecoilState } from 'recoil';
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { isRecordBoardCompactModeActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCompactModeActiveComponentState';
import { useReorderVisibleRecordFields } from '@/object-record/record-field/hooks/useReorderVisibleRecordFields';
import { useUpdateRecordField } from '@/object-record/record-field/hooks/useUpdateRecordField';
import { useUpsertRecordField } from '@/object-record/record-field/hooks/useUpsertRecordField';
@@ -13,11 +12,8 @@ import { type RecordField } from '@/object-record/record-field/types/RecordField
import { type FieldMetadata } from '@/object-record/record-field/ui/types/FieldMetadata';
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
import { type ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSaveCurrentViewFields } from '@/views/hooks/useSaveCurrentViewFields';
import { useUpdateCurrentView } from '@/views/hooks/useUpdateCurrentView';
import { type GraphQLView } from '@/views/types/GraphQLView';
import { mapRecordFieldToViewField } from '@/views/utils/mapRecordFieldToViewField';
import { produce } from 'immer';
import { findByProperty, isDefined } from 'twenty-shared/utils';
@@ -39,12 +35,6 @@ export const useObjectOptionsForBoard = ({
useRecoilState(recordIndexFieldDefinitionsState);
const { saveViewFields } = useSaveCurrentViewFields();
const { updateCurrentView } = useUpdateCurrentView();
const [isCompactModeActive, setIsCompactModeActive] = useRecoilComponentState(
isRecordBoardCompactModeActiveComponentState,
recordBoardId,
);
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular,
@@ -252,23 +242,10 @@ export const useObjectOptionsForBoard = ({
],
);
const setAndPersistIsCompactModeActive = useCallback(
(isCompactModeActive: boolean, view: GraphQLView | undefined) => {
if (!view) return;
setIsCompactModeActive(isCompactModeActive);
updateCurrentView({
isCompact: isCompactModeActive,
});
},
[setIsCompactModeActive, updateCurrentView],
);
return {
handleReorderBoardFields,
handleBoardFieldVisibilityChange,
visibleBoardFields,
hiddenBoardFields,
isCompactModeActive,
setAndPersistIsCompactModeActive,
};
};