Option-menu-imporovements (#11309)

- icon switching : if switching layout from table to kanban
and if icon is the table icon (the default one) then automatically
update the icon to the kanban icon

- add tooltip on Layout default view to better explain why it's
unavaialble


Fixes [#689](https://github.com/twentyhq/core-team-issues/issues/689)
Fixes [#688](https://github.com/twentyhq/core-team-issues/issues/688)
Fixes [#686](https://github.com/twentyhq/core-team-issues/issues/686)
This commit is contained in:
Guillim
2025-04-01 12:31:40 +02:00
committed by GitHub
parent bc81853095
commit 9cbc2e3df0
8 changed files with 82 additions and 30 deletions

View File

@ -1,7 +1,6 @@
import {
IconBaselineDensitySmall,
IconChevronLeft,
IconLayoutKanban,
IconLayoutList,
IconLayoutNavbar,
IconLayoutSidebarRight,
@ -9,6 +8,7 @@ import {
MenuItem,
MenuItemSelect,
MenuItemToggle,
OverflowingTextWithTooltip,
} from 'twenty-ui';
import { useObjectOptionsForBoard } from '@/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard';
@ -24,7 +24,7 @@ import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { ViewType } from '@/views/types/ViewType';
import { ViewType, viewTypeIconMapping } from '@/views/types/ViewType';
import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban';
import { useLingui } from '@lingui/react/macro';
import { useRecoilValue } from 'recoil';
@ -75,6 +75,7 @@ export const ObjectOptionsDropdownLayoutContent = () => {
};
const isDefaultView = currentView?.key === 'INDEX';
const nbsp = '\u00A0';
return (
<>
@ -101,15 +102,20 @@ export const ObjectOptionsDropdownLayoutContent = () => {
}}
/>
<MenuItemSelect
LeftIcon={IconLayoutKanban}
LeftIcon={viewTypeIconMapping(ViewType.Kanban)}
text={t`Kanban`}
disabled={isDefaultView}
contextualText={
isDefaultView
? t`Not available for default view`
: availableFieldsForKanban.length === 0
? t`Create Select...`
: undefined
isDefaultView ? (
<>
{nbsp}·{nbsp}
<OverflowingTextWithTooltip
text={t`Not available for default view`}
/>
</>
) : availableFieldsForKanban.length === 0 ? (
t`Create Select...`
) : undefined
}
selected={currentView?.type === ViewType.Kanban}
onClick={handleSelectKanbanViewType}

View File

@ -2,10 +2,8 @@ import { Key } from 'ts-key-enum';
import {
AppTooltip,
IconCopy,
IconLayoutKanban,
IconLayoutList,
IconListDetails,
IconTable,
IconTrash,
MenuItem,
} from 'twenty-ui';
@ -23,7 +21,7 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { ViewType } from '@/views/types/ViewType';
import { ViewType, viewTypeIconMapping } from '@/views/types/ViewType';
import { useDeleteViewFromCurrentState } from '@/views/view-picker/hooks/useDeleteViewFromCurrentState';
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
import { useTheme } from '@emotion/react';
@ -85,9 +83,7 @@ export const ObjectOptionsDropdownMenuContent = () => {
<DropdownMenuItemsContainer scrollable={false}>
<MenuItem
onClick={() => onContentChange('layout')}
LeftIcon={
currentView?.type === ViewType.Table ? IconTable : IconLayoutKanban
}
LeftIcon={viewTypeIconMapping(currentView?.type ?? ViewType.Table)}
text={t`Layout`}
contextualText={`${capitalize(currentView?.type ?? '')}`}
hasSubMenu

View File

@ -61,6 +61,8 @@ export const ObjectOptionsDropdownMenuViewName = ({
const [viewPickerSelectedIcon, setViewPickerSelectedIcon] =
useRecoilComponentStateV2(viewPickerSelectedIconComponentState);
setViewPickerSelectedIcon(currentView.icon);
const viewPickerIsPersisting = useRecoilComponentValueV2(
viewPickerIsPersistingComponentState,
);

View File

@ -9,7 +9,7 @@ import { usePersistViewGroupRecords } from '@/views/hooks/internal/usePersistVie
import { useUpdateCurrentView } from '@/views/hooks/useUpdateCurrentView';
import { GraphQLView } from '@/views/types/GraphQLView';
import { ViewGroup } from '@/views/types/ViewGroup';
import { ViewType } from '@/views/types/ViewType';
import { ViewType, viewTypeIconMapping } from '@/views/types/ViewType';
import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban';
import { useCallback } from 'react';
import { useRecoilCallback, useSetRecoilState } from 'recoil';
@ -122,13 +122,20 @@ export const useSetViewTypeFromLayoutOptionsMenu = () => {
);
}
setRecordIndexViewType(viewType);
await updateCurrentView(updateCurrentViewParams);
break;
if (shouldChangeIcon(currentView.icon, currentView.type)) {
updateCurrentViewParams.icon =
viewTypeIconMapping(viewType).displayName;
}
return await updateCurrentView(updateCurrentViewParams);
}
case ViewType.Table:
setRecordIndexViewType(viewType);
await updateCurrentView(updateCurrentViewParams);
break;
if (shouldChangeIcon(currentView.icon, currentView.type)) {
updateCurrentViewParams.icon =
viewTypeIconMapping(viewType).displayName;
}
return await updateCurrentView(updateCurrentViewParams);
default: {
return assertUnreachable(viewType);
}
@ -144,6 +151,25 @@ export const useSetViewTypeFromLayoutOptionsMenu = () => {
],
);
const shouldChangeIcon = (
oldIcon: string,
oldViewType: ViewType,
): boolean => {
if (
oldViewType === ViewType.Kanban &&
oldIcon === viewTypeIconMapping(ViewType.Kanban).displayName
) {
return true;
}
if (
oldViewType === ViewType.Table &&
oldIcon === viewTypeIconMapping(ViewType.Table).displayName
) {
return true;
}
return false;
};
return {
setAndPersistViewType,
};