-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
- {
- handleParameterClick('working_directory', value);
- }}
- />
- }
- >
-
-
+
+
{
+ handleParameterClick('working_directory', value);
+ }}
+ />
+ }
+ >
+
+
+
{
+ handleParameterClick('command', value);
+ }}
+ />
+ }
+ >
+
+
+
+
+
+
{
+ handleParameterClick('mount_path', value);
+ }}
+ />
+ }
+ >
+
+
+
{
+ handleParameterClick('env_variables', value);
+ }}
+ />
+ }
+ >
+
+
+ {controlStrategyList.map((item) => (
{
- handleParameterClick('command', value);
+ handleParameterClick(['control_strategy', item.key], {
+ ...item.value,
+ value,
+ fromSelect: true,
+ showValue: value,
+ });
}}
/>
}
+ // getValueProps={(e) => {
+ // return { value: e.value };
+ // }}
+ // getValueFromEvent={(e) => {
+ // return {
+ // ...item.value,
+ // value: e.target.value,
+ // };
+ // }}
>
-
+
+ ))}
+
+
+
+ {inParametersList.map((item) => (
-
-
-
{
- handleParameterClick('mount_path', value);
+ handleParameterClick(['in_parameters', item.key], {
+ ...item.value,
+ value,
+ fromSelect: true,
+ showValue: value,
+ });
}}
/>
}
+ required={item.value.require ? true : false}
>
-
+
+
+
+
+ {item.value.type === 'ref' && (
+
+
+
+ )}
+
+ ))}
+
+
+
+ {outParametersList.map((item) => (
{
- handleParameterClick('env_variables', value);
+ handleParameterClick(['out_parameters', item.key], {
+ ...item.value,
+ value,
+ fromSelect: true,
+ showValue: value,
+ });
}}
/>
}
+ rules={[{ required: item.value.require ? true : false }]}
+ // getValueProps={(e) => {
+ // return { value: e.value };
+ // }}
+ // getValueFromEvent={(e) => {
+ // return {
+ // ...item.value,
+ // value: e.target.value,
+ // };
+ // }}
>
-
+
- {controlStrategyList.map((item) => (
-
{
- handleParameterClick(['control_strategy', item.key], {
- ...item.value,
- value,
- });
- }}
- />
- }
- getValueProps={(e) => {
- return { value: e.value };
- }}
- getValueFromEvent={(e) => {
- return {
- ...item.value,
- value: e.target.value,
- };
- }}
- >
-
-
- ))}
-
-
-
- {inParametersList.map((item) => (
-
{
- handleParameterClick(['in_parameters', item.key], {
- ...item.value,
- value,
- });
- }}
- />
- }
- required={item.value.require ? true : false}
- >
-
-
{
- return { value: e.value };
- }}
- getValueFromEvent={(e) => {
- return {
- ...item.value,
- value: e.target.value,
- };
- }}
- >
-
-
- {item.value.type === 'ref' && (
-
-
-
- )}
-
-
- ))}
-
-
-
- {outParametersList.map((item) => (
-
{
- handleParameterClick(['out_parameters', item.key], {
- ...item.value,
- value,
- });
- }}
- />
- }
- rules={[{ required: item.value.require ? true : false }]}
- getValueProps={(e) => {
- return { value: e.value };
- }}
- getValueFromEvent={(e) => {
- return {
- ...item.value,
- value: e.target.value,
- };
- }}
- >
-
-
- ))}
-
-
- >
+ ))}
+
+
);
});
diff --git a/react-ui/src/pages/Pipeline/editPipeline/props.less b/react-ui/src/pages/Pipeline/editPipeline/props.less
new file mode 100644
index 00000000..7a802a9b
--- /dev/null
+++ b/react-ui/src/pages/Pipeline/editPipeline/props.less
@@ -0,0 +1,38 @@
+.pipeline-drawer {
+ :global {
+ label {
+ width: 100%;
+
+ &::after {
+ display: none;
+ }
+ }
+ }
+
+ &__title {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: 43px;
+ margin-bottom: 20px;
+ padding: 0 24px;
+ color: @text-color;
+ font-size: @font-size;
+ background: #f8fbff;
+ }
+
+ &__ref-row {
+ display: flex;
+ align-items: center;
+
+ &__select-button {
+ display: flex;
+ flex: none;
+ align-items: center;
+ justify-content: flex-start;
+ margin-left: 10px;
+ padding-right: 0;
+ padding-left: 0;
+ }
+ }
+}
diff --git a/react-ui/src/pages/Pipeline/editPipeline/utils.tsx b/react-ui/src/pages/Pipeline/editPipeline/utils.tsx
index bfa233f6..ffe4eb76 100644
--- a/react-ui/src/pages/Pipeline/editPipeline/utils.tsx
+++ b/react-ui/src/pages/Pipeline/editPipeline/utils.tsx
@@ -1,4 +1,5 @@
-import { PipelineGlobalParam } from '@/types';
+import { PipelineGlobalParam, PipelineNodeModelParameter } from '@/types';
+import { parseJsonText } from '@/utils';
import { Graph, INode } from '@antv/g6';
import { type MenuProps } from 'antd';
@@ -67,13 +68,19 @@ export function createMenuItems(
];
}
-function parseJsonText(text?: string | null): any | null {
- if (!text) {
- return null;
- }
- try {
- return JSON.parse(text);
- } catch (error) {
- return null;
+export function getInParameterComponent(
+ parameter: PipelineNodeModelParameter,
+): React.ReactNode | null {
+ if (parameter.value) {
}
+
+ return null;
+}
+
+export function canInput(parameter: PipelineNodeModelParameter) {
+ const { type, item_type } = parameter;
+ return !(
+ type === 'ref' &&
+ (item_type === 'dataset' || item_type === 'model' || item_type === 'image')
+ );
}
diff --git a/react-ui/src/pages/Pipeline/index.jsx b/react-ui/src/pages/Pipeline/index.jsx
index ee2ac6ae..98ba9b72 100644
--- a/react-ui/src/pages/Pipeline/index.jsx
+++ b/react-ui/src/pages/Pipeline/index.jsx
@@ -1,3 +1,4 @@
+import CommonTableCell from '@/components/CommonTableCell';
import DateTableCell from '@/components/DateTableCell';
import KFIcon from '@/components/KFIcon';
import KFModal from '@/components/KFModal';
@@ -41,7 +42,7 @@ const Pipeline = () => {
};
const routeToEdit = (e, record) => {
e.stopPropagation();
- navgite({ pathname: `/pipeline/pytorchtext/${record.id}/${record.name}` });
+ navgite({ pathname: `/pipeline/template/${record.id}/${record.name}` });
};
const showModal = () => {
form.resetFields();
@@ -66,7 +67,7 @@ const Pipeline = () => {
addWorkflow(values).then((ret) => {
console.log(ret);
if (ret.code == 200) {
- navgite({ pathname: `/pipeline/pytorchtext/${ret.data.id}/${ret.data.name}` });
+ navgite({ pathname: `/pipeline/template/${ret.data.id}/${ret.data.name}` });
}
});
}
@@ -119,9 +120,8 @@ const Pipeline = () => {
width: 120,
align: 'center',
render(text, record, index) {
- return
{(pageOption.current.page - 1) * 10 + index + 1};
+ return
{(pageOption.current.page - 1) * pageOption.current.size + index + 1};
},
- // render: (text, record, index) => `${((curPage-1)*10)+(index+1)}`,
},
{
title: '流水线名称',
@@ -133,6 +133,8 @@ const Pipeline = () => {
title: '流水线描述',
dataIndex: 'description',
key: 'description',
+ render: CommonTableCell(true),
+ ellipsis: { showTitle: false },
},
{
title: '创建时间',
diff --git a/react-ui/src/pages/Pipeline/index.less b/react-ui/src/pages/Pipeline/index.less
index 102a37ef..e1808690 100644
--- a/react-ui/src/pages/Pipeline/index.less
+++ b/react-ui/src/pages/Pipeline/index.less
@@ -7,6 +7,8 @@
margin-bottom: 10px;
padding-right: 30px;
background-image: url(/assets/images/pipeline-back.png);
+ background-repeat: no-repeat;
+ background-position: top left;
background-size: 100% 100%;
}
diff --git a/react-ui/src/pages/Workspace/components/ExperimentTable/index.tsx b/react-ui/src/pages/Workspace/components/ExperimentTable/index.tsx
index 535f9b49..a0f33e9b 100644
--- a/react-ui/src/pages/Workspace/components/ExperimentTable/index.tsx
+++ b/react-ui/src/pages/Workspace/components/ExperimentTable/index.tsx
@@ -13,7 +13,7 @@ type ExperimentTableProps = {
function ExperimentTable({ tableData = [], style }: ExperimentTableProps) {
const navgite = useNavigate();
const gotoExperiment = (record: ExperimentInstance) => {
- navgite(`/pipeline/experimentPytorchtext/${record.workflow_id}/${record.id}`);
+ navgite(`/pipeline/experiment/${record.workflow_id}/${record.id}`);
};
return (
diff --git a/react-ui/src/pages/Workspace/components/QuickStart/index.tsx b/react-ui/src/pages/Workspace/components/QuickStart/index.tsx
index c992c84a..f070fcf0 100644
--- a/react-ui/src/pages/Workspace/components/QuickStart/index.tsx
+++ b/react-ui/src/pages/Workspace/components/QuickStart/index.tsx
@@ -75,7 +75,7 @@ function QuickStart() {
buttonTop={20}
x={left + 2 * (192 + space)}
y={276}
- onClick={() => navgite('/pipeline/pipelineText')}
+ onClick={() => navgite('/pipeline/template')}
/>
navgite('/pipeline/experimentText')}
+ onClick={() => navgite('/pipeline/experiment')}
/>
= Omit & { [P in K]: NewType }
+
+// 序列化后的流水线节点
export type PipelineNodeModelSerialize = Omit<
PipelineNodeModel,
'control_strategy' | 'in_parameters' | 'out_parameters'
@@ -61,3 +68,12 @@ export type PipelineNodeModelSerialize = Omit<
in_parameters: Record;
out_parameters: Record;
};
+
+// 资源规格
+export type ComputingResource = {
+ id: number;
+ computing_resource: string;
+ description: string;
+ standard: string;
+ create_by: string;
+};
diff --git a/react-ui/src/utils/index.ts b/react-ui/src/utils/index.ts
index 15e8082c..08fef8cc 100644
--- a/react-ui/src/utils/index.ts
+++ b/react-ui/src/utils/index.ts
@@ -3,6 +3,8 @@
* @Date: 2024-03-25 13:52:54
* @Description: 工具类
*/
+
+// 生成 8 位随机数
export function s8() {
return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
}
@@ -14,3 +16,48 @@ export function getNameByCode(list: any[], code: any) {
});
return name;
}
+
+// 解析 json 字符串
+export function parseJsonText(text?: string | null): any | null {
+ if (!text) {
+ return null;
+ }
+ try {
+ return JSON.parse(text);
+ } catch (error) {
+ return null;
+ }
+}
+
+// Underscore-to-camelCase
+export function underscoreToCamelCase(obj: Record) {
+ const newObj: Record = {};
+ for (const key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ const newKey = key.replace(/([-_][a-z])/gi, function ($1) {
+ return $1.toUpperCase().replace('[-_]', '').replace('_', '');
+ });
+ let value = obj[key];
+ if (typeof value === 'object' && value !== null) {
+ value = underscoreToCamelCase(value);
+ }
+ newObj[newKey] = value;
+ }
+ }
+ return newObj;
+}
+
+export function camelCaseToUnderscore(obj: Record) {
+ const newObj: Record = {};
+ for (const key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ const newKey = key.replace(/([A-Z])/g, '_$1').toLowerCase();
+ let value = obj[key];
+ if (typeof value === 'object' && value !== null) {
+ value = camelCaseToUnderscore(value);
+ }
+ newObj[newKey] = value;
+ }
+ }
+ return newObj;
+}
diff --git a/react-ui/src/utils/modal.tsx b/react-ui/src/utils/modal.tsx
index 577c1ec3..4aff7b77 100644
--- a/react-ui/src/utils/modal.tsx
+++ b/react-ui/src/utils/modal.tsx
@@ -16,7 +16,8 @@ import { createRoot } from 'react-dom/client';
* @param modalProps - The modal properties.
* @return An object with a destroy method to close the modal.
*/
-export const openAntdModal = (
+
+export const openAntdModal = >(
modal: (props: T) => React.ReactNode,
modalProps: T,
) => {
diff --git a/react-ui/src/utils/sessionStorage.ts b/react-ui/src/utils/sessionStorage.ts
index fd006c7a..6018dbe7 100644
--- a/react-ui/src/utils/sessionStorage.ts
+++ b/react-ui/src/utils/sessionStorage.ts
@@ -1,5 +1,7 @@
// 用于新建镜像
export const mirrorNameKey = 'mirror-name';
+// 模型部署
+export const modelDeploymentInfoKey = 'model-deployment-info';
export const getSessionStorageItem = (key: string, isObject: boolean = false) => {
const jsonStr = sessionStorage.getItem(key);
@@ -22,6 +24,10 @@ export const setSessionStorageItem = (key: string, state?: any, isObject: boolea
}
};
+export const removeSessionStorageItem = (key: string) => {
+ sessionStorage.removeItem(key);
+};
+
// 获取之后就删除,多用于上一个页面传递数据到下一个页面
export const getSessionItemThenRemove = (key: string, isObject: boolean = false) => {
const res = getSessionStorageItem(key, isObject);