Преглед изворни кода

sort on display status (#24252)

Co-authored-by: crazywoola <427733928@qq.com>
tags/1.8.0
znn пре 2 месеци
родитељ
комит
243876e9b7
No account linked to committer's email address

+ 42
- 8
web/app/components/datasets/documents/index.tsx Прегледај датотеку

import { useProviderContext } from '@/context/provider-context' import { useProviderContext } from '@/context/provider-context'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { useDocumentList, useInvalidDocumentDetailKey, useInvalidDocumentList } from '@/service/knowledge/use-document' import { useDocumentList, useInvalidDocumentDetailKey, useInvalidDocumentList } from '@/service/knowledge/use-document'
import { useIndexStatus } from './list'
import { useInvalid } from '@/service/use-base' import { useInvalid } from '@/service/use-base'
import { useChildSegmentListKey, useSegmentListKey } from '@/service/knowledge/use-segment' import { useChildSegmentListKey, useSegmentListKey } from '@/service/knowledge/use-segment'
import useDocumentListQueryState from './hooks/use-document-list-query-state' import useDocumentListQueryState from './hooks/use-document-list-query-state'
import StatusWithAction from '../common/document-status-with-action/status-with-action' import StatusWithAction from '../common/document-status-with-action/status-with-action'
import { useDocLink } from '@/context/i18n' import { useDocLink } from '@/context/i18n'
import { useFetchDefaultProcessRule } from '@/service/knowledge/use-create-dataset' import { useFetchDefaultProcessRule } from '@/service/knowledge/use-create-dataset'
import { SimpleSelect } from '../../base/select'
import StatusItem from './detail/completed/status-item'
import type { Item } from '@/app/components/base/select'


const FolderPlusIcon = ({ className }: React.SVGProps<SVGElement>) => { const FolderPlusIcon = ({ className }: React.SVGProps<SVGElement>) => {
return <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}> return <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
const isFreePlan = plan.type === 'sandbox' const isFreePlan = plan.type === 'sandbox'
const [inputValue, setInputValue] = useState<string>('') // the input value const [inputValue, setInputValue] = useState<string>('') // the input value
const [searchValue, setSearchValue] = useState<string>('') const [searchValue, setSearchValue] = useState<string>('')
const [statusFilter, setStatusFilter] = useState<Item>({ value: 'all', name: 'All Status' })
const DOC_INDEX_STATUS_MAP = useIndexStatus()


// Use the new hook for URL state management // Use the new hook for URL state management
const { query, updateQuery } = useDocumentListQueryState() const { query, updateQuery } = useDocumentListQueryState()
const embeddingAvailable = !!dataset?.embedding_available const embeddingAvailable = !!dataset?.embedding_available
const debouncedSearchValue = useDebounce(searchValue, { wait: 500 }) const debouncedSearchValue = useDebounce(searchValue, { wait: 500 })


const statusFilterItems: Item[] = useMemo(() => [
{ value: 'all', name: 'All Status' },
{ value: 'queuing', name: DOC_INDEX_STATUS_MAP.queuing.text },
{ value: 'indexing', name: DOC_INDEX_STATUS_MAP.indexing.text },
{ value: 'paused', name: DOC_INDEX_STATUS_MAP.paused.text },
{ value: 'error', name: DOC_INDEX_STATUS_MAP.error.text },
{ value: 'available', name: DOC_INDEX_STATUS_MAP.available.text },
{ value: 'enabled', name: DOC_INDEX_STATUS_MAP.enabled.text },
{ value: 'disabled', name: DOC_INDEX_STATUS_MAP.disabled.text },
{ value: 'archived', name: DOC_INDEX_STATUS_MAP.archived.text },
], [DOC_INDEX_STATUS_MAP, t])

// Initialize search value from URL on mount // Initialize search value from URL on mount
useEffect(() => { useEffect(() => {
if (query.keyword) { if (query.keyword) {
</div> </div>
<div className='flex flex-1 flex-col px-6 py-4'> <div className='flex flex-1 flex-col px-6 py-4'>
<div className='flex flex-wrap items-center justify-between'> <div className='flex flex-wrap items-center justify-between'>
<Input
showLeftIcon
showClearIcon
wrapperClassName='!w-[200px]'
value={inputValue}
onChange={e => handleInputChange(e.target.value)}
onClear={() => handleInputChange('')}
/>
<div className='flex items-center gap-2'>
<SimpleSelect
placeholder={t('datasetDocuments.list.table.header.status')}
onSelect={(item) => {
setStatusFilter(item)
}}
items={statusFilterItems}
defaultValue={statusFilter.value}
wrapperClassName='w-[160px] h-8'
renderOption={({ item, selected }) => <StatusItem item={item} selected={selected} />}
optionClassName='p-0'
notClearable
/>
<Input
showLeftIcon
showClearIcon
wrapperClassName='!w-[200px]'
value={inputValue}
onChange={e => handleInputChange(e.target.value)}
onClear={() => handleInputChange('')}
/>
</div>
<div className='flex !h-8 items-center justify-center gap-2'> <div className='flex !h-8 items-center justify-center gap-2'>
{!isFreePlan && <AutoDisabledDocument datasetId={datasetId} />} {!isFreePlan && <AutoDisabledDocument datasetId={datasetId} />}
<IndexFailed datasetId={datasetId} /> <IndexFailed datasetId={datasetId} />
onUpdate={handleUpdate} onUpdate={handleUpdate}
selectedIds={selectedIds} selectedIds={selectedIds}
onSelectedIdChange={setSelectedIds} onSelectedIdChange={setSelectedIds}
statusFilter={statusFilter}
onStatusFilterChange={setStatusFilter}
pagination={{ pagination={{
total, total,
limit, limit,

+ 18
- 3
web/app/components/datasets/documents/list.tsx Прегледај датотеку

import Confirm from '@/app/components/base/confirm' import Confirm from '@/app/components/base/confirm'
import Tooltip from '@/app/components/base/tooltip' import Tooltip from '@/app/components/base/tooltip'
import Toast, { ToastContext } from '@/app/components/base/toast' import Toast, { ToastContext } from '@/app/components/base/toast'
import type { Item } from '@/app/components/base/select'
import type { ColorMap, IndicatorProps } from '@/app/components/header/indicator' import type { ColorMap, IndicatorProps } from '@/app/components/header/indicator'
import Indicator from '@/app/components/header/indicator' import Indicator from '@/app/components/header/indicator'
import { asyncRunSafe } from '@/utils' import { asyncRunSafe } from '@/utils'
pagination: PaginationProps pagination: PaginationProps
onUpdate: () => void onUpdate: () => void
onManageMetadata: () => void onManageMetadata: () => void
statusFilter: Item
onStatusFilterChange: (filter: string) => void
} }


/** /**
pagination, pagination,
onUpdate, onUpdate,
onManageMetadata, onManageMetadata,
statusFilter,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const { formatTime } = useTimestamp() const { formatTime } = useTimestamp()
const [localDocs, setLocalDocs] = useState<LocalDoc[]>(documents) const [localDocs, setLocalDocs] = useState<LocalDoc[]>(documents)
const [sortField, setSortField] = useState<'name' | 'word_count' | 'hit_count' | 'created_at' | null>('created_at') const [sortField, setSortField] = useState<'name' | 'word_count' | 'hit_count' | 'created_at' | null>('created_at')
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc') const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc')

const { const {
isShowEditModal, isShowEditModal,
showEditModal, showEditModal,
}) })


useEffect(() => { useEffect(() => {
let filteredDocs = documents

if (statusFilter.value !== 'all') {
filteredDocs = filteredDocs.filter(doc =>
typeof doc.display_status === 'string'
&& typeof statusFilter.value === 'string'
&& doc.display_status.toLowerCase() === statusFilter.value.toLowerCase(),
)
}

if (!sortField) { if (!sortField) {
setLocalDocs(documents)
setLocalDocs(filteredDocs)
return return
} }


const sortedDocs = [...documents].sort((a, b) => {
const sortedDocs = [...filteredDocs].sort((a, b) => {
let aValue: any let aValue: any
let bValue: any let bValue: any


}) })


setLocalDocs(sortedDocs) setLocalDocs(sortedDocs)
}, [documents, sortField, sortOrder])
}, [documents, sortField, sortOrder, statusFilter])


const handleSort = (field: 'name' | 'word_count' | 'hit_count' | 'created_at') => { const handleSort = (field: 'name' | 'word_count' | 'hit_count' | 'created_at') => {
if (sortField === field) { if (sortField === field) {

Loading…
Откажи
Сачувај