[IMPROVE] Paginated multiselect for EE tags (#22315)
* [IMPROVE] Paginated multiselect for EE tags * add missing tag interface * rename ILivechatTag interface * Add type to endpoint Co-authored-by: Rafael Ferreira <rafaelblink@gmail.com>pull/22466/head
parent
68e83b8662
commit
2aa1cfb60a
@ -0,0 +1,13 @@ |
||||
import { ILivechatTag } from '../../../../../../definition/ILivechatTag'; |
||||
import { ObjectFromApi } from '../../../../../../definition/ObjectFromApi'; |
||||
|
||||
export type LivechatTagsList = { |
||||
GET: (params: { |
||||
text: string; |
||||
offset: number; |
||||
count: number; |
||||
}) => { |
||||
tags: ObjectFromApi<ILivechatTag>[]; |
||||
total: number; |
||||
}; |
||||
}; |
@ -0,0 +1,7 @@ |
||||
export interface ILivechatTag { |
||||
_id: string; |
||||
name: string; |
||||
description: string; |
||||
numDepartments: number; |
||||
departments: Array<string>; |
||||
} |
@ -0,0 +1,10 @@ |
||||
import { IRocketChatRecord } from './IRocketChatRecord'; |
||||
|
||||
|
||||
export interface ILivechatTagRecord extends IRocketChatRecord { |
||||
_id: string; |
||||
name: string; |
||||
description: string; |
||||
numDepartments: number; |
||||
departments: Array<string>; |
||||
} |
@ -0,0 +1,58 @@ |
||||
import { useCallback, useState } from 'react'; |
||||
|
||||
import { useEndpoint } from '../../../client/contexts/ServerContext'; |
||||
import { useScrollableRecordList } from '../../../client/hooks/lists/useScrollableRecordList'; |
||||
import { useComponentDidUpdate } from '../../../client/hooks/useComponentDidUpdate'; |
||||
import { RecordList } from '../../../client/lib/lists/RecordList'; |
||||
import { ILivechatTagRecord } from '../../../definition/ILivechatTagRecord'; |
||||
|
||||
type TagsListOptions = { |
||||
filter: string; |
||||
}; |
||||
|
||||
export const useTagsList = ( |
||||
options: TagsListOptions, |
||||
): { |
||||
itemsList: RecordList<ILivechatTagRecord>; |
||||
initialItemCount: number; |
||||
reload: () => void; |
||||
loadMoreItems: (start: number, end: number) => void; |
||||
} => { |
||||
const [itemsList, setItemsList] = useState(() => new RecordList<ILivechatTagRecord>()); |
||||
const reload = useCallback(() => setItemsList(new RecordList<ILivechatTagRecord>()), []); |
||||
|
||||
const getTags = useEndpoint('GET', 'livechat/tags.list'); |
||||
|
||||
useComponentDidUpdate(() => { |
||||
options && reload(); |
||||
}, [options, reload]); |
||||
|
||||
const fetchData = useCallback( |
||||
async (start, end) => { |
||||
const { tags, total } = await getTags({ |
||||
text: options.filter, |
||||
offset: start, |
||||
count: end + start, |
||||
}); |
||||
return { |
||||
items: tags.map((tag: any) => { |
||||
tag._updatedAt = new Date(tag._updatedAt); |
||||
tag.label = tag.name; |
||||
tag.value = { value: tag._id, label: tag.name }; |
||||
return tag; |
||||
}), |
||||
itemCount: total, |
||||
}; |
||||
}, |
||||
[getTags, options.filter], |
||||
); |
||||
|
||||
const { loadMoreItems, initialItemCount } = useScrollableRecordList(itemsList, fetchData, 25); |
||||
|
||||
return { |
||||
reload, |
||||
itemsList, |
||||
loadMoreItems, |
||||
initialItemCount, |
||||
}; |
||||
}; |
@ -1,16 +1,35 @@ |
||||
import { MultiSelect } from '@rocket.chat/fuselage'; |
||||
import React, { useMemo } from 'react'; |
||||
import { PaginatedMultiSelectFiltered } from '@rocket.chat/fuselage'; |
||||
import React, { useMemo, useState } from 'react'; |
||||
|
||||
import { useEndpointData } from '../../../../client/hooks/useEndpointData'; |
||||
import { useRecordList } from '../../../../client/hooks/lists/useRecordList'; |
||||
import { AsyncStatePhase } from '../../../../client/hooks/useAsyncState'; |
||||
import { useTagsList } from '../../hooks/useTagsList'; |
||||
|
||||
const CurrentChatTags = ({ value, handler, ...props }) => { |
||||
const { value: data } = useEndpointData('livechat/tags.list'); |
||||
const options = useMemo( |
||||
() => (data && data.tags ? data.tags.map(({ name }) => [name, name]) : []), |
||||
[data], |
||||
const CurrentChatTags = ({ value, handler }) => { |
||||
const [tagsFilter, setTagsFilter] = useState(''); |
||||
|
||||
const { itemsList: tagsList, loadMoreItems: loadMoreTags } = useTagsList( |
||||
useMemo(() => ({ filter: tagsFilter }), [tagsFilter]), |
||||
); |
||||
|
||||
return <MultiSelect options={options} value={value} onChange={handler} flexGrow={1} {...props} />; |
||||
const { phase: tagsPhase, items: tagsItems, itemCount: tagsTotal } = useRecordList(tagsList); |
||||
|
||||
return ( |
||||
<PaginatedMultiSelectFiltered |
||||
maxWidth={'100%'} |
||||
flexGrow={1} |
||||
filter={tagsFilter} |
||||
setFilter={setTagsFilter} |
||||
onChange={handler} |
||||
options={tagsItems} |
||||
value={value} |
||||
endReached={ |
||||
tagsPhase === AsyncStatePhase.LOADING |
||||
? () => {} |
||||
: (start) => loadMoreTags(start, Math.min(50, tagsTotal)) |
||||
} |
||||
/> |
||||
); |
||||
}; |
||||
|
||||
export default CurrentChatTags; |
||||
|
Loading…
Reference in new issue