chore: replace components with core-ui, upgrade eslint
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import SealSelect from '@/components/seal-form/seal-select';
|
||||
import { Select as SealSelect } from '@gpustack/core-ui';
|
||||
import React from 'react';
|
||||
import { categoryConfig } from './model-tag';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import IconFont from '@/components/icon-font';
|
||||
import { IconFont } from '@gpustack/core-ui';
|
||||
import { Collapse, CollapseProps } from 'antd';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import OverlayScroller from '@/components/overlay-scroller';
|
||||
import {
|
||||
readColumnSettings,
|
||||
writeColumnSettings
|
||||
} from '@/utils/localstore/index';
|
||||
import { SettingOutlined } from '@ant-design/icons';
|
||||
import { OverlayScroller } from '@gpustack/core-ui';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button, Checkbox, Col, Popover, Row, Tooltip } from 'antd';
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
import CopyButton from '@/components/copy-button';
|
||||
import EditorWrap from '@/components/editor-wrap';
|
||||
import HighlightCode from '@/components/highlight-code';
|
||||
import SegmentLine from '@/components/segment-line';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
interface ViewerProps {
|
||||
code: string;
|
||||
copyText?: string;
|
||||
options?: Global.BaseOption<string>[];
|
||||
defaultValue?: string;
|
||||
headerHeight?: number;
|
||||
showTitle?: boolean;
|
||||
height?: number;
|
||||
lang?: string;
|
||||
onChange?: (value: string | number) => void;
|
||||
}
|
||||
|
||||
const Header = styled.div`
|
||||
width: 100%;
|
||||
padding-inline: 12px 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
background-color: var(--color-editor-header-bg);
|
||||
`;
|
||||
|
||||
const CommandViewer: React.FC<ViewerProps> = (props) => {
|
||||
const {
|
||||
code,
|
||||
copyText = '',
|
||||
defaultValue,
|
||||
options = [],
|
||||
headerHeight = 40,
|
||||
height = 380,
|
||||
showTitle = false,
|
||||
lang,
|
||||
onChange
|
||||
} = props || {};
|
||||
|
||||
const [value, setValue] = React.useState<string>(defaultValue || '');
|
||||
|
||||
const handlOnChange = (value: string | number) => {
|
||||
setValue(value as string);
|
||||
onChange?.(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<EditorWrap
|
||||
header={
|
||||
<Header>
|
||||
<SegmentLine
|
||||
height={headerHeight}
|
||||
defaultValue={defaultValue}
|
||||
value={value}
|
||||
size="small"
|
||||
options={options}
|
||||
showTitle={showTitle}
|
||||
onChange={handlOnChange}
|
||||
></SegmentLine>
|
||||
|
||||
<CopyButton
|
||||
text={copyText || code}
|
||||
size="small"
|
||||
style={{
|
||||
color: 'rgba(255,255,255,.7)'
|
||||
}}
|
||||
/>
|
||||
</Header>
|
||||
}
|
||||
>
|
||||
<HighlightCode
|
||||
height={height}
|
||||
theme="dark"
|
||||
code={code}
|
||||
lang={lang || value}
|
||||
copyable={false}
|
||||
></HighlightCode>
|
||||
</EditorWrap>
|
||||
);
|
||||
};
|
||||
|
||||
export default CommandViewer;
|
||||
@@ -1,4 +1,4 @@
|
||||
import IconFont from '@/components/icon-font';
|
||||
import { IconFont } from '@gpustack/core-ui';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button } from 'antd';
|
||||
import React from 'react';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import OverlayScroller from '@/components/overlay-scroller';
|
||||
import { CloseOutlined } from '@ant-design/icons';
|
||||
import { OverlayScroller } from '@gpustack/core-ui';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button, Form } from 'antd';
|
||||
import classNames from 'classnames';
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import ModalFooter from '@/components/modal-footer';
|
||||
import GSDrawer from '@/components/scroller-modal/gs-drawer';
|
||||
import ColumnWrapper from '@/pages/_components/column-wrapper';
|
||||
import { ColumnWrapper, GSDrawer, ModalFooter } from '@gpustack/core-ui';
|
||||
import { Tag } from 'antd';
|
||||
import React from 'react';
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import IconFont from '@/components/icon-font';
|
||||
import {
|
||||
AudioOutlined,
|
||||
PictureOutlined,
|
||||
WechatWorkOutlined
|
||||
} from '@ant-design/icons';
|
||||
import { IconFont } from '@gpustack/core-ui';
|
||||
import { Tag } from 'antd';
|
||||
import { modelCategoriesMap } from '../llmodels/config';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import IconFont from '@/components/icon-font';
|
||||
import { IconFont } from '@gpustack/core-ui';
|
||||
import { Breadcrumb, type BreadcrumbProps } from 'antd';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import AutoTooltip from '@/components/auto-tooltip';
|
||||
import { AutoTooltip } from '@gpustack/core-ui';
|
||||
import React from 'react';
|
||||
import pillButtonCss from './styles.less';
|
||||
|
||||
type Option = {
|
||||
label: string;
|
||||
value: string | number | null;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import SegmentLine from '@/components/segment-line';
|
||||
import { SegmentLine } from '@gpustack/core-ui';
|
||||
import { useMemoizedFn } from 'ahooks';
|
||||
import _ from 'lodash';
|
||||
import React, { forwardRef, useImperativeHandle } from 'react';
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
import { SearchOutlined } from '@ant-design/icons';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button, Checkbox, Empty, Input } from 'antd';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import List from './list';
|
||||
import SelectedList from './selected-list';
|
||||
|
||||
const PanelWrapper = styled.div<{ $maxHeight?: number; $leftWidth?: number }>`
|
||||
border: 1px solid var(--ant-color-border);
|
||||
border-radius: var(--ant-border-radius);
|
||||
overflow-y: auto;
|
||||
max-height: ${({ $maxHeight }) =>
|
||||
$maxHeight ? `${$maxHeight + 2}px` : 'auto'};
|
||||
`;
|
||||
|
||||
const Left = styled.div`
|
||||
padding: 0;
|
||||
`;
|
||||
const Right = styled.div``;
|
||||
|
||||
const Header = styled.div`
|
||||
padding: 8px 12px 8px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid var(--ant-color-split);
|
||||
background-color: var(--ant-color-fill-alter);
|
||||
`;
|
||||
|
||||
interface SelectPanelProps {
|
||||
searchPlaceholder?: string;
|
||||
height?: number;
|
||||
leftWidth?: number;
|
||||
options: Array<{ key: string; title: string }>;
|
||||
selectedKeys: string[];
|
||||
notFoundContent?: React.ReactNode;
|
||||
onSelectChange: (selectedKeys: string[]) => void;
|
||||
styles?: {
|
||||
container?: React.CSSProperties;
|
||||
left?: React.CSSProperties;
|
||||
right?: React.CSSProperties;
|
||||
header?: React.CSSProperties;
|
||||
};
|
||||
}
|
||||
|
||||
const SelectPanel: React.FC<SelectPanelProps> = ({
|
||||
height = 300,
|
||||
leftWidth = 260,
|
||||
options,
|
||||
selectedKeys,
|
||||
searchPlaceholder,
|
||||
notFoundContent,
|
||||
styles,
|
||||
onSelectChange
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const [indeterminate, setIndeterminate] = React.useState(false);
|
||||
const [checkAll, setCheckAll] = React.useState(false);
|
||||
const [searchText, setSearchText] = useState('');
|
||||
|
||||
const showOptions = useMemo(() => {
|
||||
return options.filter((item) =>
|
||||
item.title.toLowerCase().includes(searchText.toLowerCase())
|
||||
);
|
||||
}, [options, searchText]);
|
||||
|
||||
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchText(e.target.value);
|
||||
};
|
||||
|
||||
const handleOnUnselect = (
|
||||
key: string,
|
||||
newSelectedKeys: { key: string; title: string }[]
|
||||
) => {
|
||||
onSelectChange(newSelectedKeys.map((item) => item.key));
|
||||
};
|
||||
|
||||
const handleCheckAllChange = (e: any) => {
|
||||
const checked = e.target.checked;
|
||||
setCheckAll(checked);
|
||||
setIndeterminate(false);
|
||||
if (checked) {
|
||||
const allKeys = options
|
||||
.filter((item) =>
|
||||
item.title.toLowerCase().includes(searchText.toLowerCase())
|
||||
)
|
||||
.map((item) => item.key);
|
||||
onSelectChange(Array.from(new Set([...selectedKeys, ...allKeys])));
|
||||
} else {
|
||||
const filteredKeys = options
|
||||
.filter((item) =>
|
||||
item.title.toLowerCase().includes(searchText.toLowerCase())
|
||||
)
|
||||
.map((item) => item.key);
|
||||
const newSelectedKeys = selectedKeys.filter(
|
||||
(key) => !filteredKeys.includes(key)
|
||||
);
|
||||
onSelectChange(newSelectedKeys);
|
||||
}
|
||||
};
|
||||
|
||||
const updateCheckStatus = (newSelectedKeys: string[]) => {
|
||||
if (options.length === 0) {
|
||||
setIndeterminate(false);
|
||||
setCheckAll(false);
|
||||
return;
|
||||
}
|
||||
const filteredOptions = options.filter((item) =>
|
||||
item.title.toLowerCase().includes(searchText.toLowerCase())
|
||||
);
|
||||
const filteredKeys = filteredOptions.map((item) => item.key);
|
||||
const selectedFilteredKeys = newSelectedKeys.filter((key) =>
|
||||
filteredKeys.includes(key)
|
||||
);
|
||||
setIndeterminate(
|
||||
selectedFilteredKeys.length > 0 &&
|
||||
selectedFilteredKeys.length < filteredKeys.length
|
||||
);
|
||||
setCheckAll(selectedFilteredKeys.length === filteredKeys.length);
|
||||
};
|
||||
|
||||
const handleSelectChange = (newSelectedKeys: string[]) => {
|
||||
onSelectChange(newSelectedKeys);
|
||||
updateCheckStatus(newSelectedKeys);
|
||||
};
|
||||
|
||||
const handleClearSelection = () => {
|
||||
onSelectChange([]);
|
||||
setCheckAll(false);
|
||||
setIndeterminate(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
updateCheckStatus(selectedKeys);
|
||||
}, [selectedKeys, options]);
|
||||
|
||||
const renderRight = () => {
|
||||
return (
|
||||
<Right>
|
||||
<Header>
|
||||
<span>({selectedKeys.length}) selected</span>
|
||||
<Button type="text" size="small" onClick={handleClearSelection}>
|
||||
Clear
|
||||
</Button>
|
||||
</Header>
|
||||
<SelectedList
|
||||
maxHeight={height - 50}
|
||||
selectedList={options.filter((item) =>
|
||||
selectedKeys.includes(item.key)
|
||||
)}
|
||||
onUnselect={handleOnUnselect}
|
||||
/>
|
||||
</Right>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<PanelWrapper
|
||||
$maxHeight={height}
|
||||
$leftWidth={leftWidth}
|
||||
style={styles?.container}
|
||||
>
|
||||
<Left>
|
||||
<Header style={styles?.header}>
|
||||
<span
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 8,
|
||||
color: 'var(--ant-color-text-tertiary)'
|
||||
}}
|
||||
>
|
||||
<Checkbox
|
||||
checked={checkAll}
|
||||
indeterminate={indeterminate}
|
||||
onChange={handleCheckAllChange}
|
||||
></Checkbox>
|
||||
<span>
|
||||
{intl.formatMessage(
|
||||
{ id: 'common.select.count' },
|
||||
{ count: selectedKeys.length }
|
||||
)}
|
||||
</span>
|
||||
</span>
|
||||
<Input
|
||||
prefix={
|
||||
<SearchOutlined
|
||||
style={{ color: 'var(--ant-color-text-quaternary)' }}
|
||||
/>
|
||||
}
|
||||
size="small"
|
||||
allowClear
|
||||
status={'null' as any}
|
||||
placeholder={searchPlaceholder}
|
||||
style={{
|
||||
width: 300,
|
||||
height: 32,
|
||||
borderRadius: 4,
|
||||
backgroundColor: 'var(--ant-color-bg-container) !important'
|
||||
}}
|
||||
onChange={handleSearch}
|
||||
/>
|
||||
</Header>
|
||||
{showOptions.length > 0 ? (
|
||||
<List
|
||||
maxHeight={height - 50}
|
||||
dataList={showOptions}
|
||||
selectedKeys={selectedKeys}
|
||||
onSelectChange={handleSelectChange}
|
||||
/>
|
||||
) : (
|
||||
<Empty
|
||||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||
description={notFoundContent}
|
||||
></Empty>
|
||||
)}
|
||||
</Left>
|
||||
</PanelWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectPanel;
|
||||
@@ -1,70 +0,0 @@
|
||||
import { OverlayScroller } from '@/components/overlay-scroller';
|
||||
import { Checkbox } from 'antd';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import AutoTooltip from '../../../components/auto-tooltip';
|
||||
|
||||
interface ListProps {
|
||||
maxHeight?: number;
|
||||
dataList: Array<{ key: string; title: string }>;
|
||||
selectedKeys: string[];
|
||||
renderTitle?: (item: { key: string; title: string }) => React.ReactNode;
|
||||
onSelectChange: (selectedKeys: string[]) => void;
|
||||
}
|
||||
|
||||
const UL = styled.ul`
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
`;
|
||||
|
||||
const LI = styled.li<{ selected: boolean }>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 5px 12px;
|
||||
cursor: pointer;
|
||||
border-radius: 2px;
|
||||
gap: 8px;
|
||||
&:hover {
|
||||
background-color: var(--ant-control-item-bg-hover);
|
||||
}
|
||||
`;
|
||||
|
||||
const List: React.FC<ListProps> = ({
|
||||
maxHeight,
|
||||
dataList,
|
||||
selectedKeys,
|
||||
onSelectChange,
|
||||
renderTitle
|
||||
}) => {
|
||||
const handleClickItem = (item: { key: string; title: string }) => {
|
||||
const itemKey = item.key;
|
||||
const newSelectedKeys = selectedKeys.includes(itemKey)
|
||||
? selectedKeys.filter((key) => key !== itemKey)
|
||||
: [...selectedKeys, itemKey];
|
||||
onSelectChange(newSelectedKeys);
|
||||
};
|
||||
|
||||
return (
|
||||
<OverlayScroller style={{ paddingInline: 0 }} maxHeight={maxHeight}>
|
||||
<UL>
|
||||
{dataList.map((item) => (
|
||||
<LI
|
||||
key={item.key}
|
||||
selected={selectedKeys.includes(item.key)}
|
||||
onClick={() => handleClickItem(item)}
|
||||
>
|
||||
<Checkbox checked={selectedKeys.includes(item.key)}></Checkbox>
|
||||
{renderTitle ? (
|
||||
renderTitle(item)
|
||||
) : (
|
||||
<AutoTooltip ghost>{item.title}</AutoTooltip>
|
||||
)}
|
||||
</LI>
|
||||
))}
|
||||
</UL>
|
||||
</OverlayScroller>
|
||||
);
|
||||
};
|
||||
|
||||
export default List;
|
||||
@@ -1,60 +0,0 @@
|
||||
import AutoTooltip from '@/components/auto-tooltip';
|
||||
import { OverlayScroller } from '@/components/overlay-scroller';
|
||||
import { Tag } from 'antd';
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const TagInner = styled(Tag)`
|
||||
border-radius: 12px;
|
||||
margin: 0;
|
||||
`;
|
||||
|
||||
const Content = styled.div`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
padding: 8px 0;
|
||||
`;
|
||||
|
||||
interface SelectedProps {
|
||||
maxHeight?: number;
|
||||
selectedList: { key: string; title: string }[];
|
||||
onUnselect: (
|
||||
key: string,
|
||||
newSelectedKeys: { key: string; title: string }[]
|
||||
) => void;
|
||||
}
|
||||
|
||||
const SelectedList: React.FC<SelectedProps> = ({
|
||||
maxHeight,
|
||||
selectedList,
|
||||
onUnselect
|
||||
}) => {
|
||||
const handleOnUnselect = (key: string) => {
|
||||
const newSelectedKeys = selectedList.filter((item) => item.key !== key);
|
||||
onUnselect(key, newSelectedKeys);
|
||||
};
|
||||
|
||||
return (
|
||||
<OverlayScroller maxHeight={maxHeight}>
|
||||
<Content>
|
||||
{selectedList.map((item) => (
|
||||
<AutoTooltip
|
||||
title={item.title}
|
||||
key={item.key}
|
||||
maxWidth={200}
|
||||
onClose={(e) => {
|
||||
e.preventDefault();
|
||||
handleOnUnselect(item.key);
|
||||
}}
|
||||
closable
|
||||
>
|
||||
{item.title}
|
||||
</AutoTooltip>
|
||||
))}
|
||||
</Content>
|
||||
</OverlayScroller>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectedList;
|
||||
@@ -1,5 +1,5 @@
|
||||
import XTerminal from '@/components/x-terminal';
|
||||
import { CloseOutlined } from '@ant-design/icons';
|
||||
import { XTerminal } from '@gpustack/core-ui';
|
||||
import { Button, Tabs } from 'antd';
|
||||
import { throttle } from 'lodash';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import EditorWrap from '@/components/editor-wrap';
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { EditorWrap } from '@gpustack/core-ui';
|
||||
import Editor, { loader } from '@monaco-editor/react';
|
||||
import * as monaco from 'monaco-editor';
|
||||
import { yamlDefaults } from 'monaco-yaml';
|
||||
|
||||
Reference in New Issue
Block a user