refactor: Restructure breadcrumbs component; introduce Bucket and BreadcrumbItem components for improved navigation
parent
9ce0c69687
commit
d44af3ec46
@ -1,57 +0,0 @@
|
||||
import { BucketsGray } from '@/app/components/base/icons/src/public/knowledge/online-drive'
|
||||
import React, { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useDataSourceStore } from '../../../store'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
type BreadcrumbsProps = {
|
||||
prefix: string[]
|
||||
keywords: string
|
||||
bucket: string
|
||||
searchResultsLength: number
|
||||
}
|
||||
|
||||
const Breadcrumbs = ({
|
||||
prefix,
|
||||
keywords,
|
||||
bucket,
|
||||
searchResultsLength,
|
||||
}: BreadcrumbsProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { setFileList, setSelectedFileList, setPrefix, setBucket } = useDataSourceStore().getState()
|
||||
const isRoot = prefix.length === 0 && bucket === ''
|
||||
const isSearching = !!keywords
|
||||
|
||||
const handleBackToBucketList = useCallback(() => {
|
||||
setFileList([])
|
||||
setSelectedFileList([])
|
||||
setBucket('')
|
||||
setPrefix([])
|
||||
}, [setBucket, setFileList, setPrefix, setSelectedFileList])
|
||||
|
||||
return (
|
||||
<div className='flex grow items-center py-1'>
|
||||
{isRoot && (
|
||||
<div className='system-sm-medium text-test-secondary px-[5px] py-1'>
|
||||
{t('datasetPipeline.onlineDrive.breadcrumbs.allBuckets')}
|
||||
</div>
|
||||
)}
|
||||
{!isRoot && (
|
||||
<div className='flex items-center gap-x-0.5'>
|
||||
<Tooltip
|
||||
popupContent={t('datasetPipeline.onlineDrive.breadcrumbs.allBuckets')}
|
||||
>
|
||||
<div
|
||||
className='flex size-5 cursor-pointer items-center justify-center'
|
||||
onClick={handleBackToBucketList}
|
||||
>
|
||||
<BucketsGray />
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(Breadcrumbs)
|
||||
@ -0,0 +1,33 @@
|
||||
import React from 'react'
|
||||
import { BucketsGray } from '@/app/components/base/icons/src/public/knowledge/online-drive'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
type BucketProps = {
|
||||
handleBackToBucketList: () => void
|
||||
}
|
||||
|
||||
const Bucket = ({
|
||||
handleBackToBucketList,
|
||||
}: BucketProps) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip
|
||||
popupContent={t('datasetPipeline.onlineDrive.breadcrumbs.allBuckets')}
|
||||
>
|
||||
<button
|
||||
type='button'
|
||||
className='flex size-6 cursor-pointer items-center justify-center rounded-md hover:bg-state-base-hover'
|
||||
onClick={handleBackToBucketList}
|
||||
>
|
||||
<BucketsGray />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<span className='system-xs-regular text-divider-deep'>/</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(Bucket)
|
||||
@ -0,0 +1,98 @@
|
||||
import React, { useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useDataSourceStore } from '../../../../store'
|
||||
import Bucket from './bucket'
|
||||
import BreadcrumbItem from './item'
|
||||
|
||||
type BreadcrumbsProps = {
|
||||
prefix: string[]
|
||||
keywords: string
|
||||
bucket: string
|
||||
searchResultsLength: number
|
||||
isInPipeline: boolean
|
||||
}
|
||||
|
||||
const Breadcrumbs = ({
|
||||
prefix,
|
||||
keywords,
|
||||
bucket,
|
||||
searchResultsLength,
|
||||
isInPipeline,
|
||||
}: BreadcrumbsProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { setFileList, setSelectedFileList, setPrefix, setBucket } = useDataSourceStore().getState()
|
||||
const showSearchResult = !!keywords && searchResultsLength > 0
|
||||
const isRoot = prefix.length === 0 && bucket === ''
|
||||
|
||||
const breadcrumbs = useMemo(() => {
|
||||
const displayBreadcrumbNum = isInPipeline ? 2 : 3
|
||||
const prefixToDisplay = prefix.slice(0, displayBreadcrumbNum - 1)
|
||||
const collapsedBreadcrumbs = prefix.slice(displayBreadcrumbNum - 1, prefix.length - 1)
|
||||
return {
|
||||
original: prefix,
|
||||
needCollapsed: prefix.length > displayBreadcrumbNum,
|
||||
prefixBreadcrumbs: prefixToDisplay,
|
||||
collapsedBreadcrumbs,
|
||||
lastBreadcrumb: prefix[prefix.length - 1],
|
||||
}
|
||||
}, [isInPipeline, prefix])
|
||||
|
||||
const handleBackToBucketList = useCallback(() => {
|
||||
setFileList([])
|
||||
setSelectedFileList([])
|
||||
setBucket('')
|
||||
setPrefix([])
|
||||
}, [setBucket, setFileList, setPrefix, setSelectedFileList])
|
||||
|
||||
const handleClickBreadcrumb = useCallback((index: number) => {
|
||||
const newPrefix = breadcrumbs.prefixBreadcrumbs.slice(0, index - 1)
|
||||
setFileList([])
|
||||
setSelectedFileList([])
|
||||
setPrefix(newPrefix)
|
||||
}, [breadcrumbs.prefixBreadcrumbs, setFileList, setPrefix, setSelectedFileList])
|
||||
|
||||
return (
|
||||
<div className='flex grow items-center py-1'>
|
||||
{showSearchResult && (
|
||||
<div className='system-sm-medium text-test-secondary px-[5px] py-1'>
|
||||
{t('datasetPipeline.onlineDrive.breadcrumbs.searchResult', {
|
||||
searchResultsLength,
|
||||
folderName: prefix.length > 0 ? prefix[prefix.length - 1] : bucket,
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
{!showSearchResult && isRoot && (
|
||||
<div className='system-sm-medium text-test-secondary px-[5px] py-1'>
|
||||
{t('datasetPipeline.onlineDrive.breadcrumbs.allBuckets')}
|
||||
</div>
|
||||
)}
|
||||
{!showSearchResult && !isRoot && (
|
||||
<div className='flex items-center gap-x-0.5'>
|
||||
{bucket && (
|
||||
<Bucket handleBackToBucketList={handleBackToBucketList} />
|
||||
)}
|
||||
{!breadcrumbs.needCollapsed && (
|
||||
<>
|
||||
{breadcrumbs.original.map((breadcrumb, index) => {
|
||||
const isLast = index === breadcrumbs.original.length - 1
|
||||
return (
|
||||
<BreadcrumbItem
|
||||
key={`${breadcrumb}-${index}`}
|
||||
index={index}
|
||||
handleClick={handleClickBreadcrumb}
|
||||
name={breadcrumb}
|
||||
isActive={isLast}
|
||||
showSeparator={!isLast}
|
||||
disabled={isLast}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(Breadcrumbs)
|
||||
@ -0,0 +1,47 @@
|
||||
import React, { useCallback } from 'react'
|
||||
import cn from '@/utils/classnames'
|
||||
|
||||
type BreadcrumbItemProps = {
|
||||
name: string
|
||||
index: number
|
||||
handleClick: (index: number) => void
|
||||
disabled?: boolean
|
||||
isActive?: boolean
|
||||
showSeparator?: boolean
|
||||
}
|
||||
|
||||
const BreadcrumbItem = ({
|
||||
name,
|
||||
index,
|
||||
handleClick,
|
||||
disabled = false,
|
||||
isActive = false,
|
||||
showSeparator = true,
|
||||
}: BreadcrumbItemProps) => {
|
||||
const handleClickItem = useCallback(() => {
|
||||
if (!disabled)
|
||||
handleClick(index)
|
||||
}, [disabled, handleClick, index])
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type='button'
|
||||
className={cn(
|
||||
'rounded-md px-[5px] py-1',
|
||||
isActive ? 'system-sm-medium text-text-secondary' : 'system-sm-regular text-text-tertiary',
|
||||
!disabled && 'hover:bg-state-base-hover',
|
||||
)}
|
||||
disabled={disabled}
|
||||
onClick={handleClickItem}
|
||||
>
|
||||
{name}
|
||||
</button>
|
||||
{showSeparator && <span className='system-xs-regular text-divider-deep'>/</span>}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
BreadcrumbItem.displayName = 'BreadcrumbItem'
|
||||
|
||||
export default React.memo(BreadcrumbItem)
|
||||
Loading…
Reference in New Issue