diff --git a/libs/components/editor-blocks/src/blocks/group/GroupView.tsx b/libs/components/editor-blocks/src/blocks/group/GroupView.tsx index f377aeb73b..1fba5dc199 100644 --- a/libs/components/editor-blocks/src/blocks/group/GroupView.tsx +++ b/libs/components/editor-blocks/src/blocks/group/GroupView.tsx @@ -8,7 +8,7 @@ import { styled } from '@toeverything/components/ui'; import type { CreateView } from '@toeverything/framework/virgo'; import type { ComponentType, FC } from 'react'; import { useState } from 'react'; -import { GroupMenuWrapper } from './GroupMenu'; +import { GroupMenuWrapper } from './group-menu'; import { SceneKanban } from './scene-kanban'; import { ScenePage } from './ScenePage'; import { SceneTable } from './SceneTable'; diff --git a/libs/components/editor-blocks/src/blocks/group/group-menu/AddViewMenu.tsx b/libs/components/editor-blocks/src/blocks/group/group-menu/AddViewMenu.tsx new file mode 100644 index 0000000000..8eda3c1c48 --- /dev/null +++ b/libs/components/editor-blocks/src/blocks/group/group-menu/AddViewMenu.tsx @@ -0,0 +1,90 @@ +import { + RecastScene, + useRecastView, +} from '@toeverything/components/editor-core'; +import { AddViewIcon, DoneIcon } from '@toeverything/components/icons'; +import { Input, MuiClickAwayListener } from '@toeverything/components/ui'; +import type { ChangeEvent, KeyboardEvent } from 'react'; +import { useState } from 'react'; +import { IconButton } from '../components/IconButton'; +import { Panel } from '../components/Panel'; +import { VIEW_ICON_MAP } from './constant'; +import { PanelItem } from './styles'; + +export const AddViewMenu = () => { + const [viewName, setViewName] = useState(''); + const [viewType, setViewType] = useState(RecastScene.Page); + const [activePanel, setActivePanel] = useState(false); + const { addView, setCurrentView } = useRecastView(); + + const handleChange = (e: ChangeEvent) => { + setViewName(e.target.value.trim()); + }; + + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key !== 'Enter') { + return; + } + handleAddView(); + }; + + const handleAddView = async () => { + const newView = await addView({ name: viewName, type: viewType }); + await setCurrentView(newView); + setActivePanel(false); + }; + + return ( + setActivePanel(false)}> + setActivePanel(!activePanel)} + > + + Add View + {activePanel && ( + + + + + + + + + + {Object.entries(VIEW_ICON_MAP).map( + ([name, icon]) => ( + { + if (name === 'table') { + // The table view is under progress + return; + } + setViewType(name as RecastScene); + }} + > + {VIEW_ICON_MAP[name as RecastScene]} + {name.toUpperCase()} + + ) + )} + + + )} + + + ); +}; diff --git a/libs/components/editor-blocks/src/blocks/group/GroupMenu.tsx b/libs/components/editor-blocks/src/blocks/group/group-menu/MainMenu.tsx similarity index 79% rename from libs/components/editor-blocks/src/blocks/group/GroupMenu.tsx rename to libs/components/editor-blocks/src/blocks/group/group-menu/MainMenu.tsx index 1c9fe8ed03..92aa53566e 100644 --- a/libs/components/editor-blocks/src/blocks/group/GroupMenu.tsx +++ b/libs/components/editor-blocks/src/blocks/group/group-menu/MainMenu.tsx @@ -1,13 +1,14 @@ import { CommingSoon } from '@toeverything/components/common'; +import type { + AsyncBlock, + BlockEditor, +} from '@toeverything/components/editor-core'; import { mergeToPreviousGroup, RecastScene, - RecastView, useCurrentView, - useRecastView, } from '@toeverything/components/editor-core'; import { - AddViewIcon, FilterIcon, FullScreenIcon, GroupByIcon, @@ -15,45 +16,21 @@ import { KanBanIcon, SortIcon, TableIcon, - TodoListIcon, } from '@toeverything/components/icons'; import { Popover, useTheme } from '@toeverything/components/ui'; import { useFlag } from '@toeverything/datasource/feature-flags'; -import type { AsyncBlock, BlockEditor } from '@toeverything/framework/virgo'; -import type { ReactElement, ReactNode } from 'react'; +import type { ReactNode } from 'react'; import { useState } from 'react'; -import { Filter } from './components/filter'; -import { GroupBy } from './components/group-by/GroupBy'; -import { GroupPanel } from './components/group-panel/GroupPanel'; -import { IconButton } from './components/IconButton'; -import { Line } from './components/Line'; -import { Sorter } from './components/sorter'; -import { PANEL_CONFIG } from './config'; -import type { ActivePanel } from './types'; - -const VIEW_ICON_MAP: Record = { - page: , - kanban: , - table: , -}; - -const ViewsMenu = () => { - const { currentView, recastViews, setCurrentView } = useRecastView(); - return ( - <> - {recastViews.map(view => ( - setCurrentView(view)} - > - {VIEW_ICON_MAP[view.type]} - {view.name} - - ))} - - ); -}; +import { Filter } from '../components/filter'; +import { GroupBy } from '../components/group-by/GroupBy'; +import { GroupPanel } from '../components/group-panel/GroupPanel'; +import { IconButton } from '../components/IconButton'; +import { Line } from '../components/Line'; +import { Sorter } from '../components/sorter'; +import { PANEL_CONFIG } from '../config'; +import type { ActivePanel } from '../types'; +import { AddViewMenu } from './AddViewMenu'; +import { ViewsMenu } from './ViewsMenu'; const GroupMenuWrapper = ({ block, @@ -105,21 +82,7 @@ const GroupMenuWrapper = ({ content={ - - {filterSorterFlag && ( - - setActivePanel( - PANEL_CONFIG.ADD_VIEW as ActivePanel - ) - } - > - - Add View - - )} - + { // // Closed beta period temporarily // filterSorterFlag && ( diff --git a/libs/components/editor-blocks/src/blocks/group/group-menu/ViewsMenu.tsx b/libs/components/editor-blocks/src/blocks/group/group-menu/ViewsMenu.tsx new file mode 100644 index 0000000000..8989f4ea80 --- /dev/null +++ b/libs/components/editor-blocks/src/blocks/group/group-menu/ViewsMenu.tsx @@ -0,0 +1,128 @@ +import { + RecastScene, + RecastView, + useRecastView, +} from '@toeverything/components/editor-core'; +import { DeleteCashBinIcon, DoneIcon } from '@toeverything/components/icons'; +import { Input } from '@toeverything/components/ui'; +import type { ChangeEvent, KeyboardEvent } from 'react'; +import { useState } from 'react'; +import { IconButton } from '../components/IconButton'; +import { Panel } from '../components/Panel'; +import { VIEW_ICON_MAP } from './constant'; +import { PanelItem } from './styles'; + +export const ViewsMenu = () => { + const [viewName, setViewName] = useState(''); + const [viewType, setViewType] = useState(RecastScene.Page); + const [activeView, setActiveView] = useState(null); + const { currentView, recastViews, setCurrentView, updateView, removeView } = + useRecastView(); + + const handleChange = (e: ChangeEvent) => { + setViewName(e.target.value.trim()); + }; + + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key !== 'Enter') { + return; + } + handleUpdateView(); + }; + + const handleUpdateView = async () => { + if (!activeView) { + return; + } + await updateView({ + ...activeView, + name: viewName, + type: viewType, + }); + setActiveView(null); + }; + + const handleDelete = async () => { + if (!activeView) { + return; + } + await removeView(activeView.id); + + setActiveView(null); + }; + + return ( + <> + {recastViews.map(view => ( + setCurrentView(view)} + onContextMenu={e => { + setViewName(view.name); + setViewType(view.type); + setActiveView(view); + e.preventDefault(); + }} + > + {VIEW_ICON_MAP[view.type]} + {view.name} + + {activeView === view && ( + + + + + + + + + + + + + + {Object.entries(VIEW_ICON_MAP).map( + ([name, icon]) => ( + { + if (name === 'table') { + // The table view is under progress + return; + } + setViewType( + name as RecastScene + ); + }} + > + {VIEW_ICON_MAP[name as RecastScene]} + {name.toUpperCase()} + + ) + )} + + + )} + + ))} + + ); +}; diff --git a/libs/components/editor-blocks/src/blocks/group/group-menu/constant.tsx b/libs/components/editor-blocks/src/blocks/group/group-menu/constant.tsx new file mode 100644 index 0000000000..3645d50bb2 --- /dev/null +++ b/libs/components/editor-blocks/src/blocks/group/group-menu/constant.tsx @@ -0,0 +1,13 @@ +import { RecastView } from '@toeverything/components/editor-core'; +import { + KanBanIcon, + TableIcon, + TodoListIcon, +} from '@toeverything/components/icons'; +import type { ReactElement } from 'react'; + +export const VIEW_ICON_MAP: Record = { + page: , + kanban: , + table: , +}; diff --git a/libs/components/editor-blocks/src/blocks/group/group-menu/index.ts b/libs/components/editor-blocks/src/blocks/group/group-menu/index.ts new file mode 100644 index 0000000000..150014e955 --- /dev/null +++ b/libs/components/editor-blocks/src/blocks/group/group-menu/index.ts @@ -0,0 +1 @@ +export { GroupMenuWrapper } from './MainMenu'; diff --git a/libs/components/editor-blocks/src/blocks/group/group-menu/styles.ts b/libs/components/editor-blocks/src/blocks/group/group-menu/styles.ts new file mode 100644 index 0000000000..a8790709e1 --- /dev/null +++ b/libs/components/editor-blocks/src/blocks/group/group-menu/styles.ts @@ -0,0 +1,10 @@ +import { styled } from '@toeverything/components/ui'; + +export const PanelItem = styled('div')({ + display: 'flex', + userSelect: 'none', + + '& + &': { + marginTop: '8px', + }, +});