Browse Source

Merge remote-tracking branch 'origin/dev' into dev

dev-DXTZYK
chenzhihang 1 year ago
parent
commit
41a90e0672
21 changed files with 209 additions and 133 deletions
  1. +3
    -3
      react-ui/src/components/ParameterSelect/config.tsx
  2. +3
    -0
      react-ui/src/global.less
  3. +22
    -26
      react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.less
  4. +11
    -7
      react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.tsx
  5. +6
    -1
      react-ui/src/pages/Dataset/components/AddDatasetModal/index.tsx
  6. +6
    -1
      react-ui/src/pages/Dataset/components/AddModelModal/index.tsx
  7. +7
    -2
      react-ui/src/pages/Dataset/components/AddVersionModal/index.tsx
  8. +2
    -0
      react-ui/src/pages/Dataset/components/ResourceInfo/index.less
  9. +6
    -1
      react-ui/src/pages/Dataset/components/ResourceVersion/index.tsx
  10. +9
    -1
      react-ui/src/pages/Dataset/config.tsx
  11. +12
    -6
      react-ui/src/pages/Experiment/components/ExportModelModal/index.tsx
  12. +30
    -42
      react-ui/src/pages/Pipeline/components/CodeConfigItem/index.less
  13. +12
    -7
      react-ui/src/pages/Pipeline/components/CodeConfigItem/index.tsx
  14. +32
    -7
      react-ui/src/pages/Pipeline/components/CodeSelectorModal/index.less
  15. +7
    -4
      react-ui/src/pages/Pipeline/components/CodeSelectorModal/index.tsx
  16. +2
    -0
      react-ui/src/pages/Pipeline/components/ResourceSelectorModal/index.less
  17. +1
    -1
      react-ui/src/pages/Workspace/components/UserSpace/index.less
  18. +31
    -13
      react-ui/src/requestConfig.ts
  19. +0
    -8
      react-ui/src/services/dataset/index.js
  20. +3
    -2
      react-ui/src/services/experiment/index.js
  21. +4
    -1
      react-ui/src/styles/theme.less

+ 3
- 3
react-ui/src/components/ParameterSelect/config.tsx View File

@@ -17,7 +17,7 @@ const filterResourceStandard: SelectProps<string, ComputingResource>['filterOpti
const convertId = (item: any) => ({ const convertId = (item: any) => ({
...item, ...item,
id: JSON.stringify({ id: JSON.stringify({
id: item.id,
id: `${item.id}`,
name: item.name, name: item.name,
identifier: item.identifier, identifier: item.identifier,
owner: item.owner, owner: item.owner,
@@ -37,7 +37,7 @@ export const paramSelectConfig: Record<string, SelectPropsConfig> = {
const res = await getDatasetList({ const res = await getDatasetList({
page: 0, page: 0,
size: 1000, size: 1000,
available_range: 0,
is_public: false,
}); });
return res?.data?.content?.map(convertId) ?? []; return res?.data?.content?.map(convertId) ?? [];
}, },
@@ -52,7 +52,7 @@ export const paramSelectConfig: Record<string, SelectPropsConfig> = {
const res = await getModelList({ const res = await getModelList({
page: 0, page: 0,
size: 1000, size: 1000,
available_range: 0,
is_public: false,
}); });
return res?.data?.content?.map(convertId) ?? []; return res?.data?.content?.map(convertId) ?? [];
}, },


+ 3
- 0
react-ui/src/global.less View File

@@ -101,15 +101,18 @@ body {


::-webkit-scrollbar { ::-webkit-scrollbar {
width: 8px; width: 8px;
height: 8px;
background: transparent; background: transparent;
} }
::-webkit-scrollbar-thumb { ::-webkit-scrollbar-thumb {
width: 8px; width: 8px;
height: 8px;
background: rgba(0, 0, 0, 0.5); background: rgba(0, 0, 0, 0.5);
border-radius: 99px; border-radius: 99px;
} }
::-webkit-scrollbar-track { ::-webkit-scrollbar-track {
width: 8px; width: 8px;
height: 8px;
background: transparent; background: transparent;
} }
ul, ul,


+ 22
- 26
react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.less View File

@@ -14,35 +14,43 @@
} }


&__name { &__name {
position: relative;
display: inline-block;
height: 24px;
margin: 0 10px 0 0 !important;
margin-right: 10px;
margin-bottom: 0 !important;
color: @text-color; color: @text-color;
font-size: 16px; font-size: 16px;
} }


&__tag { &__tag {
padding: 4px;
color: @primary-color;
padding: 2px 11px;
font-size: 12px; font-size: 12px;
background-color: .addAlpha(@primary-color, 0.1) [];
border-radius: 4px;
border-radius: 1000px;

&--public {
color: @primary-color;
background-color: .addAlpha(@primary-color, 0.08) [];
border-color: .addAlpha(@primary-color, 0.5) [];
}

&--private {
color: @warning-color;
background-color: .addAlpha(@warning-color, 0.08) [];
border-color: .addAlpha(@warning-color, 0.5) [];
}
} }


&__url { &__url {
margin-bottom: 10px;
color: @text-color-secondary; color: @text-color-secondary;
font-size: 14px; font-size: 14px;
} }


&__description {
height: 44px;
&__branch {
margin-bottom: 20px; margin-bottom: 20px;
color: @text-color-secondary;
color: @text-color-tertiary;
font-size: 14px; font-size: 14px;
.multiLine(2);
} }


&__user,
&__time { &__time {
display: flex; display: flex;
flex: 0 1 content; flex: 0 1 content;
@@ -55,21 +63,9 @@
&:hover { &:hover {
border-color: @primary-color; border-color: @primary-color;
box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.1); box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.1);

.resource-item__name {
color: @primary-color;
}
} }
}


.resource-item__name {
&::after {
position: absolute;
top: 14px;
left: 0;
width: 100%;
height: 6px;
background: linear-gradient(to right, rgba(22, 100, 255, 0.3) 0, rgba(22, 100, 255, 0) 100%);
content: '';
&:hover &__name {
color: @primary-color;
} }
} }

+ 11
- 7
react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.tsx View File

@@ -5,6 +5,7 @@ import { AvailableRange } from '@/enums';
import { type CodeConfigData } from '@/pages/CodeConfig/List'; import { type CodeConfigData } from '@/pages/CodeConfig/List';
import { formatDate } from '@/utils/date'; import { formatDate } from '@/utils/date';
import { Button, Flex, Typography } from 'antd'; import { Button, Flex, Typography } from 'antd';
import classNames from 'classnames';
import styles from './index.less'; import styles from './index.less';


type CodeConfigItemProps = { type CodeConfigItemProps = {
@@ -24,10 +25,16 @@ function CodeConfigItem({ item, onClick, onEdit, onRemove }: CodeConfigItemProps
> >
{item.code_repo_name} {item.code_repo_name}
</Typography.Paragraph> </Typography.Paragraph>
<div className={styles['code-config-item__tag']}>
<div
className={classNames(
styles['code-config-item__tag'],
item.code_repo_vis === AvailableRange.Public
? styles['code-config-item__tag--public']
: styles['code-config-item__tag--private'],
)}
>
{item.code_repo_vis === AvailableRange.Public ? '公开' : '私有'} {item.code_repo_vis === AvailableRange.Public ? '公开' : '私有'}
</div> </div>

<Button <Button
type="text" type="text"
shape="circle" shape="circle"
@@ -54,15 +61,12 @@ function CodeConfigItem({ item, onClick, onEdit, onRemove }: CodeConfigItemProps
<Typography.Paragraph <Typography.Paragraph
className={styles['code-config-item__url']} className={styles['code-config-item__url']}
ellipsis={{ tooltip: item.git_url }} ellipsis={{ tooltip: item.git_url }}
style={{ marginBottom: '8px' }}
> >
{item.git_url} {item.git_url}
</Typography.Paragraph> </Typography.Paragraph>
<div className={styles['code-config-item__url']} style={{ marginBottom: '20px' }}>
{item.git_branch}
</div>
<div className={styles['code-config-item__branch']}>{item.git_branch}</div>
<Flex justify="space-between"> <Flex justify="space-between">
<div className={styles['code-config-item__time']}>
<div className={styles['code-config-item__user']}>
<img <img
style={{ width: '17px', marginRight: '6px' }} style={{ width: '17px', marginRight: '6px' }}
src={creatByImg} src={creatByImg}


+ 6
- 1
react-ui/src/pages/Dataset/components/AddDatasetModal/index.tsx View File

@@ -1,7 +1,7 @@
import { getAccessToken } from '@/access'; import { getAccessToken } from '@/access';
import KFIcon from '@/components/KFIcon'; import KFIcon from '@/components/KFIcon';
import KFModal from '@/components/KFModal'; import KFModal from '@/components/KFModal';
import { CategoryData, ResourceType, resourceConfig } from '@/pages/Dataset/config';
import { CategoryData, DataSource, ResourceType, resourceConfig } from '@/pages/Dataset/config';
import { addDataset } from '@/services/dataset/index.js'; import { addDataset } from '@/services/dataset/index.js';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui';
@@ -67,6 +67,7 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr
if (validateUploadFiles(fileList)) { if (validateUploadFiles(fileList)) {
const params = { const params = {
...omit(formData, ['fileList']), ...omit(formData, ['fileList']),
dataset_source: DataSource.Create,
dataset_version_vos: fileList.map((item) => { dataset_version_vos: fileList.map((item) => {
const data = item.response?.data?.[0] ?? {}; const data = item.response?.data?.[0] ?? {};
return { return {
@@ -120,6 +121,10 @@ function AddDatasetModal({ typeList, tagList, onOk, ...rest }: AddDatasetModalPr
required: true, required: true,
message: '请输入数据集版本', message: '请输入数据集版本',
}, },
{
pattern: /^[a-zA-Z0-9._-]+$/,
message: '版本只支持字母、数字、下划线、点、横杠',
},
{ {
validator: (_rule, value) => { validator: (_rule, value) => {
if (value === 'master') { if (value === 'master') {


+ 6
- 1
react-ui/src/pages/Dataset/components/AddModelModal/index.tsx View File

@@ -1,7 +1,7 @@
import { getAccessToken } from '@/access'; import { getAccessToken } from '@/access';
import KFIcon from '@/components/KFIcon'; import KFIcon from '@/components/KFIcon';
import KFModal from '@/components/KFModal'; import KFModal from '@/components/KFModal';
import { CategoryData, ResourceType, resourceConfig } from '@/pages/Dataset/config';
import { CategoryData, DataSource, ResourceType, resourceConfig } from '@/pages/Dataset/config';
import { addModel } from '@/services/dataset/index.js'; import { addModel } from '@/services/dataset/index.js';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui';
@@ -54,6 +54,7 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps)
if (validateUploadFiles(fileList)) { if (validateUploadFiles(fileList)) {
const params = { const params = {
...omit(formData, ['fileList']), ...omit(formData, ['fileList']),
model_source: DataSource.Create,
model_version_vos: fileList.map((item) => { model_version_vos: fileList.map((item) => {
const data = item.response?.data?.[0] ?? {}; const data = item.response?.data?.[0] ?? {};
return { return {
@@ -105,6 +106,10 @@ function AddModelModal({ typeList, tagList, onOk, ...rest }: AddModelModalProps)
required: true, required: true,
message: '请输入模型版本', message: '请输入模型版本',
}, },
{
pattern: /^[a-zA-Z0-9._-]+$/,
message: '版本只支持字母、数字、下划线、点、横杠',
},
{ {
validator: (_rule, value) => { validator: (_rule, value) => {
if (value === 'master') { if (value === 'master') {


+ 7
- 2
react-ui/src/pages/Dataset/components/AddVersionModal/index.tsx View File

@@ -1,7 +1,7 @@
import { getAccessToken } from '@/access'; import { getAccessToken } from '@/access';
import KFIcon from '@/components/KFIcon'; import KFIcon from '@/components/KFIcon';
import KFModal from '@/components/KFModal'; import KFModal from '@/components/KFModal';
import { ResourceType, resourceConfig } from '@/pages/Dataset/config';
import { DataSource, ResourceType, resourceConfig } from '@/pages/Dataset/config';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui'; import { getFileListFromEvent, validateUploadFiles } from '@/utils/ui';
import { import {
@@ -73,6 +73,7 @@ function AddVersionModal({
identifier, identifier,
[config.filePropKey]: version_vos, [config.filePropKey]: version_vos,
...omit(formData, 'fileList'), ...omit(formData, 'fileList'),
[config.sourceParamKey]: DataSource.Create,
}; };
createDatasetVersion(params); createDatasetVersion(params);
} }
@@ -120,6 +121,10 @@ function AddVersionModal({
required: true, required: true,
message: `请输入${name}版本`, message: `请输入${name}版本`,
}, },
{
pattern: /^[a-zA-Z0-9._-]+$/,
message: '版本只支持字母、数字、下划线、点、横杠',
},
{ {
validator: (_rule, value) => { validator: (_rule, value) => {
if (value === 'master') { if (value === 'master') {
@@ -145,7 +150,7 @@ function AddVersionModal({
<Input.TextArea <Input.TextArea
placeholder="请输入版本描述" placeholder="请输入版本描述"
autoSize={{ minRows: 2, maxRows: 6 }} autoSize={{ minRows: 2, maxRows: 6 }}
maxLength={256}
maxLength={200}
showCount showCount
allowClear allowClear
/> />


+ 2
- 0
react-ui/src/pages/Dataset/components/ResourceInfo/index.less View File

@@ -16,9 +16,11 @@
color: @text-color; color: @text-color;
font-weight: 500; font-weight: 500;
font-size: 20px; font-size: 20px;
.singleLine();
} }


&__tag { &__tag {
flex: none;
padding: 4px 10px; padding: 4px 10px;
color: @primary-color; color: @primary-color;
font-size: 14px; font-size: 14px;


+ 6
- 1
react-ui/src/pages/Dataset/components/ResourceVersion/index.tsx View File

@@ -24,7 +24,12 @@ function ResourceVersion({ resourceType, info }: ResourceVersionProps) {
// 全部导出 // 全部导出
const handleExport = async () => { const handleExport = async () => {
const url = config.downloadAllAction; const url = config.downloadAllAction;
downLoadZip(url, { name: info.name, id: info.id, version: info.version });
downLoadZip(url, {
name: info.name,
id: info.id,
version: info.version,
identifier: info.identifier,
});
}; };


// 单个导出 // 单个导出


+ 9
- 1
react-ui/src/pages/Dataset/config.tsx View File

@@ -21,6 +21,11 @@ export enum ResourceType {
Dataset = 'Dataset', // 数据集 Dataset = 'Dataset', // 数据集
} }


export enum DataSource {
Export = 'export', // 导出
Create = 'add', // 新增
}

type ResourceTypeInfo = { type ResourceTypeInfo = {
getList: (params: any) => Promise<any>; // 获取资源列表 getList: (params: any) => Promise<any>; // 获取资源列表
getVersions: (params: any) => Promise<any>; // 获取版本列表 getVersions: (params: any) => Promise<any>; // 获取版本列表
@@ -32,6 +37,7 @@ type ResourceTypeInfo = {
typeParamKey: 'data_type' | 'model_type'; // 类型参数名称,获取资源列表接口使用 typeParamKey: 'data_type' | 'model_type'; // 类型参数名称,获取资源列表接口使用
tagParamKey: 'data_tag' | 'model_tag'; // 标签参数名称,获取资源列表接口使用 tagParamKey: 'data_tag' | 'model_tag'; // 标签参数名称,获取资源列表接口使用
filePropKey: 'dataset_version_vos' | 'model_version_vos'; // 文件列表属性 filePropKey: 'dataset_version_vos' | 'model_version_vos'; // 文件列表属性
sourceParamKey: 'dataset_source' | 'model_source'; // 来源参数名称
tabItems: TabsProps['items']; // tab 列表 tabItems: TabsProps['items']; // tab 列表
typeTitle: string; // 类型标题 typeTitle: string; // 类型标题
tagTitle: string; // 标签标题 tagTitle: string; // 标签标题
@@ -58,6 +64,7 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = {
typeParamKey: 'data_type', typeParamKey: 'data_type',
tagParamKey: 'data_tag', tagParamKey: 'data_tag',
filePropKey: 'dataset_version_vos', filePropKey: 'dataset_version_vos',
sourceParamKey: 'dataset_source',
tabItems: [ tabItems: [
{ {
key: CommonTabKeys.Public, key: CommonTabKeys.Public,
@@ -80,7 +87,7 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = {
uploadAction: '/api/mmp/newdataset/upload', uploadAction: '/api/mmp/newdataset/upload',
uploadAccept: '.zip,.tgz', uploadAccept: '.zip,.tgz',
downloadAllAction: '/api/mmp/newdataset/downloadAllFiles', downloadAllAction: '/api/mmp/newdataset/downloadAllFiles',
downloadSingleAction: '/api/mmp/newdataset/downloadSinggerFile',
downloadSingleAction: '/api/mmp/newdataset/downloadSingleFile',
}, },
[ResourceType.Model]: { [ResourceType.Model]: {
getList: getModelList, getList: getModelList,
@@ -93,6 +100,7 @@ export const resourceConfig: Record<ResourceType, ResourceTypeInfo> = {
typeParamKey: 'model_type', typeParamKey: 'model_type',
tagParamKey: 'model_tag', tagParamKey: 'model_tag',
filePropKey: 'model_version_vos', filePropKey: 'model_version_vos',
sourceParamKey: 'model_source',
tabItems: [ tabItems: [
{ {
key: CommonTabKeys.Public, key: CommonTabKeys.Public,


+ 12
- 6
react-ui/src/pages/Experiment/components/ExportModelModal/index.tsx View File

@@ -1,6 +1,6 @@
import editExperimentIcon from '@/assets/img/edit-experiment.png'; import editExperimentIcon from '@/assets/img/edit-experiment.png';
import KFModal from '@/components/KFModal'; import KFModal from '@/components/KFModal';
import { type ResourceData } from '@/pages/Dataset/config';
import { ResourceVersionData, type ResourceData } from '@/pages/Dataset/config';
import { import {
addModelVersion, addModelVersion,
exportModelReq, exportModelReq,
@@ -10,6 +10,7 @@ import {
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import { InfoCircleOutlined } from '@ant-design/icons'; import { InfoCircleOutlined } from '@ant-design/icons';
import { Form, Input, ModalProps, Select } from 'antd'; import { Form, Input, ModalProps, Select } from 'antd';
import { pick } from 'lodash';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import styles from './index.less'; import styles from './index.less';


@@ -40,7 +41,7 @@ interface ExportModelModalProps extends Omit<ModalProps, 'onOk'> {
function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) { function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [models, setModels] = useState<ResourceData[]>([]); const [models, setModels] = useState<ResourceData[]>([]);
const [versions, setVersions] = useState<string[]>([]);
const [versions, setVersions] = useState<ResourceVersionData[]>([]);
const [uuid] = useState(Date.now()); const [uuid] = useState(Date.now());


const layout = { const layout = {
@@ -56,8 +57,9 @@ function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) {
const getTooltip = () => { const getTooltip = () => {
const id = form.getFieldValue('models_id'); const id = form.getFieldValue('models_id');
const name = models.find((item) => item.id === id)?.name ?? ''; const name = models.find((item) => item.id === id)?.name ?? '';
const versionNames = versions.map((item: ResourceVersionData) => item.name).join('、');
const tooltip = const tooltip =
versions.length > 0 ? `${name}有以下版本:\n${versions.join('、')}\n注意不能重复` : undefined;
versions.length > 0 ? `${name}有以下版本:\n${versionNames}\n注意不能重复` : undefined;
return tooltip; return tooltip;
}; };


@@ -75,7 +77,7 @@ function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) {
const params = { const params = {
page: 0, page: 0,
size: 1000, size: 1000,
available_range: 0, // 个人
is_public: false, // 个人
}; };
const [res] = await to(getModelList(params)); const [res] = await to(getModelList(params));
if (res && res.data) { if (res && res.data) {
@@ -85,7 +87,11 @@ function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) {


// 获取模型版本列表 // 获取模型版本列表
const getModelVersions = async (id: number) => { const getModelVersions = async (id: number) => {
const [res] = await to(getModelVersionList(id));
const model = models.find((item) => item.id === id);
if (!model) {
return;
}
const [res] = await to(getModelVersionList(pick(model, ['identifier', 'owner'])));
if (res && res.data) { if (res && res.data) {
setVersions(res.data); setVersions(res.data);
} }
@@ -175,7 +181,7 @@ function ExportModelModal({ path, onOk, ...rest }: ExportModelModalProps) {
{ required: true, message: '请输入模型版本' }, { required: true, message: '请输入模型版本' },
{ {
validator: (_, value) => { validator: (_, value) => {
if (value && versions.includes(value)) {
if (value && versions.map((item) => item.name).includes(value)) {
return Promise.reject('模型版本已存在'); return Promise.reject('模型版本已存在');
} else { } else {
return Promise.resolve(); return Promise.resolve();


+ 30
- 42
react-ui/src/pages/Pipeline/components/CodeConfigItem/index.less View File

@@ -1,68 +1,56 @@
.code-config-item { .code-config-item {
position: relative; position: relative;
padding: 20px;
background: white;
border: 1px solid #eaeaea;
width: calc(25% - 7.5px);
padding: 15px;
background-color: .addAlpha(@primary-color, 0.04) [];
border: 1px solid transparent;
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;


&__name { &__name {
position: relative;
display: inline-block;
height: 24px;
margin: 0 10px 0 0 !important;
margin-right: 8px;
margin-bottom: 0 !important;
color: @text-color; color: @text-color;
font-size: 16px;
font-size: 14px;
} }


&__tag { &__tag {
padding: 4px;
color: @primary-color;
flex: none;
padding: 2px 11px;
font-size: 12px; font-size: 12px;
background-color: .addAlpha(@primary-color, 0.1) [];
border-radius: 4px;
}
border-radius: 1000px;


&__url {
color: @text-color-secondary;
font-size: 14px;
&--public {
color: @primary-color;
background-color: .addAlpha(@primary-color, 0.08) [];
border-color: .addAlpha(@primary-color, 0.5) [];
}

&--private {
color: @warning-color;
background-color: .addAlpha(@warning-color, 0.08) [];
border-color: .addAlpha(@warning-color, 0.5) [];
}
} }


&__description {
height: 44px;
margin-bottom: 20px;
&__url {
height: 40px;
margin-bottom: 10px !important;
color: @text-color-secondary; color: @text-color-secondary;
font-size: 14px;
.multiLine(2);
font-size: 13px;
} }


&__time {
display: flex;
flex: 0 1 content;
align-items: center;
width: 100%;
color: #808080;
font-size: 13px;
&__branch {
color: @text-color-tertiary;
font-size: 12px;
} }


&:hover { &:hover {
border-color: @primary-color; border-color: @primary-color;
box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.1); box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.1);

.resource-item__name {
color: @primary-color;
}
} }
}


.resource-item__name {
&::after {
position: absolute;
top: 14px;
left: 0;
width: 100%;
height: 6px;
background: linear-gradient(to right, rgba(22, 100, 255, 0.3) 0, rgba(22, 100, 255, 0) 100%);
content: '';
&:hover &__name {
color: @primary-color;
} }
} }

+ 12
- 7
react-ui/src/pages/Pipeline/components/CodeConfigItem/index.tsx View File

@@ -1,6 +1,7 @@
import { AvailableRange } from '@/enums'; import { AvailableRange } from '@/enums';
import { type CodeConfigData } from '@/pages/CodeConfig/List'; import { type CodeConfigData } from '@/pages/CodeConfig/List';
import { Flex, Typography } from 'antd'; import { Flex, Typography } from 'antd';
import classNames from 'classnames';
import styles from './index.less'; import styles from './index.less';


type CodeConfigItemProps = { type CodeConfigItemProps = {
@@ -11,27 +12,31 @@ type CodeConfigItemProps = {
function CodeConfigItem({ item, onClick }: CodeConfigItemProps) { function CodeConfigItem({ item, onClick }: CodeConfigItemProps) {
return ( return (
<div className={styles['code-config-item']} onClick={() => onClick?.(item)}> <div className={styles['code-config-item']} onClick={() => onClick?.(item)}>
<Flex justify="space-between" align="center" style={{ marginBottom: '20px', height: '32px' }}>
<Flex justify="space-between" align="center" style={{ marginBottom: '15px' }}>
<Typography.Paragraph <Typography.Paragraph
className={styles['code-config-item__name']} className={styles['code-config-item__name']}
ellipsis={{ tooltip: item.code_repo_name }} ellipsis={{ tooltip: item.code_repo_name }}
> >
{item.code_repo_name} {item.code_repo_name}
</Typography.Paragraph> </Typography.Paragraph>
<div className={styles['code-config-item__tag']}>
<div
className={classNames(
styles['code-config-item__tag'],
item.code_repo_vis === AvailableRange.Public
? styles['code-config-item__tag--public']
: styles['code-config-item__tag--private'],
)}
>
{item.code_repo_vis === AvailableRange.Public ? '公开' : '私有'} {item.code_repo_vis === AvailableRange.Public ? '公开' : '私有'}
</div> </div>
</Flex> </Flex>
<Typography.Paragraph <Typography.Paragraph
className={styles['code-config-item__url']} className={styles['code-config-item__url']}
ellipsis={{ tooltip: item.git_url }}
style={{ marginBottom: '8px' }}
ellipsis={{ rows: 2, tooltip: item.git_url }}
> >
{item.git_url} {item.git_url}
</Typography.Paragraph> </Typography.Paragraph>
<div className={styles['code-config-item__url']} style={{ marginBottom: '20px' }}>
{item.git_branch}
</div>
<div className={styles['code-config-item__branch']}>{item.git_branch}</div>
</div> </div>
); );
} }


+ 32
- 7
react-ui/src/pages/Pipeline/components/CodeSelectorModal/index.less View File

@@ -2,28 +2,53 @@
width: 100%; width: 100%;
height: 100%; height: 100%;


&__search {
width: 100%;
}

:global { :global {
.ant-input-affix-wrapper .ant-input-prefix {
margin-inline-end: 12px;
.ant-input-affix-wrapper {
border-radius: 23px !important;
.ant-input-prefix {
margin-inline-end: 12px;
}
.ant-input-suffix {
margin-inline-end: 12px;
}
.ant-input-clear-icon {
font-size: 16px;
}
} }


.ant-pagination { .ant-pagination {
text-align: right;
text-align: center;
} }


.ant-input-group-addon { .ant-input-group-addon {
display: none; display: none;
} }

.ant-pagination {
.ant-select-single {
height: 32px !important;
}
}
} }


&__content { &__content {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 20px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
gap: 10px;
width: 100%; width: 100%;
margin-top: 30px;
max-height: 50vh;
margin-top: 24px;
margin-bottom: 30px; margin-bottom: 30px;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
} }

&__empty {
padding-top: 40px;
}
} }

+ 7
- 4
react-ui/src/pages/Pipeline/components/CodeSelectorModal/index.tsx View File

@@ -8,6 +8,7 @@ import KFModal from '@/components/KFModal';
import { type CodeConfigData } from '@/pages/CodeConfig/List'; import { type CodeConfigData } from '@/pages/CodeConfig/List';
import { getCodeConfigListReq } from '@/services/codeConfig'; import { getCodeConfigListReq } from '@/services/codeConfig';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import { Icon } from '@umijs/max';
import type { ModalProps, PaginationProps } from 'antd'; import type { ModalProps, PaginationProps } from 'antd';
import { Empty, Input, Pagination } from 'antd'; import { Empty, Input, Pagination } from 'antd';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
@@ -74,15 +75,17 @@ function CodeSelectorModal({ onOk, ...rest }: CodeSelectorModalProps) {
> >
<div className={styles['code-selector']}> <div className={styles['code-selector']}>
<Input.Search <Input.Search
className={styles['code-selector__search']}
placeholder="按代码仓库名称筛选" placeholder="按代码仓库名称筛选"
allowClear allowClear
onSearch={handleSearch} onSearch={handleSearch}
style={{
width: '100%',
}}
size="large"
onChange={(e) => setInputText(e.target.value)} onChange={(e) => setInputText(e.target.value)}
suffix={null} suffix={null}
value={inputText} value={inputText}
prefix={
<Icon icon="local:magnifying-glass" style={{ marginLeft: '10px', marginTop: '2px' }} />
}
/> />
{dataList?.length !== 0 ? ( {dataList?.length !== 0 ? (
<> <>
@@ -103,7 +106,7 @@ function CodeSelectorModal({ onOk, ...rest }: CodeSelectorModalProps) {
</> </>
) : ( ) : (
<div className={styles['code-selector__empty']}> <div className={styles['code-selector__empty']}>
<Empty></Empty>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}></Empty>
</div> </div>
)} )}
</div> </div>


+ 2
- 0
react-ui/src/pages/Pipeline/components/ResourceSelectorModal/index.less View File

@@ -50,10 +50,12 @@
border-radius: 8px; border-radius: 8px;


&__title { &__title {
height: 46px;
margin-bottom: 15px; margin-bottom: 15px;
padding: 3px 0 6px; padding: 3px 0 6px;
color: @text-color; color: @text-color;
font-size: @font-size; font-size: @font-size;
line-height: 46px;
border-bottom: 1px solid @border-color-secondary; border-bottom: 1px solid @border-color-secondary;
} }
&__files { &__files {


+ 1
- 1
react-ui/src/pages/Workspace/components/UserSpace/index.less View File

@@ -48,7 +48,7 @@
&__count { &__count {
width: 24px; width: 24px;
height: 24px; height: 24px;
color: #8a8a8a;
color: @text-color-tertiary;
font-size: 12px; font-size: 12px;
line-height: 24px; line-height: 24px;
text-align: center; text-align: center;


+ 31
- 13
react-ui/src/requestConfig.ts View File

@@ -3,7 +3,14 @@
* @Date: 2024-03-25 13:52:54 * @Date: 2024-03-25 13:52:54
* @Description: 网络请求配置,详情请参考 https://umijs.org/docs/max/request * @Description: 网络请求配置,详情请参考 https://umijs.org/docs/max/request
*/ */
import type { AxiosRequestConfig, AxiosResponse, RequestConfig, RequestOptions } from '@umijs/max';
import type {
AxiosError,
AxiosRequestConfig,
AxiosResponse,
RequestConfig,
RequestError,
RequestOptions,
} from '@umijs/max';
import { message } from 'antd'; import { message } from 'antd';
import { clearSessionToken, getAccessToken } from './access'; import { clearSessionToken, getAccessToken } from './access';
import { setRemoteMenu } from './services/session'; import { setRemoteMenu } from './services/session';
@@ -12,13 +19,12 @@ import { gotoLoginPage } from './utils/ui';


// [antd: Notification] You are calling notice in render which will break in React 18 concurrent mode. Please trigger in effect instead. // [antd: Notification] You are calling notice in render which will break in React 18 concurrent mode. Please trigger in effect instead.
const popupError = (error: string, skipErrorHandler: boolean | undefined = false) => { const popupError = (error: string, skipErrorHandler: boolean | undefined = false) => {
if (skipErrorHandler) {
return;
if (!skipErrorHandler) {
// 直接调用 message.error 有时候不弹出来
setTimeout(() => {
message.error(error);
}, 100);
} }
// 直接调用 message.error 有时候不弹出来
setTimeout(() => {
message.error(error);
}, 100);
}; };


/** /**
@@ -32,22 +38,29 @@ export const requestConfig: RequestConfig = {
const headers = options.headers ?? {}; const headers = options.headers ?? {};
const authHeader = headers['Authorization']; const authHeader = headers['Authorization'];
const isToken = headers['isToken']; const isToken = headers['isToken'];
const skipLoading = (options as RequestOptions)?.skipLoading;
if (!authHeader && isToken !== false) { if (!authHeader && isToken !== false) {
const accessToken = getAccessToken(); const accessToken = getAccessToken();
if (accessToken) { if (accessToken) {
headers['Authorization'] = `Bearer ${accessToken}`; headers['Authorization'] = `Bearer ${accessToken}`;
} }
} }
Loading.show();
if (!skipLoading) {
Loading.show();
}
return { url, options }; return { url, options };
}, },
], ],
responseInterceptors: [ responseInterceptors: [
[ [
(response: AxiosResponse) => { (response: AxiosResponse) => {
Loading.hide();
const { status, data, config } = response || {}; const { status, data, config } = response || {};
const skipErrorHandler = (config as RequestOptions)?.skipErrorHandler;
const options = config as RequestOptions;
const skipErrorHandler = options?.skipErrorHandler;
const skipLoading = options?.skipLoading;
if (!skipLoading) {
Loading.hide();
}
if (status >= 200 && status < 300) { if (status >= 200 && status < 300) {
if (data && (data instanceof Blob || data.code === 200)) { if (data && (data instanceof Blob || data.code === 200)) {
return response; return response;
@@ -66,9 +79,14 @@ export const requestConfig: RequestConfig = {
return Promise.reject(response); return Promise.reject(response);
} }
}, },
(error: Error) => {
Loading.hide();
popupError(error.message ?? '请求失败');
(error: RequestError) => {
const options = (error as AxiosError).config as RequestOptions;
const skipErrorHandler = options?.skipErrorHandler;
const skipLoading = options?.skipLoading;
if (!skipLoading) {
Loading.hide();
}
popupError(error.message ?? '请求失败', skipErrorHandler);
return Promise.reject(error); return Promise.reject(error);
}, },
], ],


+ 0
- 8
react-ui/src/services/dataset/index.js View File

@@ -67,14 +67,6 @@ export function downloadAllFiles(params) {
}); });
} }


// 下载数据集单个文件
export function downloadSingleFile(params) {
return request(`/api/mmp/newdataset/downloadSinggerFile`, {
method: 'GET',
params,
});
}

// 删除数据集版本 // 删除数据集版本
export function deleteDatasetVersion(params) { export function deleteDatasetVersion(params) {
return request(`/api/mmp/newdataset/deleteDatasetVersion`, { return request(`/api/mmp/newdataset/deleteDatasetVersion`, {


+ 3
- 2
react-ui/src/services/experiment/index.js View File

@@ -103,7 +103,7 @@ export function putExperiment(data) {
}); });
} }


// 启动tensorBoard
// 启动 tensorBoard
export function runTensorBoardReq(data) { export function runTensorBoardReq(data) {
return request(`/api/mmp/tensorBoard/run`, { return request(`/api/mmp/tensorBoard/run`, {
method: 'POST', method: 'POST',
@@ -111,11 +111,12 @@ export function runTensorBoardReq(data) {
}); });
} }


// 启动tensorBoard
// 获取 tensorBoard 状态
export function getTensorBoardStatusReq(data) { export function getTensorBoardStatusReq(data) {
return request(`/api/mmp/tensorBoard/getStatus`, { return request(`/api/mmp/tensorBoard/getStatus`, {
method: 'POST', method: 'POST',
data, data,
skipLoading: true,
}); });
} }




+ 4
- 1
react-ui/src/styles/theme.less View File

@@ -11,6 +11,7 @@
@background-color: #f9fafb; // 页面背景颜色 @background-color: #f9fafb; // 页面背景颜色
@text-color: #1d1d20; @text-color: #1d1d20;
@text-color-secondary: #575757; @text-color-secondary: #575757;
@text-color-tertiary: #8a8a8a;
@success-color: #6ac21d; @success-color: #6ac21d;
@error-color: #c73131; @error-color: #c73131;
@warning-color: #f98e1b; @warning-color: #f98e1b;
@@ -18,6 +19,7 @@
@pending-color: #ecb934; @pending-color: #ecb934;
@underline-color: #5d93ff; @underline-color: #5d93ff;


@border-color-base: #eaeaea;
@border-color: rgba(22, 100, 255, 0.3); @border-color: rgba(22, 100, 255, 0.3);
@border-color-secondary: rgba(22, 100, 255, 0.1); @border-color-secondary: rgba(22, 100, 255, 0.1);
@background-color-primary: rgba(22, 100, 255, 0.03); @background-color-primary: rgba(22, 100, 255, 0.03);
@@ -25,7 +27,7 @@


@heading-color: rgba(0, 0, 0, 0.85); @heading-color: rgba(0, 0, 0, 0.85);
@input-icon-hover-color: rgba(0, 0, 0, 0.85); @input-icon-hover-color: rgba(0, 0, 0, 0.85);
@border-color-base: #d9d9d9;
@link-hover-color: #69b1ff; @link-hover-color: #69b1ff;
@sider-background-color: #f2f5f7; @sider-background-color: #f2f5f7;


@@ -74,6 +76,7 @@
warningColor: @warning-color; warningColor: @warning-color;
textColor: @text-color; textColor: @text-color;
textColorSecondary: @text-color-secondary; textColorSecondary: @text-color-secondary;
textColorTertiary: @text-color-tertiary;
fontSize: @font-size; fontSize: @font-size;
fontSizeTitle: @font-size-title; fontSizeTitle: @font-size-title;
fontSizeContent: @font-size-content; fontSizeContent: @font-size-content;


Loading…
Cancel
Save