feat: table list sorter
This commit is contained in:
@@ -1,15 +1,16 @@
|
|||||||
import { Col, Row } from 'antd';
|
import { Col, Row } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SealColumnProps } from '../types';
|
import { OnSortFn, SealColumnProps } from '../types';
|
||||||
import TableHeader from './table-header';
|
import TableHeader from './table-header';
|
||||||
|
|
||||||
interface HeaderProps {
|
interface HeaderProps {
|
||||||
columns: SealColumnProps[];
|
columns: SealColumnProps[];
|
||||||
onSort?: (dataIndex: string, order: any) => void;
|
sortDirections?: ('ascend' | 'descend' | null)[];
|
||||||
|
onSort?: OnSortFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Header: React.FC<HeaderProps> = (props) => {
|
const Header: React.FC<HeaderProps> = (props) => {
|
||||||
const { onSort } = props;
|
const { onSort, sortDirections } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row className="row">
|
<Row className="row">
|
||||||
@@ -32,6 +33,7 @@ const Header: React.FC<HeaderProps> = (props) => {
|
|||||||
sorter={sorter}
|
sorter={sorter}
|
||||||
dataIndex={dataIndex}
|
dataIndex={dataIndex}
|
||||||
sortOrder={sortOrder}
|
sortOrder={sortOrder}
|
||||||
|
sortDirections={sortDirections}
|
||||||
width={width}
|
width={width}
|
||||||
defaultSortOrder={defaultSortOrder}
|
defaultSortOrder={defaultSortOrder}
|
||||||
title={title}
|
title={title}
|
||||||
|
|||||||
@@ -14,19 +14,39 @@ const TableHeader: React.FC<TableHeaderProps> = (props) => {
|
|||||||
firstCell,
|
firstCell,
|
||||||
lastCell,
|
lastCell,
|
||||||
sortOrder,
|
sortOrder,
|
||||||
|
sortDirections = ['ascend', 'descend', null],
|
||||||
|
defaultSortOrder,
|
||||||
onSort,
|
onSort,
|
||||||
sorter,
|
sorter = false,
|
||||||
width,
|
width,
|
||||||
dataIndex
|
dataIndex
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const handleOnSort = () => {
|
const [currentSortOrder, setCurrentSortOrder] = React.useState<
|
||||||
if (sortOrder === 'ascend') {
|
'ascend' | 'descend' | null
|
||||||
onSort?.(dataIndex, 'descend');
|
>(sortOrder || defaultSortOrder || null);
|
||||||
} else {
|
|
||||||
onSort?.(dataIndex, 'ascend');
|
const getNextSortOrder = (currentOrder: 'ascend' | 'descend' | null) => {
|
||||||
}
|
const index = sortDirections.indexOf(currentOrder);
|
||||||
|
const nextIndex = (index + 1) % sortDirections.length;
|
||||||
|
return sortDirections[nextIndex];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleOnSort = () => {
|
||||||
|
setCurrentSortOrder((prev) => {
|
||||||
|
const next = getNextSortOrder(prev);
|
||||||
|
onSort?.(
|
||||||
|
{
|
||||||
|
columnKey: dataIndex,
|
||||||
|
field: dataIndex,
|
||||||
|
order: next
|
||||||
|
},
|
||||||
|
sorter
|
||||||
|
);
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{ width, ...style }}
|
style={{ width, ...style }}
|
||||||
@@ -47,12 +67,12 @@ const TableHeader: React.FC<TableHeaderProps> = (props) => {
|
|||||||
<span className="sorter">
|
<span className="sorter">
|
||||||
<CaretUpOutlined
|
<CaretUpOutlined
|
||||||
className={classNames('sorter-up', {
|
className={classNames('sorter-up', {
|
||||||
'sorter-active': sortOrder === 'ascend'
|
'sorter-active': currentSortOrder === 'ascend'
|
||||||
})}
|
})}
|
||||||
></CaretUpOutlined>
|
></CaretUpOutlined>
|
||||||
<CaretDownOutlined
|
<CaretDownOutlined
|
||||||
className={classNames('sorter-down', {
|
className={classNames('sorter-down', {
|
||||||
'sorter-active': sortOrder === 'descend'
|
'sorter-active': currentSortOrder === 'descend'
|
||||||
})}
|
})}
|
||||||
></CaretDownOutlined>
|
></CaretDownOutlined>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import HeaderPrefix from './components/header-prefix';
|
|||||||
import TableBody from './components/table-body';
|
import TableBody from './components/table-body';
|
||||||
import './styles/index.less';
|
import './styles/index.less';
|
||||||
import { SealColumnProps, SealTableProps } from './types';
|
import { SealColumnProps, SealTableProps } from './types';
|
||||||
|
import useSorter from './use-sorter';
|
||||||
|
|
||||||
const Wrapper = styled.div<{ $token: any }>`
|
const Wrapper = styled.div<{ $token: any }>`
|
||||||
--ant-table-cell-padding-inline: ${(props) =>
|
--ant-table-cell-padding-inline: ${(props) =>
|
||||||
@@ -32,7 +33,7 @@ const SealTable: React.FC<SealTableProps & { pagination: PaginationProps }> = (
|
|||||||
childParentKey,
|
childParentKey,
|
||||||
onExpand,
|
onExpand,
|
||||||
onExpandAll,
|
onExpandAll,
|
||||||
onSort,
|
onTableSort,
|
||||||
onCell,
|
onCell,
|
||||||
expandedRowKeys,
|
expandedRowKeys,
|
||||||
loading,
|
loading,
|
||||||
@@ -43,10 +44,15 @@ const SealTable: React.FC<SealTableProps & { pagination: PaginationProps }> = (
|
|||||||
rowSelection,
|
rowSelection,
|
||||||
pagination,
|
pagination,
|
||||||
empty,
|
empty,
|
||||||
|
sortDirections,
|
||||||
renderChildren,
|
renderChildren,
|
||||||
loadChildren,
|
loadChildren,
|
||||||
loadChildrenAPI
|
loadChildrenAPI
|
||||||
} = props;
|
} = props;
|
||||||
|
const { handleOnTableSort } = useSorter({
|
||||||
|
onTableSort,
|
||||||
|
columns
|
||||||
|
});
|
||||||
const { token } = theme.useToken();
|
const { token } = theme.useToken();
|
||||||
const parsedColumns = useMemo(() => {
|
const parsedColumns = useMemo(() => {
|
||||||
if (columns) return columns;
|
if (columns) return columns;
|
||||||
@@ -156,7 +162,11 @@ const SealTable: React.FC<SealTableProps & { pagination: PaginationProps }> = (
|
|||||||
disabled={!props.dataSource?.length}
|
disabled={!props.dataSource?.length}
|
||||||
hasColumns={parsedColumns.length > 0}
|
hasColumns={parsedColumns.length > 0}
|
||||||
></HeaderPrefix>
|
></HeaderPrefix>
|
||||||
<Header onSort={onSort} columns={parsedColumns}></Header>
|
<Header
|
||||||
|
onSort={handleOnTableSort}
|
||||||
|
columns={parsedColumns}
|
||||||
|
sortDirections={sortDirections}
|
||||||
|
></Header>
|
||||||
</div>
|
</div>
|
||||||
<Spin spinning={loading}>
|
<Spin spinning={loading}>
|
||||||
<TableBody
|
<TableBody
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
export type OnSortFn = (
|
||||||
|
order: {
|
||||||
|
columnKey: string;
|
||||||
|
field: string;
|
||||||
|
order: 'ascend' | 'descend' | null;
|
||||||
|
},
|
||||||
|
sorter: boolean | { multiple?: number }
|
||||||
|
) => void;
|
||||||
|
|
||||||
export interface CellContentProps {
|
export interface CellContentProps {
|
||||||
dataIndex: string;
|
dataIndex: string;
|
||||||
render?: (text: any, record: any) => React.ReactNode;
|
render?: (text: any, record: any) => React.ReactNode;
|
||||||
@@ -20,7 +29,7 @@ export interface SealColumnProps {
|
|||||||
span: number;
|
span: number;
|
||||||
align?: 'left' | 'center' | 'right';
|
align?: 'left' | 'center' | 'right';
|
||||||
headerStyle?: React.CSSProperties;
|
headerStyle?: React.CSSProperties;
|
||||||
sorter?: boolean;
|
sorter?: boolean | { multiple?: number };
|
||||||
defaultSortOrder?: 'ascend' | 'descend';
|
defaultSortOrder?: 'ascend' | 'descend';
|
||||||
editable?:
|
editable?:
|
||||||
| boolean
|
| boolean
|
||||||
@@ -34,17 +43,23 @@ export interface SealColumnProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface TableHeaderProps {
|
export interface TableHeaderProps {
|
||||||
sorter?: boolean;
|
sorter?: boolean | { multiple?: number };
|
||||||
defaultSortOrder?: 'ascend' | 'descend';
|
sortDirections?: ('ascend' | 'descend' | null)[];
|
||||||
|
defaultSortOrder?: 'ascend' | 'descend' | null;
|
||||||
sortOrder?: 'ascend' | 'descend' | null;
|
sortOrder?: 'ascend' | 'descend' | null;
|
||||||
dataIndex: string;
|
dataIndex: string;
|
||||||
onSort?: (dataIndex: string, order: 'ascend' | 'descend') => void;
|
onSort?: OnSortFn;
|
||||||
title: React.ReactNode;
|
title: React.ReactNode;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
firstCell?: boolean;
|
firstCell?: boolean;
|
||||||
lastCell?: boolean;
|
lastCell?: boolean;
|
||||||
align?: 'left' | 'center' | 'right';
|
align?: 'left' | 'center' | 'right';
|
||||||
width?: number | string;
|
width?: number | string;
|
||||||
|
sortedDataIndexList?: Array<{
|
||||||
|
columnKey: string;
|
||||||
|
field: string;
|
||||||
|
order: 'ascend' | 'descend' | null;
|
||||||
|
}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RowSelectionProps {
|
export interface RowSelectionProps {
|
||||||
@@ -54,7 +69,14 @@ export interface RowSelectionProps {
|
|||||||
removeSelectedKeys: (rowKeys: React.Key[]) => void;
|
removeSelectedKeys: (rowKeys: React.Key[]) => void;
|
||||||
onChange: (selectedRowKeys: React.Key[], selectedRows: any[]) => void;
|
onChange: (selectedRowKeys: React.Key[], selectedRows: any[]) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type TableOrder = {
|
||||||
|
columnKey?: string;
|
||||||
|
field?: string;
|
||||||
|
order: 'ascend' | 'descend' | null;
|
||||||
|
};
|
||||||
export interface SealTableProps {
|
export interface SealTableProps {
|
||||||
|
sortDirections?: ('ascend' | 'descend' | null)[];
|
||||||
columns?: SealColumnProps[];
|
columns?: SealColumnProps[];
|
||||||
childParentKey?: string;
|
childParentKey?: string;
|
||||||
expandedRowKeys?: React.Key[];
|
expandedRowKeys?: React.Key[];
|
||||||
@@ -68,7 +90,7 @@ export interface SealTableProps {
|
|||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
loadend?: boolean;
|
loadend?: boolean;
|
||||||
onCell?: (record: any, dataIndex: string) => void;
|
onCell?: (record: any, dataIndex: string) => void;
|
||||||
onSort?: (dataIndex: string, order: 'ascend' | 'descend') => void;
|
onTableSort?: (order: TableOrder | Array<TableOrder>) => void;
|
||||||
onExpand?: (expanded: boolean, record: any, rowKey: any) => void;
|
onExpand?: (expanded: boolean, record: any, rowKey: any) => void;
|
||||||
onExpandAll?: (expanded: boolean) => void;
|
onExpandAll?: (expanded: boolean) => void;
|
||||||
renderChildren?: (
|
renderChildren?: (
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
import { isBoolean } from 'lodash';
|
||||||
|
import { useRef } from 'react';
|
||||||
|
import { SealColumnProps, TableOrder } from './types';
|
||||||
|
|
||||||
|
const initSorterList = (columns: SealColumnProps[]) => {
|
||||||
|
const list = columns.filter((col) => col.defaultSortOrder);
|
||||||
|
if (list.length === 0) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return list.map((col) => ({
|
||||||
|
columnKey: col.key || col.dataIndex,
|
||||||
|
field: col.dataIndex,
|
||||||
|
order: col.defaultSortOrder || null
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function useSorter(options: {
|
||||||
|
onTableSort?: (TableOrder: TableOrder | Array<TableOrder>) => void;
|
||||||
|
columns?: SealColumnProps[];
|
||||||
|
}) {
|
||||||
|
const { onTableSort, columns } = options;
|
||||||
|
const sorterListRef = useRef<TableOrder | Array<TableOrder>>(
|
||||||
|
initSorterList(columns || [])
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleOnTableSort = (
|
||||||
|
order: TableOrder,
|
||||||
|
sorter: boolean | { multiple?: number }
|
||||||
|
) => {
|
||||||
|
let currentOrder: TableOrder = { ...order };
|
||||||
|
|
||||||
|
if (order.order === null) {
|
||||||
|
currentOrder = {
|
||||||
|
columnKey: undefined,
|
||||||
|
field: undefined,
|
||||||
|
order: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// single column sort
|
||||||
|
if (isBoolean(sorter)) {
|
||||||
|
sorterListRef.current = currentOrder;
|
||||||
|
|
||||||
|
onTableSort?.(sorterListRef.current);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// multi column sort
|
||||||
|
if (sorter && typeof sorter === 'object' && sorter.multiple) {
|
||||||
|
if (!Array.isArray(sorterListRef.current)) {
|
||||||
|
if (
|
||||||
|
sorterListRef.current.columnKey === currentOrder.columnKey ||
|
||||||
|
sorterListRef.current.field === currentOrder.field
|
||||||
|
) {
|
||||||
|
// remove the sorter if order is null
|
||||||
|
sorterListRef.current = {
|
||||||
|
...currentOrder
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
sorterListRef.current = [sorterListRef.current, { ...currentOrder }];
|
||||||
|
}
|
||||||
|
} else if (Array.isArray(sorterListRef.current)) {
|
||||||
|
const existingIndex = sorterListRef.current.findIndex(
|
||||||
|
(item) =>
|
||||||
|
item.columnKey === order.columnKey || item.field === order.field
|
||||||
|
);
|
||||||
|
|
||||||
|
if (existingIndex !== -1) {
|
||||||
|
sorterListRef.current.splice(existingIndex, 1);
|
||||||
|
sorterListRef.current.push({ ...currentOrder });
|
||||||
|
} else {
|
||||||
|
sorterListRef.current.push({ ...currentOrder });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onTableSort?.(sorterListRef.current);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
sorterListRef,
|
||||||
|
handleOnTableSort
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -9,3 +9,10 @@ export const DEFAULT_ENTER_PAGE = {
|
|||||||
|
|
||||||
export const GPUSTACK_API_BASE_URL = 'v2';
|
export const GPUSTACK_API_BASE_URL = 'v2';
|
||||||
export const OPENAI_COMPATIBLE = 'v1';
|
export const OPENAI_COMPATIBLE = 'v1';
|
||||||
|
|
||||||
|
type SortDirection = 'ascend' | 'descend' | null;
|
||||||
|
export const TABLE_SORT_DIRECTIONS: SortDirection[] = [
|
||||||
|
'ascend',
|
||||||
|
'descend',
|
||||||
|
null
|
||||||
|
];
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { TABLE_SORT_DIRECTIONS } from '@/config/settings';
|
||||||
import useSetChunkRequest from '@/hooks/use-chunk-request';
|
import useSetChunkRequest from '@/hooks/use-chunk-request';
|
||||||
import useTableRowSelection from '@/hooks/use-table-row-selection';
|
import useTableRowSelection from '@/hooks/use-table-row-selection';
|
||||||
import useUpdateChunkedList from '@/hooks/use-update-chunk-list';
|
import useUpdateChunkedList from '@/hooks/use-update-chunk-list';
|
||||||
@@ -5,6 +6,7 @@ import { handleBatchRequest } from '@/utils';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import qs from 'query-string';
|
import qs from 'query-string';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
import { useTableMultiSort } from './use-table-sort';
|
||||||
|
|
||||||
type EventsType = 'CREATE' | 'UPDATE' | 'DELETE' | 'INSERT';
|
type EventsType = 'CREATE' | 'UPDATE' | 'DELETE' | 'INSERT';
|
||||||
|
|
||||||
@@ -51,13 +53,7 @@ export default function useTableFetch<T>(
|
|||||||
const chunkRequedtRef = useRef<any>(null);
|
const chunkRequedtRef = useRef<any>(null);
|
||||||
const modalRef = useRef<any>(null);
|
const modalRef = useRef<any>(null);
|
||||||
const rowSelection = useTableRowSelection();
|
const rowSelection = useTableRowSelection();
|
||||||
const [sortOrder, setSortOrder] = useState<{
|
const { sortOrder, handleMultiSortChange } = useTableMultiSort();
|
||||||
order?: 'ascend' | 'descend' | null;
|
|
||||||
columnKey?: string;
|
|
||||||
}>({
|
|
||||||
order: null,
|
|
||||||
columnKey: undefined
|
|
||||||
});
|
|
||||||
|
|
||||||
// for skeleton loading
|
// for skeleton loading
|
||||||
const [extraStatus, setExtraStatus] = useState<Record<string, any>>({
|
const [extraStatus, setExtraStatus] = useState<Record<string, any>>({
|
||||||
@@ -81,6 +77,7 @@ export default function useTableFetch<T>(
|
|||||||
page: 1,
|
page: 1,
|
||||||
perPage: 10,
|
perPage: 10,
|
||||||
search: '',
|
search: '',
|
||||||
|
sort_by: '',
|
||||||
...defaultQueryParams
|
...defaultQueryParams
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -106,7 +103,6 @@ export default function useTableFetch<T>(
|
|||||||
|
|
||||||
const updateHandler = (list: any) => {
|
const updateHandler = (list: any) => {
|
||||||
_.each(list, (data: any) => {
|
_.each(list, (data: any) => {
|
||||||
console.log('list================:', list);
|
|
||||||
updateChunkedList(data);
|
updateChunkedList(data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -238,9 +234,19 @@ export default function useTableFetch<T>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleTableChange = (pagination: any, filters: any, sorter: any) => {
|
const handleTableChange = (pagination: any, filters: any, sorter: any) => {
|
||||||
setSortOrder({
|
const sortKeys = handleMultiSortChange(sorter);
|
||||||
order: sorter.order,
|
setQueryParams((pre: any) => {
|
||||||
columnKey: sorter.columnKey || sorter.field
|
return {
|
||||||
|
...pre,
|
||||||
|
sort_by: sortKeys.join(',')
|
||||||
|
};
|
||||||
|
});
|
||||||
|
fetchData({
|
||||||
|
query: {
|
||||||
|
...queryParams,
|
||||||
|
page: 1,
|
||||||
|
sort_by: sortKeys.join(',')
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -337,6 +343,7 @@ export default function useTableFetch<T>(
|
|||||||
queryParams,
|
queryParams,
|
||||||
modalRef,
|
modalRef,
|
||||||
extraStatus,
|
extraStatus,
|
||||||
|
TABLE_SORT_DIRECTIONS,
|
||||||
setQueryParams,
|
setQueryParams,
|
||||||
handleDelete,
|
handleDelete,
|
||||||
handleDeleteBatch,
|
handleDeleteBatch,
|
||||||
|
|||||||
@@ -23,3 +23,32 @@ export default function useTableSort({
|
|||||||
setSortOrder: handleSortChange
|
setSortOrder: handleSortChange
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type orderType = {
|
||||||
|
columnKey?: string;
|
||||||
|
field?: string;
|
||||||
|
order: SortOrder;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useTableMultiSort() {
|
||||||
|
const [sortOrder, setSortOrder] = useState<string[]>([]);
|
||||||
|
|
||||||
|
const handleMultiSortChange = (order: orderType | orderType[]) => {
|
||||||
|
const sortOrders = Array.isArray(order) ? order : [order];
|
||||||
|
const sortOrderMap: string[] = [];
|
||||||
|
sortOrders.forEach((item) => {
|
||||||
|
const key = item.columnKey || item.field;
|
||||||
|
if (key) {
|
||||||
|
sortOrderMap.push(item.order === 'descend' ? `-${key}` : key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setSortOrder(sortOrderMap);
|
||||||
|
return sortOrderMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
sortOrder,
|
||||||
|
handleMultiSortChange
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,10 +10,7 @@ import { ListItem } from '../config/types';
|
|||||||
|
|
||||||
interface ColumnsHookProps {
|
interface ColumnsHookProps {
|
||||||
handleSelect: (val: string, record: ListItem) => void;
|
handleSelect: (val: string, record: ListItem) => void;
|
||||||
sortOrder: {
|
sortOrder: string;
|
||||||
order?: 'ascend' | 'descend' | null;
|
|
||||||
columnKey?: string;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const actionList: Global.ActionItem[] = [
|
const actionList: Global.ActionItem[] = [
|
||||||
@@ -42,6 +39,9 @@ const useModelsColumns = ({
|
|||||||
title: intl.formatMessage({ id: 'common.table.name' }),
|
title: intl.formatMessage({ id: 'common.table.name' }),
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
key: 'name',
|
key: 'name',
|
||||||
|
sorter: {
|
||||||
|
multiple: 1
|
||||||
|
},
|
||||||
render: (text: string, record: ListItem) => (
|
render: (text: string, record: ListItem) => (
|
||||||
<AutoTooltip ghost style={{ maxWidth: 400 }}>
|
<AutoTooltip ghost style={{ maxWidth: 400 }}>
|
||||||
{text}
|
{text}
|
||||||
@@ -52,6 +52,9 @@ const useModelsColumns = ({
|
|||||||
title: intl.formatMessage({ id: 'apikeys.form.expiretime' }),
|
title: intl.formatMessage({ id: 'apikeys.form.expiretime' }),
|
||||||
dataIndex: 'expires_at',
|
dataIndex: 'expires_at',
|
||||||
key: 'expires_at',
|
key: 'expires_at',
|
||||||
|
sorter: {
|
||||||
|
multiple: 2
|
||||||
|
},
|
||||||
render: (text: string, record: ListItem) => (
|
render: (text: string, record: ListItem) => (
|
||||||
<AutoTooltip ghost>
|
<AutoTooltip ghost>
|
||||||
{text
|
{text
|
||||||
@@ -93,11 +96,9 @@ const useModelsColumns = ({
|
|||||||
dataIndex: 'created_at',
|
dataIndex: 'created_at',
|
||||||
key: 'created_at',
|
key: 'created_at',
|
||||||
defaultSortOrder: 'descend',
|
defaultSortOrder: 'descend',
|
||||||
sortOrder:
|
sorter: {
|
||||||
sortOrder.order && sortOrder.columnKey === 'created_at'
|
multiple: 3
|
||||||
? sortOrder.order
|
},
|
||||||
: null,
|
|
||||||
sorter: false,
|
|
||||||
ellipsis: {
|
ellipsis: {
|
||||||
showTitle: false
|
showTitle: false
|
||||||
},
|
},
|
||||||
@@ -120,7 +121,7 @@ const useModelsColumns = ({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}, [sortOrder, intl, handleSelect]);
|
}, [intl, handleSelect]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useModelsColumns;
|
export default useModelsColumns;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import useKeysColumns from './hooks/use-keys-columns';
|
|||||||
|
|
||||||
const APIKeys: React.FC = () => {
|
const APIKeys: React.FC = () => {
|
||||||
const {
|
const {
|
||||||
|
TABLE_SORT_DIRECTIONS,
|
||||||
dataSource,
|
dataSource,
|
||||||
rowSelection,
|
rowSelection,
|
||||||
queryParams,
|
queryParams,
|
||||||
@@ -32,7 +33,10 @@ const APIKeys: React.FC = () => {
|
|||||||
} = useTableFetch<ListItem>({
|
} = useTableFetch<ListItem>({
|
||||||
fetchAPI: queryApisKeysList,
|
fetchAPI: queryApisKeysList,
|
||||||
deleteAPI: deleteApisKey,
|
deleteAPI: deleteApisKey,
|
||||||
contentForDelete: 'apikeys.table.apikeys'
|
contentForDelete: 'apikeys.table.apikeys',
|
||||||
|
defaultQueryParams: {
|
||||||
|
sort_by: '-created_at'
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
@@ -139,7 +143,7 @@ const APIKeys: React.FC = () => {
|
|||||||
dataSource={dataSource.dataList}
|
dataSource={dataSource.dataList}
|
||||||
rowSelection={rowSelection}
|
rowSelection={rowSelection}
|
||||||
loading={dataSource.loading}
|
loading={dataSource.loading}
|
||||||
sortDirections={['ascend', 'descend', 'ascend']}
|
sortDirections={TABLE_SORT_DIRECTIONS}
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
onChange={handleTableChange}
|
onChange={handleTableChange}
|
||||||
pagination={{
|
pagination={{
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import IconFont from '@/components/icon-font';
|
|||||||
import { FilterBar } from '@/components/page-tools';
|
import { FilterBar } from '@/components/page-tools';
|
||||||
import SealTable from '@/components/seal-table';
|
import SealTable from '@/components/seal-table';
|
||||||
import TableContext from '@/components/seal-table/table-context';
|
import TableContext from '@/components/seal-table/table-context';
|
||||||
|
import { TableOrder } from '@/components/seal-table/types';
|
||||||
import { PageAction } from '@/config';
|
import { PageAction } from '@/config';
|
||||||
|
import { TABLE_SORT_DIRECTIONS } from '@/config/settings';
|
||||||
import type { PageActionType } from '@/config/types';
|
import type { PageActionType } from '@/config/types';
|
||||||
import useExpandedRowKeys from '@/hooks/use-expanded-row-keys';
|
import useExpandedRowKeys from '@/hooks/use-expanded-row-keys';
|
||||||
import useTableFetch from '@/hooks/use-table-fetch';
|
import useTableFetch from '@/hooks/use-table-fetch';
|
||||||
@@ -54,6 +56,7 @@ const Clusters: React.FC = () => {
|
|||||||
rowSelection,
|
rowSelection,
|
||||||
queryParams,
|
queryParams,
|
||||||
modalRef,
|
modalRef,
|
||||||
|
handleTableChange,
|
||||||
handleDelete,
|
handleDelete,
|
||||||
handleDeleteBatch,
|
handleDeleteBatch,
|
||||||
fetchData,
|
fetchData,
|
||||||
@@ -65,7 +68,10 @@ const Clusters: React.FC = () => {
|
|||||||
deleteAPI: deleteCluster,
|
deleteAPI: deleteCluster,
|
||||||
watch: true,
|
watch: true,
|
||||||
API: CLUSTERS_API,
|
API: CLUSTERS_API,
|
||||||
contentForDelete: 'menu.clusterManagement.clusters'
|
contentForDelete: 'menu.clusterManagement.clusters',
|
||||||
|
defaultQueryParams: {
|
||||||
|
sort_by: '-created_at'
|
||||||
|
}
|
||||||
});
|
});
|
||||||
const { watchDataList: allWorkerPoolList } = useWatchList(WORKER_POOLS_API);
|
const { watchDataList: allWorkerPoolList } = useWatchList(WORKER_POOLS_API);
|
||||||
const [expandAtom] = useAtom(expandKeysAtom);
|
const [expandAtom] = useAtom(expandKeysAtom);
|
||||||
@@ -227,6 +233,10 @@ const Clusters: React.FC = () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleOnSortChange = (order: TableOrder | Array<TableOrder>) => {
|
||||||
|
handleTableChange({}, {}, order);
|
||||||
|
};
|
||||||
|
|
||||||
const setDisableExpand = (row: ClusterListItem) => {
|
const setDisableExpand = (row: ClusterListItem) => {
|
||||||
return (
|
return (
|
||||||
row.provider !== ProviderValueMap.DigitalOcean ||
|
row.provider !== ProviderValueMap.DigitalOcean ||
|
||||||
@@ -314,10 +324,12 @@ const Clusters: React.FC = () => {
|
|||||||
<SealTable
|
<SealTable
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
loadChildren={getWorkerPoolList}
|
loadChildren={getWorkerPoolList}
|
||||||
|
sortDirections={TABLE_SORT_DIRECTIONS}
|
||||||
expandedRowKeys={expandedRowKeys}
|
expandedRowKeys={expandedRowKeys}
|
||||||
onExpand={handleExpandChange}
|
onExpand={handleExpandChange}
|
||||||
onExpandAll={handleToggleExpandAll}
|
onExpandAll={handleToggleExpandAll}
|
||||||
renderChildren={renderChildren}
|
renderChildren={renderChildren}
|
||||||
|
onTableSort={handleOnSortChange}
|
||||||
dataSource={dataSource.dataList}
|
dataSource={dataSource.dataList}
|
||||||
loading={dataSource.loading}
|
loading={dataSource.loading}
|
||||||
loadend={dataSource.loadend}
|
loadend={dataSource.loadend}
|
||||||
|
|||||||
@@ -58,7 +58,10 @@ const Credentials: React.FC = () => {
|
|||||||
} = useTableFetch<ListItem>({
|
} = useTableFetch<ListItem>({
|
||||||
fetchAPI: queryCredentialList,
|
fetchAPI: queryCredentialList,
|
||||||
deleteAPI: deleteCredential,
|
deleteAPI: deleteCredential,
|
||||||
contentForDelete: 'menu.clusterManagement.credentials'
|
contentForDelete: 'menu.clusterManagement.credentials',
|
||||||
|
defaultQueryParams: {
|
||||||
|
sort_by: '-created_at'
|
||||||
|
}
|
||||||
});
|
});
|
||||||
const [isFromCluster, setIsFromCluster] = useAtom(fromClusterCreationAtom);
|
const [isFromCluster, setIsFromCluster] = useAtom(fromClusterCreationAtom);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ const useClusterColumns = (
|
|||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'common.table.name' }),
|
title: intl.formatMessage({ id: 'common.table.name' }),
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
|
sorter: {
|
||||||
|
multiple: 1
|
||||||
|
},
|
||||||
span: 3,
|
span: 3,
|
||||||
render: (text: string, record: ClusterListItem) => (
|
render: (text: string, record: ClusterListItem) => (
|
||||||
<AutoTooltip ghost>{text}</AutoTooltip>
|
<AutoTooltip ghost>{text}</AutoTooltip>
|
||||||
@@ -41,6 +44,9 @@ const useClusterColumns = (
|
|||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'clusters.table.provider' }),
|
title: intl.formatMessage({ id: 'clusters.table.provider' }),
|
||||||
dataIndex: 'provider',
|
dataIndex: 'provider',
|
||||||
|
sorter: {
|
||||||
|
multiple: 2
|
||||||
|
},
|
||||||
span: 4,
|
span: 4,
|
||||||
render: (value: string) => (
|
render: (value: string) => (
|
||||||
<AutoTooltip ghost minWidth={20}>
|
<AutoTooltip ghost minWidth={20}>
|
||||||
@@ -86,6 +92,10 @@ const useClusterColumns = (
|
|||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'common.table.createTime' }),
|
title: intl.formatMessage({ id: 'common.table.createTime' }),
|
||||||
dataIndex: 'created_at',
|
dataIndex: 'created_at',
|
||||||
|
defaultSortOrder: 'descend',
|
||||||
|
sorter: {
|
||||||
|
multiple: 5
|
||||||
|
},
|
||||||
span: 4,
|
span: 4,
|
||||||
render: (value: string) => (
|
render: (value: string) => (
|
||||||
<AutoTooltip ghost minWidth={20}>
|
<AutoTooltip ghost minWidth={20}>
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ const useCredentialColumns = (
|
|||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'common.table.name' }),
|
title: intl.formatMessage({ id: 'common.table.name' }),
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
|
sorter: {
|
||||||
|
multiple: 1
|
||||||
|
},
|
||||||
render: (text: string) => (
|
render: (text: string) => (
|
||||||
<AutoTooltip ghost minWidth={20}>
|
<AutoTooltip ghost minWidth={20}>
|
||||||
{text}
|
{text}
|
||||||
@@ -32,6 +35,7 @@ const useCredentialColumns = (
|
|||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'clusters.table.provider' }),
|
title: intl.formatMessage({ id: 'clusters.table.provider' }),
|
||||||
dataIndex: 'provider',
|
dataIndex: 'provider',
|
||||||
|
sorter: false,
|
||||||
render: (value: string) => <span>{ProviderLabelMap[value]}</span>
|
render: (value: string) => <span>{ProviderLabelMap[value]}</span>
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -39,11 +43,9 @@ const useCredentialColumns = (
|
|||||||
dataIndex: 'created_at',
|
dataIndex: 'created_at',
|
||||||
showSorterTooltip: false,
|
showSorterTooltip: false,
|
||||||
defaultSortOrder: 'descend',
|
defaultSortOrder: 'descend',
|
||||||
sortOrder:
|
sorter: {
|
||||||
sortOrder.order && sortOrder.columnKey === 'created_at'
|
multiple: 3
|
||||||
? sortOrder.order
|
},
|
||||||
: null,
|
|
||||||
sorter: false,
|
|
||||||
ellipsis: {
|
ellipsis: {
|
||||||
showTitle: false
|
showTitle: false
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import { PageSize } from '@/components/logs-viewer/config';
|
|||||||
import PageTools from '@/components/page-tools';
|
import PageTools from '@/components/page-tools';
|
||||||
import BaseSelect from '@/components/seal-form/base/select';
|
import BaseSelect from '@/components/seal-form/base/select';
|
||||||
import SealTable from '@/components/seal-table';
|
import SealTable from '@/components/seal-table';
|
||||||
|
import { TableOrder } from '@/components/seal-table/types';
|
||||||
import { PageAction } from '@/config';
|
import { PageAction } from '@/config';
|
||||||
|
import { TABLE_SORT_DIRECTIONS } from '@/config/settings';
|
||||||
import { PageActionType } from '@/config/types';
|
import { PageActionType } from '@/config/types';
|
||||||
import useBodyScroll from '@/hooks/use-body-scroll';
|
import useBodyScroll from '@/hooks/use-body-scroll';
|
||||||
import useExpandedRowKeys from '@/hooks/use-expanded-row-keys';
|
import useExpandedRowKeys from '@/hooks/use-expanded-row-keys';
|
||||||
@@ -75,6 +77,8 @@ interface ModelsProps {
|
|||||||
handleOnToggleExpandAll: () => void;
|
handleOnToggleExpandAll: () => void;
|
||||||
onStop?: (ids: number[]) => void;
|
onStop?: (ids: number[]) => void;
|
||||||
onStart?: () => void;
|
onStart?: () => void;
|
||||||
|
onTableSort?: (order: TableOrder | Array<TableOrder>) => void;
|
||||||
|
sortOrder: string[];
|
||||||
queryParams: {
|
queryParams: {
|
||||||
page: number;
|
page: number;
|
||||||
perPage: number;
|
perPage: number;
|
||||||
@@ -114,6 +118,8 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
handleClusterChange,
|
handleClusterChange,
|
||||||
onStop,
|
onStop,
|
||||||
onStart,
|
onStart,
|
||||||
|
onTableSort,
|
||||||
|
sortOrder,
|
||||||
deleteIds,
|
deleteIds,
|
||||||
dataSource,
|
dataSource,
|
||||||
queryParams,
|
queryParams,
|
||||||
@@ -148,13 +154,6 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
removeExpandedRowKey,
|
removeExpandedRowKey,
|
||||||
expandedRowKeys
|
expandedRowKeys
|
||||||
} = useExpandedRowKeys(expandAtom);
|
} = useExpandedRowKeys(expandAtom);
|
||||||
const [sortOrder, setSortOrder] = useState<{
|
|
||||||
columnKey: string;
|
|
||||||
order: 'ascend' | 'descend' | null;
|
|
||||||
}>({
|
|
||||||
order: null,
|
|
||||||
columnKey: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
const [apiAccessInfo, setAPIAccessInfo] = useState<any>({
|
const [apiAccessInfo, setAPIAccessInfo] = useState<any>({
|
||||||
show: false,
|
show: false,
|
||||||
@@ -219,11 +218,8 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
currentData.current = data;
|
currentData.current = data;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOnSort = (dataIndex: string, order: any) => {
|
const handleOnSort = (order: TableOrder | Array<TableOrder>) => {
|
||||||
setSortOrder({
|
onTableSort?.(order);
|
||||||
columnKey: dataIndex,
|
|
||||||
order: order
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOnCell = useMemoizedFn(async (record: any, extra: any) => {
|
const handleOnCell = useMemoizedFn(async (record: any, extra: any) => {
|
||||||
@@ -710,6 +706,7 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
|
|
||||||
<SealTable
|
<SealTable
|
||||||
columns={columns}
|
columns={columns}
|
||||||
|
sortDirections={TABLE_SORT_DIRECTIONS}
|
||||||
dataSource={dataSource}
|
dataSource={dataSource}
|
||||||
rowSelection={rowSelection}
|
rowSelection={rowSelection}
|
||||||
expandedRowKeys={expandedRowKeys}
|
expandedRowKeys={expandedRowKeys}
|
||||||
@@ -720,7 +717,7 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
rowKey="id"
|
rowKey="id"
|
||||||
childParentKey="model_id"
|
childParentKey="model_id"
|
||||||
expandable={true}
|
expandable={true}
|
||||||
onSort={handleOnSort}
|
onTableSort={handleOnSort}
|
||||||
onCell={handleOnCell}
|
onCell={handleOnCell}
|
||||||
pollingChildren={false}
|
pollingChildren={false}
|
||||||
watchChildren={true}
|
watchChildren={true}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { OPENAI_COMPATIBLE } from '@/config/settings';
|
|||||||
import { QuestionCircleOutlined } from '@ant-design/icons';
|
import { QuestionCircleOutlined } from '@ant-design/icons';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Tooltip } from 'antd';
|
import { Tooltip } from 'antd';
|
||||||
import type { SortOrder } from 'antd/es/table/interface';
|
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
@@ -34,10 +33,7 @@ const setModelActionList = (record: any) => {
|
|||||||
|
|
||||||
interface ModelsColumnsHookProps {
|
interface ModelsColumnsHookProps {
|
||||||
handleSelect: (val: string, record: ListItem) => void;
|
handleSelect: (val: string, record: ListItem) => void;
|
||||||
sortOrder: {
|
sortOrder: string[];
|
||||||
columnKey: string;
|
|
||||||
order: SortOrder;
|
|
||||||
};
|
|
||||||
clusterList: Global.BaseOption<
|
clusterList: Global.BaseOption<
|
||||||
number,
|
number,
|
||||||
{ provider: string; state: string | number }
|
{ provider: string; state: string | number }
|
||||||
@@ -57,11 +53,9 @@ const useModelsColumns = ({
|
|||||||
title: intl.formatMessage({ id: 'common.table.name' }),
|
title: intl.formatMessage({ id: 'common.table.name' }),
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
key: 'name',
|
key: 'name',
|
||||||
sortOrder:
|
sorter: {
|
||||||
sortOrder.order && sortOrder.columnKey === 'name'
|
multiple: 1
|
||||||
? sortOrder.order
|
},
|
||||||
: null,
|
|
||||||
sorter: false,
|
|
||||||
span: 5,
|
span: 5,
|
||||||
render: (text: string, record: ListItem) => (
|
render: (text: string, record: ListItem) => (
|
||||||
<span className="flex-center" style={{ maxWidth: '100%' }}>
|
<span className="flex-center" style={{ maxWidth: '100%' }}>
|
||||||
@@ -74,8 +68,11 @@ const useModelsColumns = ({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'clusters.title' }),
|
title: intl.formatMessage({ id: 'clusters.title' }),
|
||||||
dataIndex: 'cluster',
|
dataIndex: 'cluster_id',
|
||||||
key: 'cluster',
|
key: 'cluster_id',
|
||||||
|
sorter: {
|
||||||
|
multiple: 2
|
||||||
|
},
|
||||||
span: 3,
|
span: 3,
|
||||||
render: (text: string, record: ListItem) => (
|
render: (text: string, record: ListItem) => (
|
||||||
<span className="flex flex-column" style={{ width: '100%' }}>
|
<span className="flex flex-column" style={{ width: '100%' }}>
|
||||||
@@ -90,6 +87,9 @@ const useModelsColumns = ({
|
|||||||
title: intl.formatMessage({ id: 'models.form.source' }),
|
title: intl.formatMessage({ id: 'models.form.source' }),
|
||||||
dataIndex: 'source',
|
dataIndex: 'source',
|
||||||
key: 'source',
|
key: 'source',
|
||||||
|
sorter: {
|
||||||
|
multiple: 3
|
||||||
|
},
|
||||||
span: 5,
|
span: 5,
|
||||||
render: (text: string, record: ListItem) => (
|
render: (text: string, record: ListItem) => (
|
||||||
<span className="flex flex-column" style={{ width: '100%' }}>
|
<span className="flex flex-column" style={{ width: '100%' }}>
|
||||||
@@ -111,9 +111,12 @@ const useModelsColumns = ({
|
|||||||
<QuestionCircleOutlined className="m-l-5" />
|
<QuestionCircleOutlined className="m-l-5" />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
),
|
),
|
||||||
dataIndex: 'replicas',
|
dataIndex: 'ready_replicas',
|
||||||
key: 'replicas',
|
key: 'ready_replicas',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
|
sorter: {
|
||||||
|
multiple: 4
|
||||||
|
},
|
||||||
span: 4,
|
span: 4,
|
||||||
editable: {
|
editable: {
|
||||||
valueType: 'number',
|
valueType: 'number',
|
||||||
@@ -130,11 +133,9 @@ const useModelsColumns = ({
|
|||||||
dataIndex: 'created_at',
|
dataIndex: 'created_at',
|
||||||
key: 'created_at',
|
key: 'created_at',
|
||||||
defaultSortOrder: 'descend',
|
defaultSortOrder: 'descend',
|
||||||
sortOrder:
|
sorter: {
|
||||||
sortOrder.order && sortOrder.columnKey === 'created_at'
|
multiple: 5
|
||||||
? sortOrder.order
|
},
|
||||||
: null,
|
|
||||||
sorter: false,
|
|
||||||
span: 4,
|
span: 4,
|
||||||
render: (text: number) => (
|
render: (text: number) => (
|
||||||
<AutoTooltip ghost>
|
<AutoTooltip ghost>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import TableContext from '@/components/seal-table/table-context';
|
import TableContext from '@/components/seal-table/table-context';
|
||||||
|
import { TableOrder } from '@/components/seal-table/types';
|
||||||
import useSetChunkRequest from '@/hooks/use-chunk-request';
|
import useSetChunkRequest from '@/hooks/use-chunk-request';
|
||||||
|
import { useTableMultiSort } from '@/hooks/use-table-sort';
|
||||||
import useUpdateChunkedList from '@/hooks/use-update-chunk-list';
|
import useUpdateChunkedList from '@/hooks/use-update-chunk-list';
|
||||||
import { useMemoizedFn } from 'ahooks';
|
import { useMemoizedFn } from 'ahooks';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
@@ -15,6 +17,7 @@ import TableList from './components/table-list';
|
|||||||
import { ListItem } from './config/types';
|
import { ListItem } from './config/types';
|
||||||
|
|
||||||
const Models: React.FC = () => {
|
const Models: React.FC = () => {
|
||||||
|
const { sortOrder, handleMultiSortChange } = useTableMultiSort();
|
||||||
const { setChunkRequest, createAxiosToken } = useSetChunkRequest();
|
const { setChunkRequest, createAxiosToken } = useSetChunkRequest();
|
||||||
const { setChunkRequest: setModelInstanceChunkRequest } =
|
const { setChunkRequest: setModelInstanceChunkRequest } =
|
||||||
useSetChunkRequest();
|
useSetChunkRequest();
|
||||||
@@ -43,7 +46,8 @@ const Models: React.FC = () => {
|
|||||||
perPage: 10,
|
perPage: 10,
|
||||||
search: '',
|
search: '',
|
||||||
cluster_id: 0,
|
cluster_id: 0,
|
||||||
categories: []
|
categories: [],
|
||||||
|
sort_by: '-created_at'
|
||||||
});
|
});
|
||||||
|
|
||||||
const { updateChunkedList, cacheDataListRef } = useUpdateChunkedList({
|
const { updateChunkedList, cacheDataListRef } = useUpdateChunkedList({
|
||||||
@@ -96,6 +100,7 @@ const Models: React.FC = () => {
|
|||||||
perPage: number;
|
perPage: number;
|
||||||
search: string;
|
search: string;
|
||||||
categories: any[];
|
categories: any[];
|
||||||
|
sort_by: string;
|
||||||
};
|
};
|
||||||
}) => {
|
}) => {
|
||||||
const { loadingVal, query } = params || {};
|
const { loadingVal, query } = params || {};
|
||||||
@@ -294,6 +299,23 @@ const Models: React.FC = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleOnSortChange = (order: TableOrder | Array<TableOrder>) => {
|
||||||
|
const sortKeys = handleMultiSortChange(order);
|
||||||
|
setQueryParams((pre: any) => {
|
||||||
|
return {
|
||||||
|
...pre,
|
||||||
|
sort_by: sortKeys.join(',')
|
||||||
|
};
|
||||||
|
});
|
||||||
|
fetchData({
|
||||||
|
query: {
|
||||||
|
...queryParams,
|
||||||
|
page: 1,
|
||||||
|
sort_by: sortKeys.join(',')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let timer: any = null;
|
let timer: any = null;
|
||||||
// fetch data first time
|
// fetch data first time
|
||||||
@@ -397,6 +419,8 @@ const Models: React.FC = () => {
|
|||||||
onCancelViewLogs={handleOnCancelViewLogs}
|
onCancelViewLogs={handleOnCancelViewLogs}
|
||||||
onStop={handleSearchBySilent}
|
onStop={handleSearchBySilent}
|
||||||
onStart={handleSearchBySilent}
|
onStart={handleSearchBySilent}
|
||||||
|
onTableSort={handleOnSortChange}
|
||||||
|
sortOrder={sortOrder}
|
||||||
queryParams={queryParams}
|
queryParams={queryParams}
|
||||||
loading={dataSource.loading}
|
loading={dataSource.loading}
|
||||||
loadend={dataSource.loadend}
|
loadend={dataSource.loadend}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import IconFont from '@/components/icon-font';
|
import IconFont from '@/components/icon-font';
|
||||||
import { FilterBar } from '@/components/page-tools';
|
import { FilterBar } from '@/components/page-tools';
|
||||||
|
import { TABLE_SORT_DIRECTIONS } from '@/config/settings';
|
||||||
import useTableFetch from '@/hooks/use-table-fetch';
|
import useTableFetch from '@/hooks/use-table-fetch';
|
||||||
import NoResult from '@/pages/_components/no-result';
|
import NoResult from '@/pages/_components/no-result';
|
||||||
import PageBox from '@/pages/_components/page-box';
|
import PageBox from '@/pages/_components/page-box';
|
||||||
@@ -102,7 +103,7 @@ const GPUList: React.FC = () => {
|
|||||||
<Table
|
<Table
|
||||||
columns={columns}
|
columns={columns}
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
sortDirections={['ascend', 'descend', 'ascend']}
|
sortDirections={TABLE_SORT_DIRECTIONS}
|
||||||
tableLayout={dataSource.loadend ? 'auto' : 'fixed'}
|
tableLayout={dataSource.loadend ? 'auto' : 'fixed'}
|
||||||
dataSource={dataSource.dataList}
|
dataSource={dataSource.dataList}
|
||||||
loading={dataSource.loading}
|
loading={dataSource.loading}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import DeleteModal from '@/components/delete-modal';
|
|||||||
import IconFont from '@/components/icon-font';
|
import IconFont from '@/components/icon-font';
|
||||||
import { FilterBar } from '@/components/page-tools';
|
import { FilterBar } from '@/components/page-tools';
|
||||||
import { PageAction } from '@/config';
|
import { PageAction } from '@/config';
|
||||||
|
import { TABLE_SORT_DIRECTIONS } from '@/config/settings';
|
||||||
import useAppUtils from '@/hooks/use-app-utils';
|
import useAppUtils from '@/hooks/use-app-utils';
|
||||||
import useBodyScroll from '@/hooks/use-body-scroll';
|
import useBodyScroll from '@/hooks/use-body-scroll';
|
||||||
import useTableFetch from '@/hooks/use-table-fetch';
|
import useTableFetch from '@/hooks/use-table-fetch';
|
||||||
@@ -67,7 +68,10 @@ const ModelFiles = () => {
|
|||||||
deleteAPI: deleteModelFile,
|
deleteAPI: deleteModelFile,
|
||||||
API: MODEL_FILES_API,
|
API: MODEL_FILES_API,
|
||||||
watch: true,
|
watch: true,
|
||||||
contentForDelete: 'resources.modelfiles.modelfile'
|
contentForDelete: 'resources.modelfiles.modelfile',
|
||||||
|
defaultQueryParams: {
|
||||||
|
sort_by: '-created_at'
|
||||||
|
}
|
||||||
});
|
});
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const { showSuccess } = useAppUtils();
|
const { showSuccess } = useAppUtils();
|
||||||
@@ -316,6 +320,7 @@ const ModelFiles = () => {
|
|||||||
<Table
|
<Table
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
tableLayout="fixed"
|
tableLayout="fixed"
|
||||||
|
sortDirections={TABLE_SORT_DIRECTIONS}
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
onChange={handleTableChange}
|
onChange={handleTableChange}
|
||||||
dataSource={dataSource.dataList}
|
dataSource={dataSource.dataList}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import DeleteModal from '@/components/delete-modal';
|
import DeleteModal from '@/components/delete-modal';
|
||||||
import { FilterBar } from '@/components/page-tools';
|
import { FilterBar } from '@/components/page-tools';
|
||||||
|
import { TABLE_SORT_DIRECTIONS } from '@/config/settings';
|
||||||
import useTableFetch from '@/hooks/use-table-fetch';
|
import useTableFetch from '@/hooks/use-table-fetch';
|
||||||
import PageBox from '@/pages/_components/page-box';
|
import PageBox from '@/pages/_components/page-box';
|
||||||
import { queryClusterList } from '@/pages/cluster-management/apis';
|
import { queryClusterList } from '@/pages/cluster-management/apis';
|
||||||
@@ -51,7 +52,10 @@ const Workers: React.FC = () => {
|
|||||||
events: ['UPDATE', 'DELETE', 'INSERT'],
|
events: ['UPDATE', 'DELETE', 'INSERT'],
|
||||||
contentForDelete: 'resources.worker',
|
contentForDelete: 'resources.worker',
|
||||||
watch: true,
|
watch: true,
|
||||||
API: WORKERS_API
|
API: WORKERS_API,
|
||||||
|
defaultQueryParams: {
|
||||||
|
sort_by: '-created_at'
|
||||||
|
}
|
||||||
});
|
});
|
||||||
const { TerminalPanel, terminals, handleAddTerminal } = useTerminalTabs();
|
const { TerminalPanel, terminals, handleAddTerminal } = useTerminalTabs();
|
||||||
const { MaintenanceModal, handleStopMaintenance, setOpenStatus } =
|
const { MaintenanceModal, handleStopMaintenance, setOpenStatus } =
|
||||||
@@ -270,7 +274,7 @@ const Workers: React.FC = () => {
|
|||||||
<ConfigProvider renderEmpty={renderEmpty}>
|
<ConfigProvider renderEmpty={renderEmpty}>
|
||||||
<Table
|
<Table
|
||||||
columns={columns}
|
columns={columns}
|
||||||
sortDirections={['ascend', 'descend', 'ascend']}
|
sortDirections={TABLE_SORT_DIRECTIONS}
|
||||||
tableLayout={dataSource.loadend ? 'auto' : 'fixed'}
|
tableLayout={dataSource.loadend ? 'auto' : 'fixed'}
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
dataSource={dataSource.dataList}
|
dataSource={dataSource.dataList}
|
||||||
|
|||||||
@@ -255,10 +255,7 @@ const getWorkerName = (
|
|||||||
const useFilesColumns = (props: {
|
const useFilesColumns = (props: {
|
||||||
handleSelect: (action: string, record: ListItem) => void;
|
handleSelect: (action: string, record: ListItem) => void;
|
||||||
workersList: Global.BaseOption<number>[];
|
workersList: Global.BaseOption<number>[];
|
||||||
sortOrder: {
|
sortOrder: string[];
|
||||||
order?: 'ascend' | 'descend' | null;
|
|
||||||
columnKey?: string;
|
|
||||||
};
|
|
||||||
}): ColumnsType<ListItem> => {
|
}): ColumnsType<ListItem> => {
|
||||||
const { workersList, sortOrder, handleSelect } = props;
|
const { workersList, sortOrder, handleSelect } = props;
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
@@ -268,6 +265,9 @@ const useFilesColumns = (props: {
|
|||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'models.form.source' }),
|
title: intl.formatMessage({ id: 'models.form.source' }),
|
||||||
dataIndex: 'source',
|
dataIndex: 'source',
|
||||||
|
sorter: {
|
||||||
|
multiple: 1
|
||||||
|
},
|
||||||
ellipsis: {
|
ellipsis: {
|
||||||
showTitle: false
|
showTitle: false
|
||||||
},
|
},
|
||||||
@@ -285,7 +285,10 @@ const useFilesColumns = (props: {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'resources.worker' }),
|
title: intl.formatMessage({ id: 'resources.worker' }),
|
||||||
dataIndex: 'worker_name',
|
dataIndex: 'worker_id',
|
||||||
|
sorter: {
|
||||||
|
multiple: 2
|
||||||
|
},
|
||||||
width: '18%',
|
width: '18%',
|
||||||
ellipsis: {
|
ellipsis: {
|
||||||
showTitle: false
|
showTitle: false
|
||||||
@@ -309,6 +312,9 @@ const useFilesColumns = (props: {
|
|||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'resources.modelfiles.form.path' }),
|
title: intl.formatMessage({ id: 'resources.modelfiles.form.path' }),
|
||||||
dataIndex: 'resolved_paths',
|
dataIndex: 'resolved_paths',
|
||||||
|
sorter: {
|
||||||
|
multiple: 3
|
||||||
|
},
|
||||||
width: '20%',
|
width: '20%',
|
||||||
ellipsis: {
|
ellipsis: {
|
||||||
showTitle: false
|
showTitle: false
|
||||||
@@ -336,15 +342,15 @@ const useFilesColumns = (props: {
|
|||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'common.table.createTime' }),
|
title: intl.formatMessage({ id: 'common.table.createTime' }),
|
||||||
dataIndex: 'created_at',
|
dataIndex: 'created_at',
|
||||||
sorter: false,
|
defaultSortOrder: 'descend',
|
||||||
|
key: 'created_at',
|
||||||
|
sorter: {
|
||||||
|
multiple: 4
|
||||||
|
},
|
||||||
width: 180,
|
width: 180,
|
||||||
ellipsis: {
|
ellipsis: {
|
||||||
showTitle: false
|
showTitle: false
|
||||||
},
|
},
|
||||||
sortOrder:
|
|
||||||
sortOrder.order && sortOrder.columnKey === 'created_at'
|
|
||||||
? sortOrder.order
|
|
||||||
: null,
|
|
||||||
render: (text: number) => (
|
render: (text: number) => (
|
||||||
<AutoTooltip ghost minWidth={20}>
|
<AutoTooltip ghost minWidth={20}>
|
||||||
{dayjs(text).format('YYYY-MM-DD HH:mm:ss')}
|
{dayjs(text).format('YYYY-MM-DD HH:mm:ss')}
|
||||||
@@ -363,7 +369,7 @@ const useFilesColumns = (props: {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}, [intl, sortOrder, workersList, handleSelect]);
|
}, [intl, workersList, handleSelect]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useFilesColumns;
|
export default useFilesColumns;
|
||||||
|
|||||||
@@ -39,10 +39,7 @@ const useGPUColumns = (props: {
|
|||||||
loadend: boolean;
|
loadend: boolean;
|
||||||
firstLoad: boolean;
|
firstLoad: boolean;
|
||||||
clusterList: Global.BaseOption<number>[];
|
clusterList: Global.BaseOption<number>[];
|
||||||
sortOrder: {
|
sortOrder: string[];
|
||||||
order?: 'ascend' | 'descend' | null;
|
|
||||||
columnKey?: string;
|
|
||||||
};
|
|
||||||
}): ColumnsType<GPUDeviceItem> => {
|
}): ColumnsType<GPUDeviceItem> => {
|
||||||
const { clusterList, loadend, firstLoad, sortOrder } = props;
|
const { clusterList, loadend, firstLoad, sortOrder } = props;
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
@@ -53,11 +50,9 @@ const useGPUColumns = (props: {
|
|||||||
title: intl.formatMessage({ id: 'common.table.name' }),
|
title: intl.formatMessage({ id: 'common.table.name' }),
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
width: 240,
|
width: 240,
|
||||||
sorter: false,
|
sorter: {
|
||||||
sortOrder:
|
multiple: 1
|
||||||
sortOrder.order && sortOrder.columnKey === 'name'
|
},
|
||||||
? sortOrder.order
|
|
||||||
: null,
|
|
||||||
render: (text: string, record: GPUDeviceItem) => (
|
render: (text: string, record: GPUDeviceItem) => (
|
||||||
<AutoTooltip ghost maxWidth={240}>
|
<AutoTooltip ghost maxWidth={240}>
|
||||||
{text}
|
{text}
|
||||||
@@ -67,11 +62,17 @@ const useGPUColumns = (props: {
|
|||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'resources.table.index' }),
|
title: intl.formatMessage({ id: 'resources.table.index' }),
|
||||||
dataIndex: 'index',
|
dataIndex: 'index',
|
||||||
|
sorter: {
|
||||||
|
multiple: 2
|
||||||
|
},
|
||||||
render: (text: string, record: GPUDeviceItem) => <span>{text}</span>
|
render: (text: string, record: GPUDeviceItem) => <span>{text}</span>
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'clusters.title' }),
|
title: intl.formatMessage({ id: 'clusters.title' }),
|
||||||
dataIndex: 'cluster_id',
|
dataIndex: 'cluster_id',
|
||||||
|
sorter: {
|
||||||
|
multiple: 3
|
||||||
|
},
|
||||||
ellipsis: {
|
ellipsis: {
|
||||||
showTitle: false
|
showTitle: false
|
||||||
},
|
},
|
||||||
@@ -84,6 +85,9 @@ const useGPUColumns = (props: {
|
|||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'resources.worker' }),
|
title: intl.formatMessage({ id: 'resources.worker' }),
|
||||||
dataIndex: 'worker_name',
|
dataIndex: 'worker_name',
|
||||||
|
sorter: {
|
||||||
|
multiple: 4
|
||||||
|
},
|
||||||
ellipsis: {
|
ellipsis: {
|
||||||
showTitle: false
|
showTitle: false
|
||||||
},
|
},
|
||||||
@@ -93,7 +97,10 @@ const useGPUColumns = (props: {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'resources.table.vender' }),
|
title: intl.formatMessage({ id: 'resources.table.vender' }),
|
||||||
dataIndex: 'vendor'
|
dataIndex: 'vendor',
|
||||||
|
sorter: {
|
||||||
|
multiple: 5
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: `${intl.formatMessage({ id: 'resources.table.temperature' })} (°C)`,
|
title: `${intl.formatMessage({ id: 'resources.table.temperature' })} (°C)`,
|
||||||
@@ -104,8 +111,11 @@ const useGPUColumns = (props: {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: `${intl.formatMessage({ id: 'resources.table.utilization' })}`,
|
title: `${intl.formatMessage({ id: 'resources.table.utilization' })}`,
|
||||||
dataIndex: 'gpuUtil',
|
dataIndex: 'core.utilization_rate',
|
||||||
key: 'gpuUtil',
|
key: 'core.utilization_rate',
|
||||||
|
sorter: {
|
||||||
|
multiple: 6
|
||||||
|
},
|
||||||
render: (text: number, record: GPUDeviceItem) => {
|
render: (text: number, record: GPUDeviceItem) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -122,8 +132,11 @@ const useGPUColumns = (props: {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'resources.table.vramutilization' }),
|
title: intl.formatMessage({ id: 'resources.table.vramutilization' }),
|
||||||
dataIndex: 'VRAM',
|
dataIndex: 'memory.utilization_rate',
|
||||||
key: 'VRAM',
|
key: 'memory.utilization_rate',
|
||||||
|
sorter: {
|
||||||
|
multiple: 7
|
||||||
|
},
|
||||||
render: (text: number, record: GPUDeviceItem, index: number) => {
|
render: (text: number, record: GPUDeviceItem, index: number) => {
|
||||||
return (
|
return (
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
@@ -147,7 +160,7 @@ const useGPUColumns = (props: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}, [intl, sortOrder, clusterList, loadend, firstLoad]);
|
}, [intl, clusterList, loadend, firstLoad]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useGPUColumns;
|
export default useGPUColumns;
|
||||||
|
|||||||
@@ -239,10 +239,7 @@ const useWorkerColumns = ({
|
|||||||
};
|
};
|
||||||
loadend: boolean;
|
loadend: boolean;
|
||||||
firstLoad: boolean;
|
firstLoad: boolean;
|
||||||
sortOrder: {
|
sortOrder: string[];
|
||||||
order?: 'ascend' | 'descend' | null;
|
|
||||||
columnKey?: string;
|
|
||||||
};
|
|
||||||
handleSelect: (action: string, record: ListItem) => void;
|
handleSelect: (action: string, record: ListItem) => void;
|
||||||
}): ColumnsType<ListItem> => {
|
}): ColumnsType<ListItem> => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
@@ -277,11 +274,9 @@ const useWorkerColumns = ({
|
|||||||
title: intl.formatMessage({ id: 'common.table.name' }),
|
title: intl.formatMessage({ id: 'common.table.name' }),
|
||||||
dataIndex: 'name',
|
dataIndex: 'name',
|
||||||
width: 100,
|
width: 100,
|
||||||
sorter: false,
|
sorter: {
|
||||||
sortOrder:
|
multiple: 1
|
||||||
sortOrder.order && sortOrder.columnKey === 'name'
|
},
|
||||||
? sortOrder.order
|
|
||||||
: null,
|
|
||||||
render: (text: string) => (
|
render: (text: string) => (
|
||||||
<AutoTooltip ghost maxWidth={240}>
|
<AutoTooltip ghost maxWidth={240}>
|
||||||
{text}
|
{text}
|
||||||
@@ -306,6 +301,9 @@ const useWorkerColumns = ({
|
|||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'common.table.status' }),
|
title: intl.formatMessage({ id: 'common.table.status' }),
|
||||||
dataIndex: 'state',
|
dataIndex: 'state',
|
||||||
|
sorter: {
|
||||||
|
multiple: 2
|
||||||
|
},
|
||||||
render: (_, record) => (
|
render: (_, record) => (
|
||||||
<StatusTag
|
<StatusTag
|
||||||
maxTooltipWidth={400}
|
maxTooltipWidth={400}
|
||||||
@@ -321,6 +319,9 @@ const useWorkerColumns = ({
|
|||||||
{
|
{
|
||||||
title: 'IP',
|
title: 'IP',
|
||||||
dataIndex: 'ip',
|
dataIndex: 'ip',
|
||||||
|
sorter: {
|
||||||
|
multiple: 3
|
||||||
|
},
|
||||||
render: (text: string, record) => (
|
render: (text: string, record) => (
|
||||||
<AutoTooltip ghost maxWidth={240}>
|
<AutoTooltip ghost maxWidth={240}>
|
||||||
{renderIP(text, record)}
|
{renderIP(text, record)}
|
||||||
@@ -329,7 +330,10 @@ const useWorkerColumns = ({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'CPU',
|
title: 'CPU',
|
||||||
dataIndex: 'cpu',
|
dataIndex: 'status.cpu.utilization_rate',
|
||||||
|
sorter: {
|
||||||
|
multiple: 4
|
||||||
|
},
|
||||||
render: (text: string, record) =>
|
render: (text: string, record) =>
|
||||||
statusAvailable(record) ? (
|
statusAvailable(record) ? (
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
@@ -341,7 +345,10 @@ const useWorkerColumns = ({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'resources.table.memory' }),
|
title: intl.formatMessage({ id: 'resources.table.memory' }),
|
||||||
dataIndex: 'memory',
|
dataIndex: 'status.memory.utilization_rate',
|
||||||
|
sorter: {
|
||||||
|
multiple: 5
|
||||||
|
},
|
||||||
render: (_, record) =>
|
render: (_, record) =>
|
||||||
statusAvailable(record) ? (
|
statusAvailable(record) ? (
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
|
|||||||
@@ -71,12 +71,9 @@ const useUsersColumns = ({
|
|||||||
title: intl.formatMessage({ id: 'common.table.name' }),
|
title: intl.formatMessage({ id: 'common.table.name' }),
|
||||||
dataIndex: 'username',
|
dataIndex: 'username',
|
||||||
key: 'username',
|
key: 'username',
|
||||||
defaultSortOrder: 'descend',
|
sorter: {
|
||||||
sortOrder:
|
multiple: 1
|
||||||
sortOrder.order && sortOrder.columnKey === 'username'
|
},
|
||||||
? sortOrder.order
|
|
||||||
: null,
|
|
||||||
sorter: false,
|
|
||||||
render: (text: string, record: ListItem) => (
|
render: (text: string, record: ListItem) => (
|
||||||
<AutoTooltip ghost style={{ maxWidth: 400 }}>
|
<AutoTooltip ghost style={{ maxWidth: 400 }}>
|
||||||
{text}
|
{text}
|
||||||
@@ -85,8 +82,11 @@ const useUsersColumns = ({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: intl.formatMessage({ id: 'users.table.role' }),
|
title: intl.formatMessage({ id: 'users.table.role' }),
|
||||||
dataIndex: 'role',
|
dataIndex: 'is_admin',
|
||||||
key: 'role',
|
key: 'is_admin',
|
||||||
|
sorter: {
|
||||||
|
multiple: 6
|
||||||
|
},
|
||||||
ellipsis: {
|
ellipsis: {
|
||||||
showTitle: false
|
showTitle: false
|
||||||
},
|
},
|
||||||
@@ -125,6 +125,9 @@ const useUsersColumns = ({
|
|||||||
title: intl.formatMessage({ id: 'users.form.source' }),
|
title: intl.formatMessage({ id: 'users.form.source' }),
|
||||||
dataIndex: 'source',
|
dataIndex: 'source',
|
||||||
key: 'source',
|
key: 'source',
|
||||||
|
sorter: {
|
||||||
|
multiple: 3
|
||||||
|
},
|
||||||
ellipsis: {
|
ellipsis: {
|
||||||
showTitle: false
|
showTitle: false
|
||||||
},
|
},
|
||||||
@@ -138,6 +141,9 @@ const useUsersColumns = ({
|
|||||||
title: intl.formatMessage({ id: 'users.table.status' }),
|
title: intl.formatMessage({ id: 'users.table.status' }),
|
||||||
dataIndex: 'is_active',
|
dataIndex: 'is_active',
|
||||||
key: 'is_active',
|
key: 'is_active',
|
||||||
|
sorter: {
|
||||||
|
multiple: 4
|
||||||
|
},
|
||||||
ellipsis: {
|
ellipsis: {
|
||||||
showTitle: false
|
showTitle: false
|
||||||
},
|
},
|
||||||
@@ -185,11 +191,9 @@ const useUsersColumns = ({
|
|||||||
key: 'created_at',
|
key: 'created_at',
|
||||||
defaultSortOrder: 'descend',
|
defaultSortOrder: 'descend',
|
||||||
showSorterTooltip: false,
|
showSorterTooltip: false,
|
||||||
sortOrder:
|
sorter: {
|
||||||
sortOrder.order && sortOrder.columnKey === 'created_at'
|
multiple: 5
|
||||||
? sortOrder.order
|
},
|
||||||
: null,
|
|
||||||
sorter: false,
|
|
||||||
ellipsis: {
|
ellipsis: {
|
||||||
showTitle: false
|
showTitle: false
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import DeleteModal from '@/components/delete-modal';
|
|||||||
import IconFont from '@/components/icon-font';
|
import IconFont from '@/components/icon-font';
|
||||||
import { FilterBar } from '@/components/page-tools';
|
import { FilterBar } from '@/components/page-tools';
|
||||||
import { PageAction } from '@/config';
|
import { PageAction } from '@/config';
|
||||||
|
import { TABLE_SORT_DIRECTIONS } from '@/config/settings';
|
||||||
import type { PageActionType } from '@/config/types';
|
import type { PageActionType } from '@/config/types';
|
||||||
import useTableFetch from '@/hooks/use-table-fetch';
|
import useTableFetch from '@/hooks/use-table-fetch';
|
||||||
import { useIntl, useModel } from '@umijs/max';
|
import { useIntl, useModel } from '@umijs/max';
|
||||||
@@ -38,7 +39,10 @@ const Users: React.FC = () => {
|
|||||||
} = useTableFetch<ListItem>({
|
} = useTableFetch<ListItem>({
|
||||||
fetchAPI: queryUsersList,
|
fetchAPI: queryUsersList,
|
||||||
deleteAPI: deleteUser,
|
deleteAPI: deleteUser,
|
||||||
contentForDelete: 'users.table.user'
|
contentForDelete: 'users.table.user',
|
||||||
|
defaultQueryParams: {
|
||||||
|
sort_by: '-created_at'
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const { initialState } = useModel('@@initialState') || {};
|
const { initialState } = useModel('@@initialState') || {};
|
||||||
@@ -188,7 +192,7 @@ const Users: React.FC = () => {
|
|||||||
dataSource={dataList}
|
dataSource={dataList}
|
||||||
rowSelection={rowSelection}
|
rowSelection={rowSelection}
|
||||||
loading={dataSource.loading}
|
loading={dataSource.loading}
|
||||||
sortDirections={['ascend', 'descend', 'ascend']}
|
sortDirections={TABLE_SORT_DIRECTIONS}
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
onChange={handleTableChange}
|
onChange={handleTableChange}
|
||||||
pagination={{
|
pagination={{
|
||||||
|
|||||||
Reference in New Issue
Block a user