Add pagination to Hub (#844)

This commit is contained in:
Piotr Rogowski 2022-10-25 22:26:52 +02:00 committed by GitHub
parent 72fa95ea20
commit b978b051d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 36 additions and 17 deletions

View File

@ -71,23 +71,24 @@ const useDb = () => {
} }
}; };
const searchTunes = async (search?: string) => { const searchTunes = async (search: string, page: number, perPage: number) => {
// TODO: add pagination const phrases = search.length > 0 ? search.replace(/ +(?= )/g,'').split(' ') : [];
const batchSide = 100;
const phrases = search ? search.replace(/ +(?= )/g,'').split(' ') : [];
const filter = phrases const filter = phrases
.filter((phrase) => phrase.length > 1) .filter((phrase) => phrase.length > 1)
.map((phrase) => `textSearch ~ "${phrase}"`) .map((phrase) => `textSearch ~ "${phrase}"`)
.join(' || '); .join(' || ');
try { try {
const list = await client.records.getFullList(Collections.Tunes, batchSide, { const list = await client.records.getList(Collections.Tunes, page, perPage, {
sort: '-created', sort: '-created',
filter, filter,
expand: 'userProfile', expand: 'userProfile',
}); });
return Promise.resolve(list as TunesRecordFull[]); return Promise.resolve({
items: list.items as TunesRecordFull[],
totalItems: list.totalItems,
});
} catch (error) { } catch (error) {
Sentry.captureException(error); Sentry.captureException(error);
databaseGenericError(new Error(formatError(error))); databaseGenericError(new Error(formatError(error)));
@ -101,7 +102,7 @@ const useDb = () => {
createTune: (data: TunesRecord): Promise<TunesRecordFull> => createTune(data), createTune: (data: TunesRecord): Promise<TunesRecordFull> => createTune(data),
getTune: (tuneId: string): Promise<TunesRecordFull | null> => getTune(tuneId), getTune: (tuneId: string): Promise<TunesRecordFull | null> => getTune(tuneId),
getIni: (tuneId: string): Promise<IniFilesRecordFull | null> => getIni(tuneId), getIni: (tuneId: string): Promise<IniFilesRecordFull | null> => getIni(tuneId),
searchTunes: (search?: string): Promise<TunesRecordFull[]> => searchTunes(search), searchTunes: (search: string, page: number, perPage: number): Promise<{ items: TunesRecordFull[]; totalItems: number }> => searchTunes(search, page, perPage),
}; };
}; };

View File

@ -3,6 +3,7 @@ import {
Grid, Grid,
Input, Input,
InputRef, InputRef,
Pagination,
Space, Space,
Table, Table,
Typography, Typography,
@ -49,14 +50,16 @@ const Hub = () => {
const [dataSource, setDataSource] = useState<{}[]>([]); // TODO: fix this type const [dataSource, setDataSource] = useState<{}[]>([]); // TODO: fix this type
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const [searchQuery, setSearchQuery] = useState(''); const [searchQuery, setSearchQuery] = useState('');
const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(5);
const [total, setTotal] = useState(0);
const searchRef = useRef<InputRef | null>(null); const searchRef = useRef<InputRef | null>(null);
const loadData = debounce(async (searchText?: string) => { const loadData = debounce(async (searchText: string) => {
setIsLoading(true); setIsLoading(true);
const list = await searchTunes(searchText); const { items, totalItems } = await searchTunes(searchText, page, pageSize);
setTotal(totalItems);
// set initial list const mapped = items.map((tune) => ({
setDataSource(list.map((tune) => ({
...tune, ...tune,
key: tune.tuneId, key: tune.tuneId,
year: tune.year, year: tune.year,
@ -65,32 +68,34 @@ const Hub = () => {
aspiration: aspirationMapper[tune.aspiration], aspiration: aspirationMapper[tune.aspiration],
published: formatTime(tune.updated), published: formatTime(tune.updated),
stars: 0, stars: 0,
}))); }));
setDataSource(mapped);
setIsLoading(false); setIsLoading(false);
}, 300); }, 300);
const debounceLoadData = useCallback((value: string) => { const debounceLoadData = useCallback((value: string) => {
setSearchQuery(value); setSearchQuery(value);
loadData(value); loadData(value);
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
const handleGlobalKeyboard = useCallback((e: KeyboardEvent) => { const handleGlobalKeyboard = useCallback((e: KeyboardEvent) => {
if (isEscape(e)) { if (isEscape(e)) {
setSearchQuery(''); setSearchQuery('');
loadData(); loadData('');
} }
}, [loadData]); }, [loadData]);
useEffect(() => { useEffect(() => {
loadData(); loadData('');
window.addEventListener('keydown', handleGlobalKeyboard); window.addEventListener('keydown', handleGlobalKeyboard);
// searchRef.current?.focus(); // autofocus // searchRef.current?.focus(); // autofocus
return () => window.removeEventListener('keydown', handleGlobalKeyboard); return () => window.removeEventListener('keydown', handleGlobalKeyboard);
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, [page]);
const columns: ColumnsType<any> = [ const columns: ColumnsType<any> = [
{ {
@ -200,6 +205,19 @@ const Hub = () => {
scroll={xs ? undefined : { x: 1360 }} scroll={xs ? undefined : { x: 1360 }}
pagination={false} pagination={false}
/> />
<div style={{ textAlign: 'right' }}>
<Pagination
style={{ marginTop: 10 }}
pageSize={pageSize}
current={page}
total={total}
onChange={(newPage, newPageSize) => {
setIsLoading(true);
setPage(newPage);
setPageSize(newPageSize);
}}
/>
</div>
</div> </div>
); );
}; };