Remove the heart icon button to add the view as a favorite from the top bar (#8769)
closes #8546 @Bonapara please check the behaviour, if this is what you were looking for! ;)
This commit is contained in:
@ -38,6 +38,7 @@ export const PageFavoriteFoldersDropdown = ({
|
|||||||
onSubmit={closeDropdown}
|
onSubmit={closeDropdown}
|
||||||
record={record}
|
record={record}
|
||||||
objectNameSingular={objectNameSingular}
|
objectNameSingular={objectNameSingular}
|
||||||
|
dropdownId={dropdownId}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ type FavoriteFolderPickerProps = {
|
|||||||
onSubmit?: () => void;
|
onSubmit?: () => void;
|
||||||
record?: ObjectRecord;
|
record?: ObjectRecord;
|
||||||
objectNameSingular: string;
|
objectNameSingular: string;
|
||||||
|
dropdownId: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const NO_FOLDER_ID = 'no-folder';
|
const NO_FOLDER_ID = 'no-folder';
|
||||||
@ -28,6 +29,7 @@ export const FavoriteFolderPicker = ({
|
|||||||
onSubmit,
|
onSubmit,
|
||||||
record,
|
record,
|
||||||
objectNameSingular,
|
objectNameSingular,
|
||||||
|
dropdownId,
|
||||||
}: FavoriteFolderPickerProps) => {
|
}: FavoriteFolderPickerProps) => {
|
||||||
const [isFavoriteFolderCreating, setIsFavoriteFolderCreating] =
|
const [isFavoriteFolderCreating, setIsFavoriteFolderCreating] =
|
||||||
useRecoilState(isFavoriteFolderCreatingState);
|
useRecoilState(isFavoriteFolderCreatingState);
|
||||||
@ -97,7 +99,7 @@ export const FavoriteFolderPicker = ({
|
|||||||
toggleFolderSelection={toggleFolderSelection}
|
toggleFolderSelection={toggleFolderSelection}
|
||||||
/>
|
/>
|
||||||
</DropdownMenuItemsContainer>
|
</DropdownMenuItemsContainer>
|
||||||
<FavoriteFolderPickerFooter />
|
<FavoriteFolderPickerFooter dropdownId={dropdownId} />
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { FAVORITE_FOLDER_PICKER_DROPDOWN_ID } from '@/favorites/favorite-folder-picker/constants/FavoriteFolderPickerDropdownId';
|
|
||||||
import { isFavoriteFolderCreatingState } from '@/favorites/states/isFavoriteFolderCreatingState';
|
import { isFavoriteFolderCreatingState } from '@/favorites/states/isFavoriteFolderCreatingState';
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||||
@ -10,13 +9,16 @@ import { useRecoilState, useSetRecoilState } from 'recoil';
|
|||||||
import { IconPlus, MenuItem } from 'twenty-ui';
|
import { IconPlus, MenuItem } from 'twenty-ui';
|
||||||
|
|
||||||
const StyledFooter = styled.div`
|
const StyledFooter = styled.div`
|
||||||
background: ${({ theme }) => theme.background.primary};
|
|
||||||
border-bottom-left-radius: ${({ theme }) => theme.border.radius.md};
|
border-bottom-left-radius: ${({ theme }) => theme.border.radius.md};
|
||||||
border-bottom-right-radius: ${({ theme }) => theme.border.radius.md};
|
border-bottom-right-radius: ${({ theme }) => theme.border.radius.md};
|
||||||
border-top: 1px solid ${({ theme }) => theme.border.color.light};
|
border-top: 1px solid ${({ theme }) => theme.border.color.light};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const FavoriteFolderPickerFooter = () => {
|
export const FavoriteFolderPickerFooter = ({
|
||||||
|
dropdownId,
|
||||||
|
}: {
|
||||||
|
dropdownId: string;
|
||||||
|
}) => {
|
||||||
const [, setIsFavoriteFolderCreating] = useRecoilState(
|
const [, setIsFavoriteFolderCreating] = useRecoilState(
|
||||||
isFavoriteFolderCreatingState,
|
isFavoriteFolderCreatingState,
|
||||||
);
|
);
|
||||||
@ -25,7 +27,7 @@ export const FavoriteFolderPickerFooter = () => {
|
|||||||
);
|
);
|
||||||
const { openNavigationSection } = useNavigationSection('Favorites');
|
const { openNavigationSection } = useNavigationSection('Favorites');
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { closeDropdown } = useDropdown(FAVORITE_FOLDER_PICKER_DROPDOWN_ID);
|
const { closeDropdown } = useDropdown(dropdownId);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledFooter>
|
<StyledFooter>
|
||||||
|
|||||||
@ -1,21 +1,12 @@
|
|||||||
import { PageFavoriteFoldersDropdown } from '@/favorites/components/PageFavoriteFolderDropdown';
|
|
||||||
import { FAVORITE_FOLDER_PICKER_DROPDOWN_ID } from '@/favorites/favorite-folder-picker/constants/FavoriteFolderPickerDropdownId';
|
|
||||||
import { useFavorites } from '@/favorites/hooks/useFavorites';
|
|
||||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||||
import { isObjectMetadataReadOnly } from '@/object-metadata/utils/isObjectMetadataReadOnly';
|
import { isObjectMetadataReadOnly } from '@/object-metadata/utils/isObjectMetadataReadOnly';
|
||||||
import { RecordIndexPageKanbanAddButton } from '@/object-record/record-index/components/RecordIndexPageKanbanAddButton';
|
import { RecordIndexPageKanbanAddButton } from '@/object-record/record-index/components/RecordIndexPageKanbanAddButton';
|
||||||
import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext';
|
import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext';
|
||||||
import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState';
|
import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState';
|
||||||
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
|
|
||||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
|
||||||
import { PageAddButton } from '@/ui/layout/page/components/PageAddButton';
|
import { PageAddButton } from '@/ui/layout/page/components/PageAddButton';
|
||||||
import { PageHeader } from '@/ui/layout/page/components/PageHeader';
|
import { PageHeader } from '@/ui/layout/page/components/PageHeader';
|
||||||
import { PageHotkeysEffect } from '@/ui/layout/page/components/PageHotkeysEffect';
|
import { PageHotkeysEffect } from '@/ui/layout/page/components/PageHotkeysEffect';
|
||||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
|
||||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
|
||||||
import { View } from '@/views/types/View';
|
|
||||||
import { ViewType } from '@/views/types/ViewType';
|
import { ViewType } from '@/views/types/ViewType';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import { useIcons } from 'twenty-ui';
|
import { useIcons } from 'twenty-ui';
|
||||||
@ -24,27 +15,10 @@ import { capitalize } from '~/utils/string/capitalize';
|
|||||||
export const RecordIndexPageHeader = () => {
|
export const RecordIndexPageHeader = () => {
|
||||||
const { findObjectMetadataItemByNamePlural } =
|
const { findObjectMetadataItemByNamePlural } =
|
||||||
useFilteredObjectMetadataItems();
|
useFilteredObjectMetadataItems();
|
||||||
const isFavoriteFolderEnabled = useIsFeatureEnabled(
|
|
||||||
'IS_FAVORITE_FOLDER_ENABLED',
|
|
||||||
);
|
|
||||||
|
|
||||||
const { objectNamePlural, onCreateRecord, recordIndexId } = useContext(
|
const { objectNamePlural, onCreateRecord } = useContext(
|
||||||
RecordIndexRootPropsContext,
|
RecordIndexRootPropsContext,
|
||||||
);
|
);
|
||||||
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
|
|
||||||
const currentViewId = useRecoilComponentValueV2(
|
|
||||||
currentViewIdComponentState,
|
|
||||||
recordIndexId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const view = views.find((view) => view.id === currentViewId);
|
|
||||||
|
|
||||||
const { sortedFavorites: favorites } = useFavorites();
|
|
||||||
|
|
||||||
const isFavorite = favorites.some(
|
|
||||||
(favorite) =>
|
|
||||||
favorite.recordId === currentViewId && favorite.workspaceMemberId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const objectMetadataItem =
|
const objectMetadataItem =
|
||||||
findObjectMetadataItemByNamePlural(objectNamePlural);
|
findObjectMetadataItemByNamePlural(objectNamePlural);
|
||||||
@ -72,14 +46,6 @@ export const RecordIndexPageHeader = () => {
|
|||||||
return (
|
return (
|
||||||
<PageHeader title={pageHeaderTitle} Icon={Icon}>
|
<PageHeader title={pageHeaderTitle} Icon={Icon}>
|
||||||
<PageHotkeysEffect onAddButtonClick={handleAddButtonClick} />
|
<PageHotkeysEffect onAddButtonClick={handleAddButtonClick} />
|
||||||
{isFavoriteFolderEnabled && (
|
|
||||||
<PageFavoriteFoldersDropdown
|
|
||||||
record={view}
|
|
||||||
dropdownId={FAVORITE_FOLDER_PICKER_DROPDOWN_ID}
|
|
||||||
objectNameSingular="view"
|
|
||||||
isFavorite={isFavorite}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{shouldDisplayAddButton &&
|
{shouldDisplayAddButton &&
|
||||||
(isTable ? (
|
(isTable ? (
|
||||||
<PageAddButton onClick={handleAddButtonClick} />
|
<PageAddButton onClick={handleAddButtonClick} />
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { TEXT_INPUT_STYLE } from 'twenty-ui';
|
|||||||
const StyledDropdownMenuSearchInputContainer = styled.div`
|
const StyledDropdownMenuSearchInputContainer = styled.div`
|
||||||
align-items: center;
|
align-items: center;
|
||||||
--vertical-padding: ${({ theme }) => theme.spacing(2)};
|
--vertical-padding: ${({ theme }) => theme.spacing(2)};
|
||||||
|
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||||
display: flex;
|
display: flex;
|
||||||
background: ${({ theme }) => theme.background.transparent.secondary};
|
background: ${({ theme }) => theme.background.transparent.secondary};
|
||||||
backdrop-filter: ${({ theme }) => theme.blur.medium};
|
backdrop-filter: ${({ theme }) => theme.blur.medium};
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { SelectHotkeyScope } from '@/ui/input/types/SelectHotkeyScope';
|
import { SelectHotkeyScope } from '@/ui/input/types/SelectHotkeyScope';
|
||||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
|
import { Placement } from '@floating-ui/react';
|
||||||
import { FunctionComponent, MouseEvent, ReactElement, ReactNode } from 'react';
|
import { FunctionComponent, MouseEvent, ReactElement, ReactNode } from 'react';
|
||||||
import {
|
import {
|
||||||
IconChevronRight,
|
IconChevronRight,
|
||||||
@ -36,6 +37,7 @@ export type MenuItemWithOptionDropdownProps = {
|
|||||||
testId?: string;
|
testId?: string;
|
||||||
text: ReactNode;
|
text: ReactNode;
|
||||||
hasSubMenu?: boolean;
|
hasSubMenu?: boolean;
|
||||||
|
dropdownPlacement?: Placement;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: refactor this
|
// TODO: refactor this
|
||||||
@ -53,6 +55,7 @@ export const MenuItemWithOptionDropdown = ({
|
|||||||
testId,
|
testId,
|
||||||
text,
|
text,
|
||||||
hasSubMenu = false,
|
hasSubMenu = false,
|
||||||
|
dropdownPlacement = 'bottom-end',
|
||||||
}: MenuItemWithOptionDropdownProps) => {
|
}: MenuItemWithOptionDropdownProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
@ -86,6 +89,7 @@ export const MenuItemWithOptionDropdown = ({
|
|||||||
accent="tertiary"
|
accent="tertiary"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
dropdownPlacement={dropdownPlacement}
|
||||||
dropdownComponents={dropdownContent}
|
dropdownComponents={dropdownContent}
|
||||||
dropdownId={dropdownId}
|
dropdownId={dropdownId}
|
||||||
dropdownHotkeyScope={{ scope: SelectHotkeyScope.Select }}
|
dropdownHotkeyScope={{ scope: SelectHotkeyScope.Select }}
|
||||||
|
|||||||
@ -17,10 +17,12 @@ import { ViewsHotkeyScope } from '@/views/types/ViewsHotkeyScope';
|
|||||||
import { ViewPickerContentCreateMode } from '@/views/view-picker/components/ViewPickerContentCreateMode';
|
import { ViewPickerContentCreateMode } from '@/views/view-picker/components/ViewPickerContentCreateMode';
|
||||||
import { ViewPickerContentEditMode } from '@/views/view-picker/components/ViewPickerContentEditMode';
|
import { ViewPickerContentEditMode } from '@/views/view-picker/components/ViewPickerContentEditMode';
|
||||||
import { ViewPickerContentEffect } from '@/views/view-picker/components/ViewPickerContentEffect';
|
import { ViewPickerContentEffect } from '@/views/view-picker/components/ViewPickerContentEffect';
|
||||||
|
import { ViewPickerFavoriteFoldersDropdown } from '@/views/view-picker/components/ViewPickerFavoriteFoldersDropdown';
|
||||||
import { ViewPickerListContent } from '@/views/view-picker/components/ViewPickerListContent';
|
import { ViewPickerListContent } from '@/views/view-picker/components/ViewPickerListContent';
|
||||||
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
|
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
|
||||||
import { useUpdateViewFromCurrentState } from '@/views/view-picker/hooks/useUpdateViewFromCurrentState';
|
import { useUpdateViewFromCurrentState } from '@/views/view-picker/hooks/useUpdateViewFromCurrentState';
|
||||||
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
||||||
|
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||||
import { isDefined } from '~/utils/isDefined';
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
const StyledDropdownLabelAdornments = styled.span`
|
const StyledDropdownLabelAdornments = styled.span`
|
||||||
@ -49,6 +51,9 @@ const StyledViewName = styled.span`
|
|||||||
|
|
||||||
export const ViewPickerDropdown = () => {
|
export const ViewPickerDropdown = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
const isFavoriteFolderEnabled = useIsFeatureEnabled(
|
||||||
|
'IS_FAVORITE_FOLDER_ENABLED',
|
||||||
|
);
|
||||||
|
|
||||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||||
|
|
||||||
@ -99,21 +104,33 @@ export const ViewPickerDropdown = () => {
|
|||||||
</StyledDropdownLabelAdornments>
|
</StyledDropdownLabelAdornments>
|
||||||
</StyledDropdownButtonContainer>
|
</StyledDropdownButtonContainer>
|
||||||
}
|
}
|
||||||
dropdownComponents={
|
dropdownComponents={(() => {
|
||||||
viewPickerMode === 'list' ? (
|
switch (viewPickerMode) {
|
||||||
<ViewPickerListContent />
|
case 'list':
|
||||||
) : (
|
return <ViewPickerListContent />;
|
||||||
<>
|
case 'favorite-folders-picker':
|
||||||
{viewPickerMode === 'create-empty' ||
|
return (
|
||||||
viewPickerMode === 'create-from-current' ? (
|
isFavoriteFolderEnabled && <ViewPickerFavoriteFoldersDropdown />
|
||||||
<ViewPickerContentCreateMode />
|
);
|
||||||
) : (
|
case 'create-empty':
|
||||||
<ViewPickerContentEditMode />
|
case 'create-from-current':
|
||||||
)}
|
return (
|
||||||
<ViewPickerContentEffect />
|
<>
|
||||||
</>
|
<ViewPickerContentCreateMode />
|
||||||
)
|
<ViewPickerContentEffect />
|
||||||
}
|
</>
|
||||||
|
);
|
||||||
|
case 'edit':
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewPickerContentEditMode />
|
||||||
|
<ViewPickerContentEffect />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
})()}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,36 @@
|
|||||||
|
import { FavoriteFolderPicker } from '@/favorites/favorite-folder-picker/components/FavoriteFolderPicker';
|
||||||
|
import { FavoriteFolderPickerEffect } from '@/favorites/favorite-folder-picker/components/FavoriteFolderPickerEffect';
|
||||||
|
import { FavoriteFolderPickerComponentInstanceContext } from '@/favorites/favorite-folder-picker/scopes/FavoriteFolderPickerScope';
|
||||||
|
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
|
||||||
|
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||||
|
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||||
|
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||||
|
import { View } from '@/views/types/View';
|
||||||
|
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
|
||||||
|
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
|
||||||
|
|
||||||
|
export const ViewPickerFavoriteFoldersDropdown = () => {
|
||||||
|
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
|
||||||
|
const [viewPickerReferenceViewId] = useRecoilComponentStateV2(
|
||||||
|
viewPickerReferenceViewIdComponentState,
|
||||||
|
);
|
||||||
|
|
||||||
|
const view = views.find((view) => view.id === viewPickerReferenceViewId);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FavoriteFolderPickerComponentInstanceContext
|
||||||
|
favoriteFoldersScopeId={VIEW_PICKER_DROPDOWN_ID}
|
||||||
|
>
|
||||||
|
<DropdownScope dropdownScopeId={VIEW_PICKER_DROPDOWN_ID}>
|
||||||
|
<>
|
||||||
|
<FavoriteFolderPickerEffect record={view} />
|
||||||
|
<FavoriteFolderPicker
|
||||||
|
record={view}
|
||||||
|
objectNameSingular="view"
|
||||||
|
dropdownId={VIEW_PICKER_DROPDOWN_ID}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
</DropdownScope>
|
||||||
|
</FavoriteFolderPickerComponentInstanceContext>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -1,26 +1,18 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { DropResult } from '@hello-pangea/dnd';
|
import { DropResult } from '@hello-pangea/dnd';
|
||||||
import { MouseEvent, useCallback } from 'react';
|
import { MouseEvent, useCallback } from 'react';
|
||||||
import {
|
import { IconPlus, MenuItem } from 'twenty-ui';
|
||||||
IconLock,
|
|
||||||
IconPencil,
|
|
||||||
IconPlus,
|
|
||||||
LightIconButtonAccent,
|
|
||||||
MenuItem,
|
|
||||||
MenuItemDraggable,
|
|
||||||
useIcons,
|
|
||||||
} from 'twenty-ui';
|
|
||||||
|
|
||||||
import { DraggableItem } from '@/ui/layout/draggable-list/components/DraggableItem';
|
import { DraggableItem } from '@/ui/layout/draggable-list/components/DraggableItem';
|
||||||
import { DraggableList } from '@/ui/layout/draggable-list/components/DraggableList';
|
import { DraggableList } from '@/ui/layout/draggable-list/components/DraggableList';
|
||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
|
||||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||||
import { useChangeView } from '@/views/hooks/useChangeView';
|
import { useChangeView } from '@/views/hooks/useChangeView';
|
||||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||||
import { useUpdateView } from '@/views/hooks/useUpdateView';
|
import { useUpdateView } from '@/views/hooks/useUpdateView';
|
||||||
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
|
import { View } from '@/views/types/View';
|
||||||
|
import { ViewPickerOptionDropdown } from '@/views/view-picker/components/ViewPickerOptionDropdown';
|
||||||
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
||||||
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
|
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
|
||||||
import { moveArrayItem } from '~/utils/array/moveArrayItem';
|
import { moveArrayItem } from '~/utils/array/moveArrayItem';
|
||||||
@ -39,13 +31,11 @@ export const ViewPickerListContent = () => {
|
|||||||
|
|
||||||
const { setViewPickerMode } = useViewPickerMode();
|
const { setViewPickerMode } = useViewPickerMode();
|
||||||
|
|
||||||
const { closeDropdown } = useDropdown(VIEW_PICKER_DROPDOWN_ID);
|
|
||||||
const { updateView } = useUpdateView();
|
const { updateView } = useUpdateView();
|
||||||
const { changeView } = useChangeView();
|
const { changeView } = useChangeView();
|
||||||
|
|
||||||
const handleViewSelect = (viewId: string) => {
|
const handleViewSelect = (viewId: string) => {
|
||||||
changeView(viewId);
|
changeView(viewId);
|
||||||
closeDropdown();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddViewButtonClick = () => {
|
const handleAddViewButtonClick = () => {
|
||||||
@ -56,7 +46,7 @@ export const ViewPickerListContent = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleEditViewButtonClick = (
|
const handleEditViewButtonClick = (
|
||||||
event: MouseEvent<HTMLButtonElement>,
|
event: MouseEvent<HTMLElement>,
|
||||||
viewId: string,
|
viewId: string,
|
||||||
) => {
|
) => {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@ -64,8 +54,6 @@ export const ViewPickerListContent = () => {
|
|||||||
setViewPickerMode('edit');
|
setViewPickerMode('edit');
|
||||||
};
|
};
|
||||||
|
|
||||||
const { getIcon } = useIcons();
|
|
||||||
|
|
||||||
const handleDragEnd = useCallback(
|
const handleDragEnd = useCallback(
|
||||||
(result: DropResult) => {
|
(result: DropResult) => {
|
||||||
if (!result.destination) return;
|
if (!result.destination) return;
|
||||||
@ -87,46 +75,25 @@ export const ViewPickerListContent = () => {
|
|||||||
<DropdownMenuItemsContainer>
|
<DropdownMenuItemsContainer>
|
||||||
<DraggableList
|
<DraggableList
|
||||||
onDragEnd={handleDragEnd}
|
onDragEnd={handleDragEnd}
|
||||||
draggableItems={viewsOnCurrentObject.map((view, index) => (
|
draggableItems={viewsOnCurrentObject.map((view, index) => {
|
||||||
<DraggableItem
|
const isIndexView = view.key === 'INDEX';
|
||||||
key={view.id}
|
return (
|
||||||
draggableId={view.id}
|
<DraggableItem
|
||||||
index={index}
|
key={view.id}
|
||||||
isDragDisabled={viewsOnCurrentObject.length === 1}
|
draggableId={view.id}
|
||||||
itemComponent={
|
index={index}
|
||||||
view.key === 'INDEX' ? (
|
isDragDisabled={viewsOnCurrentObject.length === 1}
|
||||||
<MenuItemDraggable
|
itemComponent={
|
||||||
key={view.id}
|
<ViewPickerOptionDropdown
|
||||||
iconButtons={[
|
view={view as View}
|
||||||
{
|
handleViewSelect={handleViewSelect}
|
||||||
Icon: IconLock,
|
isIndexView={isIndexView}
|
||||||
},
|
onEdit={handleEditViewButtonClick}
|
||||||
].filter(isDefined)}
|
|
||||||
isIconDisplayedOnHoverOnly={false}
|
|
||||||
onClick={() => handleViewSelect(view.id)}
|
|
||||||
LeftIcon={getIcon(view.icon)}
|
|
||||||
text={view.name}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
}
|
||||||
<MenuItemDraggable
|
/>
|
||||||
key={view.id}
|
);
|
||||||
iconButtons={[
|
})}
|
||||||
{
|
|
||||||
Icon: IconPencil,
|
|
||||||
onClick: (event: MouseEvent<HTMLButtonElement>) =>
|
|
||||||
handleEditViewButtonClick(event, view.id),
|
|
||||||
accent: 'tertiary' as LightIconButtonAccent,
|
|
||||||
},
|
|
||||||
].filter(isDefined)}
|
|
||||||
isIconDisplayedOnHoverOnly={true}
|
|
||||||
onClick={() => handleViewSelect(view.id)}
|
|
||||||
LeftIcon={getIcon(view.icon)}
|
|
||||||
text={view.name}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
/>
|
/>
|
||||||
</DropdownMenuItemsContainer>
|
</DropdownMenuItemsContainer>
|
||||||
<DropdownMenuSeparator />
|
<DropdownMenuSeparator />
|
||||||
|
|||||||
@ -0,0 +1,125 @@
|
|||||||
|
import { useCreateFavorite } from '@/favorites/hooks/useCreateFavorite';
|
||||||
|
import { useFavorites } from '@/favorites/hooks/useFavorites';
|
||||||
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
|
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||||
|
import { MenuItemWithOptionDropdown } from '@/ui/navigation/menu-item/components/MenuItemWithOptionDropdown';
|
||||||
|
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||||
|
import { View } from '@/views/types/View';
|
||||||
|
import { useDeleteViewFromCurrentState } from '@/views/view-picker/hooks/useDeleteViewFromCurrentState';
|
||||||
|
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
||||||
|
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
|
||||||
|
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import {
|
||||||
|
IconHeart,
|
||||||
|
IconLock,
|
||||||
|
IconPencil,
|
||||||
|
IconTrash,
|
||||||
|
MenuItem,
|
||||||
|
useIcons,
|
||||||
|
} from 'twenty-ui';
|
||||||
|
|
||||||
|
type ViewPickerOptionDropdownProps = {
|
||||||
|
isIndexView: boolean;
|
||||||
|
view: View;
|
||||||
|
onEdit: (event: React.MouseEvent<HTMLElement>, viewId: string) => void;
|
||||||
|
handleViewSelect: (viewId: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ViewPickerOptionDropdown = ({
|
||||||
|
isIndexView,
|
||||||
|
onEdit,
|
||||||
|
view,
|
||||||
|
handleViewSelect,
|
||||||
|
}: ViewPickerOptionDropdownProps) => {
|
||||||
|
const { closeDropdown } = useDropdown(`view-picker-options-${view.id}`);
|
||||||
|
const { getIcon } = useIcons();
|
||||||
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
|
const { deleteViewFromCurrentState } = useDeleteViewFromCurrentState();
|
||||||
|
const setViewPickerReferenceViewId = useSetRecoilComponentStateV2(
|
||||||
|
viewPickerReferenceViewIdComponentState,
|
||||||
|
);
|
||||||
|
const { setViewPickerMode } = useViewPickerMode();
|
||||||
|
|
||||||
|
const isFavoriteFolderEnabled = useIsFeatureEnabled(
|
||||||
|
'IS_FAVORITE_FOLDER_ENABLED',
|
||||||
|
);
|
||||||
|
|
||||||
|
const { sortedFavorites: favorites } = useFavorites();
|
||||||
|
const { createFavorite } = useCreateFavorite();
|
||||||
|
|
||||||
|
const isFavorite = favorites.some(
|
||||||
|
(favorite) => favorite.recordId === view.id && favorite.workspaceMemberId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
setViewPickerReferenceViewId(view.id);
|
||||||
|
deleteViewFromCurrentState();
|
||||||
|
closeDropdown();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleAddToFavorites = () => {
|
||||||
|
if (!isFavorite) {
|
||||||
|
createFavorite(view, 'view');
|
||||||
|
}
|
||||||
|
setViewPickerReferenceViewId(view.id);
|
||||||
|
setViewPickerMode('favorite-folders-picker');
|
||||||
|
closeDropdown();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<MenuItemWithOptionDropdown
|
||||||
|
text={view.name}
|
||||||
|
LeftIcon={getIcon(view.icon)}
|
||||||
|
onClick={() => handleViewSelect(view.id)}
|
||||||
|
isIconDisplayedOnHoverOnly={!isIndexView}
|
||||||
|
RightIcon={!isHovered && isIndexView ? IconLock : null}
|
||||||
|
onMouseEnter={() => setIsHovered(true)}
|
||||||
|
onMouseLeave={() => {
|
||||||
|
setIsHovered(false);
|
||||||
|
closeDropdown();
|
||||||
|
}}
|
||||||
|
dropdownPlacement="bottom-start"
|
||||||
|
dropdownId={`view-picker-options-${view.id}`}
|
||||||
|
dropdownContent={
|
||||||
|
<DropdownMenuItemsContainer>
|
||||||
|
{isIndexView ? (
|
||||||
|
isFavoriteFolderEnabled && (
|
||||||
|
<MenuItem
|
||||||
|
LeftIcon={IconHeart}
|
||||||
|
text={isFavorite ? 'Manage favorite' : 'Add to Favorite'}
|
||||||
|
onClick={handleAddToFavorites}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{isFavoriteFolderEnabled && (
|
||||||
|
<MenuItem
|
||||||
|
LeftIcon={IconHeart}
|
||||||
|
text={isFavorite ? 'Manage favorite' : 'Add to Favorite'}
|
||||||
|
onClick={handleAddToFavorites}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<MenuItem
|
||||||
|
LeftIcon={IconPencil}
|
||||||
|
text="Edit"
|
||||||
|
onClick={(event) => {
|
||||||
|
onEdit(event, view.id);
|
||||||
|
closeDropdown();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
LeftIcon={IconTrash}
|
||||||
|
text="Delete"
|
||||||
|
onClick={handleDelete}
|
||||||
|
accent="danger"
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</DropdownMenuItemsContainer>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -2,4 +2,5 @@ export type ViewPickerMode =
|
|||||||
| 'list'
|
| 'list'
|
||||||
| 'edit'
|
| 'edit'
|
||||||
| 'create-empty'
|
| 'create-empty'
|
||||||
| 'create-from-current';
|
| 'create-from-current'
|
||||||
|
| 'favorite-folders-picker';
|
||||||
|
|||||||
Reference in New Issue
Block a user