Feat list query (#21907)
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { type ReadonlyURLSearchParams, usePathname, useRouter, useSearchParams } from 'next/navigation'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
|
||||
export type DocumentListQuery = {
|
||||
page: number
|
||||
limit: number
|
||||
keyword: string
|
||||
}
|
||||
|
||||
const DEFAULT_QUERY: DocumentListQuery = {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
keyword: '',
|
||||
}
|
||||
|
||||
// Parse the query parameters from the URL search string.
|
||||
function parseParams(params: ReadonlyURLSearchParams): DocumentListQuery {
|
||||
const page = Number.parseInt(params.get('page') || '1', 10)
|
||||
const limit = Number.parseInt(params.get('limit') || '10', 10)
|
||||
const keyword = params.get('keyword') || ''
|
||||
|
||||
return {
|
||||
page: page > 0 ? page : 1,
|
||||
limit: (limit > 0 && limit <= 100) ? limit : 10,
|
||||
keyword: keyword ? decodeURIComponent(keyword) : '',
|
||||
}
|
||||
}
|
||||
|
||||
// Update the URL search string with the given query parameters.
|
||||
function updateSearchParams(query: DocumentListQuery, searchParams: URLSearchParams) {
|
||||
const { page, limit, keyword } = query || {}
|
||||
|
||||
const hasNonDefaultParams = (page && page > 1) || (limit && limit !== 10) || (keyword && keyword.trim())
|
||||
|
||||
if (hasNonDefaultParams) {
|
||||
searchParams.set('page', (page || 1).toString())
|
||||
searchParams.set('limit', (limit || 10).toString())
|
||||
}
|
||||
else {
|
||||
searchParams.delete('page')
|
||||
searchParams.delete('limit')
|
||||
}
|
||||
|
||||
if (keyword && keyword.trim())
|
||||
searchParams.set('keyword', encodeURIComponent(keyword))
|
||||
else
|
||||
searchParams.delete('keyword')
|
||||
}
|
||||
|
||||
function useDocumentListQueryState() {
|
||||
const searchParams = useSearchParams()
|
||||
const query = useMemo(() => parseParams(searchParams), [searchParams])
|
||||
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
|
||||
// Helper function to update specific query parameters
|
||||
const updateQuery = useCallback((updates: Partial<DocumentListQuery>) => {
|
||||
const newQuery = { ...query, ...updates }
|
||||
const params = new URLSearchParams()
|
||||
updateSearchParams(newQuery, params)
|
||||
const search = params.toString()
|
||||
const queryString = search ? `?${search}` : ''
|
||||
router.push(`${pathname}${queryString}`, { scroll: false })
|
||||
}, [query, router, pathname])
|
||||
|
||||
// Helper function to reset query to defaults
|
||||
const resetQuery = useCallback(() => {
|
||||
const params = new URLSearchParams()
|
||||
updateSearchParams(DEFAULT_QUERY, params)
|
||||
const search = params.toString()
|
||||
const queryString = search ? `?${search}` : ''
|
||||
router.push(`${pathname}${queryString}`, { scroll: false })
|
||||
}, [router, pathname])
|
||||
|
||||
return useMemo(() => ({
|
||||
query,
|
||||
updateQuery,
|
||||
resetQuery,
|
||||
}), [query, updateQuery, resetQuery])
|
||||
}
|
||||
|
||||
export default useDocumentListQueryState
|
@@ -26,6 +26,7 @@ import cn from '@/utils/classnames'
|
||||
import { useDocumentList, useInvalidDocumentDetailKey, useInvalidDocumentList } from '@/service/knowledge/use-document'
|
||||
import { useInvalid } from '@/service/use-base'
|
||||
import { useChildSegmentListKey, useSegmentListKey } from '@/service/knowledge/use-segment'
|
||||
import useDocumentListQueryState from './hooks/use-document-list-query-state'
|
||||
import useEditDocumentMetadata from '../metadata/hooks/use-edit-dataset-metadata'
|
||||
import DatasetMetadataDrawer from '../metadata/metadata-dataset/dataset-metadata-drawer'
|
||||
import StatusWithAction from '../common/document-status-with-action/status-with-action'
|
||||
@@ -82,7 +83,6 @@ type IDocumentsProps = {
|
||||
}
|
||||
|
||||
export const fetcher = (url: string) => get(url, {}, {})
|
||||
const DEFAULT_LIMIT = 10
|
||||
|
||||
const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
|
||||
const { t } = useTranslation()
|
||||
@@ -91,8 +91,12 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
|
||||
const isFreePlan = plan.type === 'sandbox'
|
||||
const [inputValue, setInputValue] = useState<string>('') // the input value
|
||||
const [searchValue, setSearchValue] = useState<string>('')
|
||||
const [currPage, setCurrPage] = React.useState<number>(0)
|
||||
const [limit, setLimit] = useState<number>(DEFAULT_LIMIT)
|
||||
|
||||
// Use the new hook for URL state management
|
||||
const { query, updateQuery } = useDocumentListQueryState()
|
||||
const [currPage, setCurrPage] = React.useState<number>(query.page - 1) // Convert to 0-based index
|
||||
const [limit, setLimit] = useState<number>(query.limit)
|
||||
|
||||
const router = useRouter()
|
||||
const { dataset } = useDatasetDetailContext()
|
||||
const [notionPageSelectorModalVisible, setNotionPageSelectorModalVisible] = useState(false)
|
||||
@@ -103,6 +107,45 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
|
||||
const embeddingAvailable = !!dataset?.embedding_available
|
||||
const debouncedSearchValue = useDebounce(searchValue, { wait: 500 })
|
||||
|
||||
// Initialize search value from URL on mount
|
||||
useEffect(() => {
|
||||
if (query.keyword) {
|
||||
setInputValue(query.keyword)
|
||||
setSearchValue(query.keyword)
|
||||
}
|
||||
}, []) // Only run on mount
|
||||
|
||||
// Sync local state with URL query changes
|
||||
useEffect(() => {
|
||||
setCurrPage(query.page - 1)
|
||||
setLimit(query.limit)
|
||||
if (query.keyword !== searchValue) {
|
||||
setInputValue(query.keyword)
|
||||
setSearchValue(query.keyword)
|
||||
}
|
||||
}, [query])
|
||||
|
||||
// Update URL when pagination changes
|
||||
const handlePageChange = (newPage: number) => {
|
||||
setCurrPage(newPage)
|
||||
updateQuery({ page: newPage + 1 }) // Convert to 1-based index
|
||||
}
|
||||
|
||||
// Update URL when limit changes
|
||||
const handleLimitChange = (newLimit: number) => {
|
||||
setLimit(newLimit)
|
||||
setCurrPage(0) // Reset to first page when limit changes
|
||||
updateQuery({ limit: newLimit, page: 1 })
|
||||
}
|
||||
|
||||
// Update URL when search changes
|
||||
useEffect(() => {
|
||||
if (debouncedSearchValue !== query.keyword) {
|
||||
setCurrPage(0) // Reset to first page when search changes
|
||||
updateQuery({ keyword: debouncedSearchValue, page: 1 })
|
||||
}
|
||||
}, [debouncedSearchValue, query.keyword, updateQuery])
|
||||
|
||||
const { data: documentsRes, isFetching: isListLoading } = useDocumentList({
|
||||
datasetId,
|
||||
query: {
|
||||
@@ -327,9 +370,9 @@ const Documents: FC<IDocumentsProps> = ({ datasetId }) => {
|
||||
pagination={{
|
||||
total,
|
||||
limit,
|
||||
onLimitChange: setLimit,
|
||||
onLimitChange: handleLimitChange,
|
||||
current: currPage,
|
||||
onChange: setCurrPage,
|
||||
onChange: handlePageChange,
|
||||
}}
|
||||
onManageMetadata={showEditMetadataModal}
|
||||
/>
|
||||
|
@@ -598,7 +598,6 @@ const DocumentList: FC<IDocumentListProps> = ({
|
||||
)
|
||||
}}
|
||||
/>
|
||||
{/* {doc.position} */}
|
||||
{index + 1}
|
||||
</div>
|
||||
</td>
|
||||
|
Reference in New Issue
Block a user