|
import { useCallback, useEffect, useMemo, useState } from 'react' |
|
import useSWR from 'swr' |
|
import s from './base.module.css' |
|
import WorkspaceSelector from './workspace-selector' |
|
import SearchInput from './search-input' |
|
import PageSelector from './page-selector' |
|
import cn from '@/utils/classnames' |
|
import { preImportNotionPages } from '@/service/datasets' |
|
import { NotionConnector } from '@/app/components/datasets/create/step-one' |
|
import type { DataSourceNotionPageMap, DataSourceNotionWorkspace, NotionPage } from '@/models/common' |
|
import { useModalContext } from '@/context/modal-context' |
|
|
|
type NotionPageSelectorProps = { |
|
value?: string[] |
|
onSelect: (selectedPages: NotionPage[]) => void |
|
canPreview?: boolean |
|
previewPageId?: string |
|
onPreview?: (selectedPage: NotionPage) => void |
|
datasetId?: string |
|
} |
|
|
|
const NotionPageSelector = ({ |
|
value, |
|
onSelect, |
|
canPreview, |
|
previewPageId, |
|
onPreview, |
|
datasetId = '', |
|
}: NotionPageSelectorProps) => { |
|
const { data, mutate } = useSWR({ url: '/notion/pre-import/pages', datasetId }, preImportNotionPages) |
|
const [prevData, setPrevData] = useState(data) |
|
const [searchValue, setSearchValue] = useState('') |
|
const [currentWorkspaceId, setCurrentWorkspaceId] = useState('') |
|
const { setShowAccountSettingModal } = useModalContext() |
|
|
|
const notionWorkspaces = useMemo(() => { |
|
return data?.notion_info || [] |
|
}, [data?.notion_info]) |
|
const firstWorkspaceId = notionWorkspaces[0]?.workspace_id |
|
const currentWorkspace = notionWorkspaces.find(workspace => workspace.workspace_id === currentWorkspaceId) |
|
|
|
const getPagesMapAndSelectedPagesId: [DataSourceNotionPageMap, Set<string>, Set<string>] = useMemo(() => { |
|
const selectedPagesId = new Set<string>() |
|
const boundPagesId = new Set<string>() |
|
const pagesMap = notionWorkspaces.reduce((prev: DataSourceNotionPageMap, next: DataSourceNotionWorkspace) => { |
|
next.pages.forEach((page) => { |
|
if (page.is_bound) { |
|
selectedPagesId.add(page.page_id) |
|
boundPagesId.add(page.page_id) |
|
} |
|
prev[page.page_id] = { |
|
...page, |
|
workspace_id: next.workspace_id, |
|
} |
|
}) |
|
|
|
return prev |
|
}, {}) |
|
return [pagesMap, selectedPagesId, boundPagesId] |
|
}, [notionWorkspaces]) |
|
const defaultSelectedPagesId = [...Array.from(getPagesMapAndSelectedPagesId[1]), ...(value || [])] |
|
const [selectedPagesId, setSelectedPagesId] = useState<Set<string>>(new Set(defaultSelectedPagesId)) |
|
|
|
if (prevData !== data) { |
|
setPrevData(data) |
|
setSelectedPagesId(new Set(defaultSelectedPagesId)) |
|
} |
|
|
|
const handleSearchValueChange = useCallback((value: string) => { |
|
setSearchValue(value) |
|
}, []) |
|
const handleSelectWorkspace = useCallback((workspaceId: string) => { |
|
setCurrentWorkspaceId(workspaceId) |
|
}, []) |
|
const handleSelectPages = (newSelectedPagesId: Set<string>) => { |
|
const selectedPages = Array.from(newSelectedPagesId).map(pageId => getPagesMapAndSelectedPagesId[0][pageId]) |
|
|
|
setSelectedPagesId(new Set(Array.from(newSelectedPagesId))) |
|
onSelect(selectedPages) |
|
} |
|
const handlePreviewPage = (previewPageId: string) => { |
|
if (onPreview) |
|
onPreview(getPagesMapAndSelectedPagesId[0][previewPageId]) |
|
} |
|
|
|
useEffect(() => { |
|
setCurrentWorkspaceId(firstWorkspaceId) |
|
}, [firstWorkspaceId]) |
|
|
|
return ( |
|
<div className='bg-gray-25 border border-gray-200 rounded-xl'> |
|
{ |
|
data?.notion_info?.length |
|
? ( |
|
<> |
|
<div className='flex items-center pl-[10px] pr-2 h-11 bg-white border-b border-b-gray-200 rounded-t-xl'> |
|
<WorkspaceSelector |
|
value={currentWorkspaceId || firstWorkspaceId} |
|
items={notionWorkspaces} |
|
onSelect={handleSelectWorkspace} |
|
/> |
|
<div className='mx-1 w-[1px] h-3 bg-gray-200' /> |
|
<div |
|
className={cn(s['setting-icon'], 'w-6 h-6 cursor-pointer')} |
|
onClick={() => setShowAccountSettingModal({ payload: 'data-source', onCancelCallback: mutate })} |
|
/> |
|
<div className='grow' /> |
|
<SearchInput |
|
value={searchValue} |
|
onChange={handleSearchValueChange} |
|
/> |
|
</div> |
|
<div className='rounded-b-xl overflow-hidden'> |
|
<PageSelector |
|
value={selectedPagesId} |
|
disabledValue={getPagesMapAndSelectedPagesId[2]} |
|
searchValue={searchValue} |
|
list={currentWorkspace?.pages || []} |
|
pagesMap={getPagesMapAndSelectedPagesId[0]} |
|
onSelect={handleSelectPages} |
|
canPreview={canPreview} |
|
previewPageId={previewPageId} |
|
onPreview={handlePreviewPage} |
|
/> |
|
</div> |
|
</> |
|
) |
|
: ( |
|
<NotionConnector onSetting={() => setShowAccountSettingModal({ payload: 'data-source', onCancelCallback: mutate })} /> |
|
) |
|
} |
|
</div> |
|
) |
|
} |
|
|
|
export default NotionPageSelector |
|
|