Files
twenty_crm/front/src/modules/ui/table/options/components/TableOptionsDropdownContent.tsx
Lucas Bordeau 8627416d60 Refator/sorts dropdown (#1568)
* WIP

* Fixed lint

* Ok for sorts

* Fixed on dropdown toggle

* Fix lint
2023-09-13 16:38:11 -07:00

163 lines
5.4 KiB
TypeScript

import { useRef, useState } from 'react';
import { useRecoilValue } from 'recoil';
import { Key } from 'ts-key-enum';
import { DropdownMenuHeader } from '@/ui/dropdown/components/DropdownMenuHeader';
import { DropdownMenuInput } from '@/ui/dropdown/components/DropdownMenuInput';
import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu';
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
import { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton';
import { IconChevronLeft, IconFileImport, IconTag } from '@/ui/icon';
import { MenuItem } from '@/ui/menu-item/components/MenuItem';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { ViewFieldsVisibilityDropdownSection } from '@/ui/view-bar/components/ViewFieldsVisibilityDropdownSection';
import { useUpsertView } from '@/ui/view-bar/hooks/useUpsertView';
import { viewsByIdScopedSelector } from '@/ui/view-bar/states/selectors/viewsByIdScopedSelector';
import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState';
import type { View } from '@/ui/view-bar/types/View';
import { TableOptionsDropdownId } from '../../constants/TableOptionsDropdownId';
import { useTableColumns } from '../../hooks/useTableColumns';
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
import { hiddenTableColumnsScopedSelector } from '../../states/selectors/hiddenTableColumnsScopedSelector';
import { visibleTableColumnsScopedSelector } from '../../states/selectors/visibleTableColumnsScopedSelector';
import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
type TableOptionsDropdownButtonProps = {
onViewsChange?: (views: View[]) => void | Promise<void>;
onImport?: () => void;
};
type TableOptionsMenu = 'fields';
export function TableOptionsDropdownContent({
onViewsChange,
onImport,
}: TableOptionsDropdownButtonProps) {
const { closeDropdownButton } = useDropdownButton({
dropdownId: TableOptionsDropdownId,
});
const [currentMenu, setCurrentMenu] = useState<TableOptionsMenu | undefined>(
undefined,
);
const viewEditInputRef = useRef<HTMLInputElement>(null);
const viewEditMode = useRecoilValue(viewEditModeState);
const visibleTableColumns = useRecoilScopedValue(
visibleTableColumnsScopedSelector,
TableRecoilScopeContext,
);
const hiddenTableColumns = useRecoilScopedValue(
hiddenTableColumnsScopedSelector,
TableRecoilScopeContext,
);
const viewsById = useRecoilScopedValue(
viewsByIdScopedSelector,
TableRecoilScopeContext,
);
const { upsertView } = useUpsertView({
onViewsChange,
scopeContext: TableRecoilScopeContext,
});
const { handleColumnVisibilityChange } = useTableColumns();
const handleViewNameSubmit = async () => {
const name = viewEditInputRef.current?.value;
await upsertView(name);
};
const handleSelectMenu = (option: TableOptionsMenu) => {
handleViewNameSubmit();
setCurrentMenu(option);
};
const resetMenu = () => setCurrentMenu(undefined);
useScopedHotkeys(
Key.Escape,
() => {
closeDropdownButton();
},
TableOptionsHotkeyScope.Dropdown,
);
useScopedHotkeys(
Key.Enter,
() => {
handleViewNameSubmit();
resetMenu();
closeDropdownButton();
},
TableOptionsHotkeyScope.Dropdown,
);
return (
<StyledDropdownMenu>
{!currentMenu && (
<>
{!!viewEditMode.mode ? (
<DropdownMenuInput
ref={viewEditInputRef}
autoFocus
placeholder={
viewEditMode.mode === 'create' ? 'New view' : 'View name'
}
defaultValue={
viewEditMode.viewId
? viewsById[viewEditMode.viewId]?.name
: undefined
}
/>
) : (
<DropdownMenuHeader>View settings</DropdownMenuHeader>
)}
<StyledDropdownMenuSeparator />
<StyledDropdownMenuItemsContainer>
<MenuItem
onClick={() => handleSelectMenu('fields')}
LeftIcon={IconTag}
text="Fields"
/>
{onImport && (
<MenuItem
onClick={onImport}
LeftIcon={IconFileImport}
text="Import"
/>
)}
</StyledDropdownMenuItemsContainer>
</>
)}
{currentMenu === 'fields' && (
<>
<DropdownMenuHeader StartIcon={IconChevronLeft} onClick={resetMenu}>
Fields
</DropdownMenuHeader>
<StyledDropdownMenuSeparator />
<ViewFieldsVisibilityDropdownSection
title="Visible"
fields={visibleTableColumns}
onVisibilityChange={handleColumnVisibilityChange}
/>
{hiddenTableColumns.length > 0 && (
<>
<StyledDropdownMenuSeparator />
<ViewFieldsVisibilityDropdownSection
title="Hidden"
fields={hiddenTableColumns}
onVisibilityChange={handleColumnVisibilityChange}
/>
</>
)}
</>
)}
</StyledDropdownMenu>
);
}