From b05595f84b61d68990661911a1a0c1aa594cc629 Mon Sep 17 00:00:00 2001 From: jialin Date: Tue, 16 Jul 2024 18:12:28 +0800 Subject: [PATCH] chore: custom table sort --- .../seal-table/components/table-header.tsx | 45 +++++++++++++++++-- src/components/seal-table/index.tsx | 18 +++++++- src/components/seal-table/styles/header.less | 41 +++++++++++++++++ src/components/seal-table/types.ts | 9 ++++ src/global.less | 7 ++- src/pages/llmodels/components/table-list.tsx | 12 ++--- .../playground/components/view-code-modal.tsx | 11 ++--- src/pages/resources/components/gpus.tsx | 2 +- 8 files changed, 127 insertions(+), 18 deletions(-) diff --git a/src/components/seal-table/components/table-header.tsx b/src/components/seal-table/components/table-header.tsx index 61d18b3f..7356b780 100644 --- a/src/components/seal-table/components/table-header.tsx +++ b/src/components/seal-table/components/table-header.tsx @@ -1,10 +1,30 @@ +import { CaretDownOutlined, CaretUpOutlined } from '@ant-design/icons'; import classNames from 'classnames'; import React from 'react'; import '../styles/header.less'; import { TableHeaderProps } from '../types'; const TableHeader: React.FC = (props) => { - const { title, style, align, firstCell, lastCell } = props; + const { + title, + style, + align, + firstCell, + lastCell, + sortOrder, + onSort, + sorter, + dataIndex, + defaultSortOrder + } = props; + + const handleOnSort = () => { + if (sortOrder === 'ascend') { + onSort?.(dataIndex, 'descend'); + } else { + onSort?.(dataIndex, 'ascend'); + } + }; return (
= (props) => { 'table-header-center': align === 'center', 'table-header-right': align === 'right', 'table-header-first': firstCell, - 'table-header-last': lastCell + 'table-header-last': lastCell, + 'table-header-sorter': sorter })} > -
{title}
+ {sorter ? ( + + {title} + + + + + + ) : ( +
{title}
+ )}
); }; diff --git a/src/components/seal-table/index.tsx b/src/components/seal-table/index.tsx index 08af924f..25a15aa1 100644 --- a/src/components/seal-table/index.tsx +++ b/src/components/seal-table/index.tsx @@ -24,6 +24,7 @@ const SealTable: React.FC = ( rowKey, childParentKey, onExpand, + onSort, expandedRowKeys, loading, expandable, @@ -117,12 +118,25 @@ const SealTable: React.FC = ( {React.Children.map(props.children, (child, i) => { const { props: columnProps } = child as any; - const { title, align, span, headerStyle } = - columnProps as SealColumnProps; + const { + title, + dataIndex, + align, + span, + headerStyle, + sortOrder, + sorter, + defaultSortOrder + } = columnProps as SealColumnProps; if (React.isValidElement(child)) { return ( void; children?: React.ReactNode; title: string; style?: React.CSSProperties; @@ -34,6 +42,7 @@ export interface SealTableProps { pollingChildren?: boolean; watchChildren?: boolean; loading?: boolean; + onSort?: (dataIndex: string, order: 'ascend' | 'descend') => void; onExpand?: (expanded: boolean, record: any, rowKey: any) => void; renderChildren?: (data: any) => React.ReactNode; loadChildren?: (record: any) => Promise; diff --git a/src/global.less b/src/global.less index d8d3b688..ef72aee6 100644 --- a/src/global.less +++ b/src/global.less @@ -32,7 +32,7 @@ html { --ant-color-fill-secondary: rgba(0, 0, 0, 6%); --table-td-radius: 8px; --checkbox-border-radius: 4px; - --ant-table-cell-padding-inline: 8px; + --ant-table-cell-padding-inline: 16px; --ant-table-cell-padding-block: 8px; --ant-table-header-border-radius: 8px; --ant-table-header-split-color: #f0f0f0; @@ -149,6 +149,11 @@ body { display: none; } + .ant-slider:hover .ant-slider-handle::after { + box-shadow: 0 0 0 var(--ant-slider-handle-line-width) + var(--ant-slider-track-hover-bg); + } + .ant-select-selector { .ant-select-selection-item { font-weight: var(--font-weight-normal); diff --git a/src/pages/llmodels/components/table-list.tsx b/src/pages/llmodels/components/table-list.tsx index 6d5d854a..aadf162e 100644 --- a/src/pages/llmodels/components/table-list.tsx +++ b/src/pages/llmodels/components/table-list.tsx @@ -110,9 +110,9 @@ const Models: React.FC = ({ }); }; - const handleTableChange = (pagination: any, filters: any, sorter: any) => { - console.log('handleTableChange=======', pagination, filters, sorter); - setSortOrder(sorter.order); + const handleOnSort = (dataIndex: string, order: any) => { + console.log('handleTableChange=======', dataIndex, order); + setSortOrder(order); }; const handleAddModal = () => { @@ -326,7 +326,7 @@ const Models: React.FC = ({ rowKey="id" childParentKey="model_id" expandable={true} - onChange={handleTableChange} + onSort={handleOnSort} pollingChildren={false} watchChildren={true} loadChildren={getModelInstances} @@ -384,8 +384,7 @@ const Models: React.FC = ({ key="created_at" defaultSortOrder="descend" sortOrder={sortOrder} - showSorterTooltip={false} - sorter={true} + sorter={false} render={(text, row) => { return dayjs(text).format('YYYY-MM-DD HH:mm:ss'); }} @@ -394,6 +393,7 @@ const Models: React.FC = ({ span={4} title={intl.formatMessage({ id: 'common.table.operation' })} key="operation" + dataIndex="operation" render={(text, record) => { return !record.transition ? ( = (props) => { const [codeValue, setCodeValue] = useState(''); const [lang, setLang] = useState('shell'); - const BaseURL = `${window.location.origin}/v1-openai/chat/completions`; + const BaseURL = `${window.location.origin}/v1-openai`; const langOptions = [ { label: 'Curl', value: 'shell' }, @@ -69,14 +69,14 @@ const ViewCodeModal: React.FC = (props) => { const systemList = systemMessage ? [{ role: 'system', content: systemMessage }] : []; - const code = `import OpenAI from "openai";\nconst openai = new OpenAI();\n\nconst baseURL = "${BaseURL}"\n\nasync function main(){\nconst params = ${JSON.stringify( + const code = `const OpenAI = require("openai");\n\nconst openai = new OpenAI({\n"apiKey": $\{GUPSTACK_API_KEY},\n"baseURL": "${BaseURL}"\n});\n\n\nasync function main(){\nconst params = ${JSON.stringify( { ...parameters, messages: [...systemList, ...messageList] }, null, 2 - )};\nconst chatCompletion = await openai.chat.completions.create(params);\nfor await (const chunk of chatCompletion) {\n process.stdout.write(chunk.choices[0]?.delta?.content || '');\n}\n}\nmain();`; + )};\nconst chatCompletion = await openai.chat.completions.create(params);\nfor await (const chunk of chatCompletion) {\n process.stdout.write(chunk.choices[0]?.message?.content || '');\n}\n}\nmain();`; setCodeValue(code); } else if (lang === 'python') { const formattedParams = _.keys(parameters).reduce( @@ -95,7 +95,7 @@ const ViewCodeModal: React.FC = (props) => { const systemList = systemMessage ? [{ role: 'system', content: systemMessage }] : []; - const code = `from openai import OpenAI\nclient = OpenAI()\n\nbaseURL = ${BaseURL}\n\ncompletion = client.chat.completions.create(\n${formattedParams} messages=${JSON.stringify([...systemList, ...messageList], null, 2)})\nprint(completion.choices[0].message)`; + const code = `from openai import OpenAI\n\nbaseURL = ${BaseURL}\n\nclient = OpenAI(\nbase_url=baseURL, \napi_key="$\{GUPSTACK_API_KEY}"\n)\n\ncompletion = client.chat.completions.create(\n${formattedParams} messages=${JSON.stringify([...systemList, ...messageList], null, 2)})\nprint(completion.choices[0].message.content)`; setCodeValue(code); } formatCode(); @@ -118,9 +118,10 @@ const ViewCodeModal: React.FC = (props) => { minimap: { enabled: false }, + readOnly: true, formatOnType: true, formatOnPaste: true, - fontWeight: '700', + fontWeight: 700, scrollbar: { verticalSliderSize: 8 } diff --git a/src/pages/resources/components/gpus.tsx b/src/pages/resources/components/gpus.tsx index c4011e0f..6270761e 100644 --- a/src/pages/resources/components/gpus.tsx +++ b/src/pages/resources/components/gpus.tsx @@ -137,7 +137,7 @@ const GPUList: React.FC = () => { dataIndex="temperature" key="Temperature" render={(text, record: GPUDeviceItem) => { - return {_.round(text, 1)}; + return {text ? _.round(text, 1) : '-'}; }} />