Поиск по пользователям переведён на RxJs

This commit is contained in:
Александр Сироткин 2022-02-24 15:41:38 +05:00
parent 6eb6f0f4c2
commit 8ed948a14d

View File

@ -1,10 +1,11 @@
import { Input, Modal, Radio } from 'antd'
import { memo, useCallback, useEffect, useState } from 'react'
import { BehaviorSubject, debounceTime, distinctUntilChanged, filter, map } from 'rxjs'
import { UserView } from '@components/views'
import LoaderPortal from '@components/LoaderPortal'
import { makeColumn, makeNumericSorter, Table } from '@components/Table'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { makeColumn, makeNumericSorter, Table } from '@components/Table'
import { DrillingProgramService } from '@api'
import { arrayOrDefault } from '@utils'
@ -14,31 +15,19 @@ const userRules = [
{ label: 'Согласовант', value: 2 },
]
const SEARCH_TIMEOUT = 1000
const SEARCH_TIMEOUT = 400
export const CategoryEditor = memo(({ idWell, visible, category, onClosed }) => {
const [title, setTitle] = useState()
const [users, setUsers] = useState([])
const [allUsers, setAllUsers] = useState([])
const [filteredUsers, setFilteredUsers] = useState([])
const [searchTimeout, setSearchTimeout] = useState(null)
const [showLoader, setShowLoader] = useState(false)
const [searchValue, setSearchValue] = useState('')
const [subject, setSubject] = useState(null)
useEffect(() => invokeWebApiWrapperAsync(
async () => {
const allUsers = arrayOrDefault(await DrillingProgramService.getAvailableUsers(idWell))
setAllUsers(allUsers)
},
setShowLoader,
`Не удалось загрузить список доступных пользователей скважины "${idWell}"`
), [idWell])
const calcFilteredUsers = useCallback(async (value, users) => await invokeWebApiWrapperAsync(
async () => {
if (searchTimeout)
clearTimeout(searchTimeout)
setSearchTimeout(null)
const filteredUsers = users.filter(({ user }) => user && [
user.login ?? '',
user.name ?? '',
@ -48,12 +37,40 @@ export const CategoryEditor = memo(({ idWell, visible, category, onClosed }) =>
user.phone ?? '',
user.position ?? '',
user.company?.caption ?? '',
].join(' ').toLowerCase().includes(value))
].join(' ').toLowerCase().includes(searchValue))
setFilteredUsers(filteredUsers)
},
setShowLoader,
`Не удалось произвести поиск пользователей`
), [searchTimeout])
), [users, searchValue])
useEffect(() => {
if (!subject) {
const sub = new BehaviorSubject('')
setSubject(sub)
} else {
const observable = subject.pipe(
debounceTime(SEARCH_TIMEOUT),
map(s => s.trim().toLowerCase() ?? ''),
distinctUntilChanged(),
filter(s => s.length <= 0 || s.length >= 2),
).subscribe(value => setSearchValue(value))
return () => {
observable.unsubscribe()
subject.unsubscribe()
}
}
}, [subject])
useEffect(() => invokeWebApiWrapperAsync(
async () => {
const allUsers = arrayOrDefault(await DrillingProgramService.getAvailableUsers(idWell))
setAllUsers(allUsers)
},
setShowLoader,
`Не удалось загрузить список доступных пользователей скважины "${idWell}"`
), [idWell])
const calcUsers = useCallback(() => {
if (!visible) return
@ -68,8 +85,7 @@ export const CategoryEditor = memo(({ idWell, visible, category, onClosed }) =>
...approvers.map((user) => ({ user, status: 2 })),
]
setUsers(users)
calcFilteredUsers(searchValue, users)
}, [category, visible, allUsers, calcFilteredUsers, searchValue])
}, [category, visible, allUsers])
useEffect(calcUsers, [calcUsers])
@ -114,17 +130,9 @@ export const CategoryEditor = memo(({ idWell, visible, category, onClosed }) =>
})
]
const onSearchTextChange = useCallback((value) => {
value = value.trim().toLowerCase() ?? ''
setSearchValue(value)
const onSearchTextChange = useCallback((e) => subject?.next(e?.target?.value), [subject])
if (!searchTimeout) {
clearTimeout(searchTimeout)
setSearchTimeout(setTimeout(() => calcFilteredUsers(value, users), SEARCH_TIMEOUT))
}
}, [searchTimeout, calcFilteredUsers, users])
const onModalCanceled = useCallback(() => {
const onModalClosed = useCallback(() => {
onClosed?.()
calcUsers()
}, [onClosed, calcUsers])
@ -135,16 +143,14 @@ export const CategoryEditor = memo(({ idWell, visible, category, onClosed }) =>
width={1000}
visible={visible}
footer={null}
onCancel={onModalCanceled}
title={`Редактирование категории ${title}`}
onCancel={onModalClosed}
title={`Редактирование пользователей категории ${title}`}
>
<div>
<Input.Search
allowClear
placeholder={'Поиск пользователя'}
onChange={(e) => onSearchTextChange(e?.target?.value)}
onSearch={(text) => calcFilteredUsers(text, users)}
value={searchValue}
onChange={onSearchTextChange}
style={{ marginBottom: '15px' }}
/>
<LoaderPortal show={showLoader}>