chore: catalog: scroll to load more data
This commit is contained in:
@@ -28,7 +28,6 @@ const HighlightCode: React.FC<{
|
||||
|
||||
const currentTheme = React.useMemo(() => {
|
||||
const res = theme || userSettings.theme === 'realDark' ? 'dark' : 'light';
|
||||
console.log('currentTheme:', res, userSettings.theme, '===>', theme);
|
||||
return res;
|
||||
}, [theme, userSettings.theme]);
|
||||
|
||||
|
||||
@@ -75,7 +75,6 @@ export default {
|
||||
borderRadiusSM: 2,
|
||||
colorBgContainer: '#fff',
|
||||
fontSize: 14,
|
||||
motion: true,
|
||||
colorFillTertiary: '#f4f5f4'
|
||||
motion: true
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,6 +14,7 @@ export default function useBodyScroll() {
|
||||
window.__GPUSTACK_BODY_SCROLLER__?.elements()?.scrollEventElement;
|
||||
|
||||
instanceRef.current = window.__GPUSTACK_BODY_SCROLLER__;
|
||||
console.log('bodyScroller', bodyScroller.current, instanceRef.current);
|
||||
};
|
||||
|
||||
const saveScrollHeight = React.useCallback(() => {
|
||||
|
||||
@@ -10,12 +10,18 @@ import { Button, Input, Pagination, Select, Space, message } from 'antd';
|
||||
import { useAtom } from 'jotai';
|
||||
import _ from 'lodash';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { createModel, queryCatalogList } from './apis';
|
||||
import CatalogList from './components/catalog-list';
|
||||
import DelopyBuiltInModal from './components/deploy-builtin-modal';
|
||||
import { modelCategories, modelSourceMap } from './config';
|
||||
import { CatalogItem as CatalogItemType, FormData } from './config/types';
|
||||
|
||||
const PageWrapper = styled.div`
|
||||
display: none;
|
||||
margin-block: 32px 16px;
|
||||
`;
|
||||
|
||||
const Catalog: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const { saveScrollHeight, restoreScrollHeight } = useBodyScroll();
|
||||
@@ -26,14 +32,16 @@ const Catalog: React.FC = () => {
|
||||
dataList: CatalogItemType[];
|
||||
loading: boolean;
|
||||
total: number;
|
||||
totalPage: number;
|
||||
}>({
|
||||
dataList: [],
|
||||
loading: false,
|
||||
total: 0
|
||||
total: 0,
|
||||
totalPage: 0
|
||||
});
|
||||
const [queryParams, setQueryParams] = useState({
|
||||
page: 1,
|
||||
perPage: 100,
|
||||
perPage: 12,
|
||||
search: '',
|
||||
categories: ''
|
||||
});
|
||||
@@ -71,39 +79,62 @@ const Catalog: React.FC = () => {
|
||||
[cacheData.current]
|
||||
);
|
||||
|
||||
const fetchData = useCallback(async () => {
|
||||
setDataSource((pre) => {
|
||||
pre.loading = true;
|
||||
return { ...pre };
|
||||
});
|
||||
try {
|
||||
const params = {
|
||||
..._.pick(queryParams, ['page', 'perPage'])
|
||||
const fetchData = useCallback(
|
||||
async (query?: any) => {
|
||||
const searchQuery = {
|
||||
...queryParams,
|
||||
...query
|
||||
};
|
||||
const res: any = await queryCatalogList(params);
|
||||
if (
|
||||
dataSource.loading ||
|
||||
(searchQuery.page > dataSource.totalPage && dataSource.totalPage > 0)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
setDataSource((pre) => {
|
||||
pre.loading = true;
|
||||
|
||||
cacheData.current = res.items || [];
|
||||
const dataList = filterData({
|
||||
search: queryParams.search,
|
||||
categories: queryParams.categories
|
||||
return { ...pre };
|
||||
});
|
||||
setDataSource({
|
||||
dataList: dataList,
|
||||
loading: false,
|
||||
total: res.pagination.total
|
||||
});
|
||||
} catch (error) {
|
||||
cacheData.current = [];
|
||||
setDataSource({
|
||||
dataList: [],
|
||||
loading: false,
|
||||
total: dataSource.total
|
||||
});
|
||||
console.log('error', error);
|
||||
} finally {
|
||||
setIsFirst(false);
|
||||
}
|
||||
}, [queryParams, cacheData.current]);
|
||||
try {
|
||||
const params = {
|
||||
..._.pickBy(searchQuery, (val: string | number) => !!val)
|
||||
};
|
||||
const res: any = await queryCatalogList(params);
|
||||
|
||||
const dataList =
|
||||
searchQuery.page === 1
|
||||
? res.items
|
||||
: _.concat(dataSource.dataList, res.items);
|
||||
setDataSource({
|
||||
dataList: dataList,
|
||||
loading: false,
|
||||
total: res.pagination.total,
|
||||
totalPage: res.pagination.totalPage
|
||||
});
|
||||
setQueryParams({
|
||||
...queryParams,
|
||||
...query
|
||||
});
|
||||
} catch (error) {
|
||||
cacheData.current = [];
|
||||
setDataSource({
|
||||
dataList: [],
|
||||
loading: false,
|
||||
total: dataSource.total,
|
||||
totalPage: dataSource.totalPage
|
||||
});
|
||||
setQueryParams({
|
||||
...queryParams,
|
||||
...query
|
||||
});
|
||||
console.log('error', error);
|
||||
} finally {
|
||||
setIsFirst(false);
|
||||
}
|
||||
},
|
||||
[queryParams, cacheData.current]
|
||||
);
|
||||
|
||||
const handleDeployModalCancel = () => {
|
||||
setOpenDeployModal({
|
||||
@@ -160,49 +191,57 @@ const Catalog: React.FC = () => {
|
||||
);
|
||||
|
||||
const handleSearch = (e: any) => {
|
||||
fetchData();
|
||||
fetchData({
|
||||
...queryParams,
|
||||
page: 1
|
||||
});
|
||||
};
|
||||
|
||||
const handleNameChange = _.debounce((e: any) => {
|
||||
const dataList = filterData({
|
||||
search: e.target.value,
|
||||
categories: queryParams.categories
|
||||
});
|
||||
|
||||
setQueryParams({
|
||||
fetchData({
|
||||
...queryParams,
|
||||
page: 1,
|
||||
search: e.target.value
|
||||
});
|
||||
|
||||
setDataSource({
|
||||
dataList,
|
||||
loading: false,
|
||||
total: dataSource.total
|
||||
});
|
||||
}, 200);
|
||||
|
||||
const handleCategoryChange = (value: any) => {
|
||||
const dataList = filterData({
|
||||
search: queryParams.search,
|
||||
categories: value
|
||||
});
|
||||
setQueryParams({
|
||||
fetchData({
|
||||
...queryParams,
|
||||
page: 1,
|
||||
categories: value
|
||||
});
|
||||
setDataSource({
|
||||
dataList,
|
||||
loading: false,
|
||||
total: dataSource.total
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = async () => {
|
||||
// Determine the scrolling element
|
||||
const scrollingElement = document.documentElement || document.body;
|
||||
|
||||
// Calculate if the user has scrolled to the bottom
|
||||
const isAtBottom =
|
||||
scrollingElement.scrollTop + scrollingElement.clientHeight >=
|
||||
scrollingElement.scrollHeight - 20; // Adding a small buffer for precision
|
||||
|
||||
if (isAtBottom) {
|
||||
fetchData({
|
||||
...queryParams,
|
||||
page: queryParams.page + 1
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('scroll', handleScroll);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('scroll', handleScroll);
|
||||
};
|
||||
}, [fetchData]);
|
||||
|
||||
return (
|
||||
<PageContainer
|
||||
ghost
|
||||
@@ -259,7 +298,7 @@ const Catalog: React.FC = () => {
|
||||
activeId={-1}
|
||||
isFirst={isFirst}
|
||||
></CatalogList>
|
||||
<div style={{ marginBlock: '32px 16px' }}>
|
||||
<PageWrapper>
|
||||
<Pagination
|
||||
hideOnSinglePage={queryParams.perPage === 100}
|
||||
align="end"
|
||||
@@ -269,7 +308,7 @@ const Catalog: React.FC = () => {
|
||||
showSizeChanger
|
||||
onChange={handleOnPageChange}
|
||||
/>
|
||||
</div>
|
||||
</PageWrapper>
|
||||
<DelopyBuiltInModal
|
||||
open={openDeployModal.show}
|
||||
action={PageAction.CREATE}
|
||||
|
||||
@@ -3,10 +3,23 @@ import { Col, FloatButton, Row, Spin } from 'antd';
|
||||
import _ from 'lodash';
|
||||
import ResizeObserver from 'rc-resize-observer';
|
||||
import React, { useCallback } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { CatalogItem as CatalogItemType } from '../config/types';
|
||||
import CatalogItem from './catalog-item';
|
||||
import CatalogSkelton from './catalog-skelton';
|
||||
|
||||
const SpinWrapper = styled.div`
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 400px;
|
||||
right: 0;
|
||||
`;
|
||||
|
||||
interface CatalogListProps {
|
||||
dataList: any[];
|
||||
loading: boolean;
|
||||
@@ -23,19 +36,7 @@ const ListSkeleton: React.FC<{
|
||||
return (
|
||||
<div>
|
||||
{loading && (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
position: 'absolute',
|
||||
display: 'flex',
|
||||
alignItems: 'flex-start',
|
||||
justifyContent: 'center',
|
||||
top: 0,
|
||||
left: 0,
|
||||
height: 400,
|
||||
right: 0
|
||||
}}
|
||||
>
|
||||
<SpinWrapper>
|
||||
<Spin
|
||||
spinning={loading}
|
||||
style={{
|
||||
@@ -45,7 +46,7 @@ const ListSkeleton: React.FC<{
|
||||
>
|
||||
{isFirst && <CatalogSkelton span={span}></CatalogSkelton>}
|
||||
</Spin>
|
||||
</div>
|
||||
</SpinWrapper>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -91,7 +91,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const handleOnValuesChange = (data: any) => {
|
||||
const handleOnValuesChange = _.debounce((data: any) => {
|
||||
const formdata = form.getFieldsValue?.();
|
||||
|
||||
let alldata = {};
|
||||
@@ -116,7 +116,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
||||
}
|
||||
|
||||
const originalData = _.pick(originFormData.current, Object.keys(alldata));
|
||||
console.log('alldata:', alldata, originalData);
|
||||
console.log('alldata:', formdata, alldata, originalData);
|
||||
|
||||
const isEqual = _.isEqualWith(
|
||||
_.omit(alldata, updateIgnoreFields),
|
||||
@@ -137,7 +137,7 @@ const UpdateModal: React.FC<AddModalProps> = (props) => {
|
||||
})
|
||||
});
|
||||
}
|
||||
};
|
||||
}, 100);
|
||||
|
||||
// voxbox is not support multi gpu
|
||||
const handleSetGPUIds = (backend: string) => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// this list is copied from llamacpp repo
|
||||
enum FileType {
|
||||
F32 = 0,
|
||||
F16 = 1,
|
||||
|
||||
@@ -407,10 +407,13 @@ const GroundEmbedding: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
key: 'json',
|
||||
label: 'JSON',
|
||||
children: (
|
||||
<div style={{ padding: 10, backgroundColor: '#fafafa' }}>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: 'var(--ant-color-bg-container)'
|
||||
}}
|
||||
>
|
||||
<HighlightCode
|
||||
height={outputHeight - 20}
|
||||
theme="light"
|
||||
height={outputHeight - 32}
|
||||
code={embeddingData.code}
|
||||
copyValue={embeddingData.copyValue}
|
||||
lang="json"
|
||||
@@ -671,9 +674,10 @@ const GroundEmbedding: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
style={{
|
||||
border: '1px solid var(--ant-color-border)',
|
||||
borderRadius: 'var(--border-radius-base)',
|
||||
width: '100%'
|
||||
width: '100%',
|
||||
overflow: 'hidden'
|
||||
}}
|
||||
className="scatter "
|
||||
className="scatter"
|
||||
>
|
||||
<Tabs
|
||||
defaultActiveKey={outputType}
|
||||
|
||||
Reference in New Issue
Block a user