Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion deployment/helm/datamate/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,10 @@ ray-cluster:
key: DB_PASSWORD
- name: PG_DATABASE
value: "datamate"
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
resources:
limits:
cpu: "8"
Expand All @@ -352,7 +356,7 @@ ray-cluster:
volumeMounts:
- mountPath: /tmp/ray
name: log-volume
subPath: ray/worker
subPath: ray/$(POD_NAME)
- mountPath: /dataset
name: dataset-volume
- mountPath: /flow
Expand Down
6 changes: 4 additions & 2 deletions frontend/public/config/error-code.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
"cleaning.0009": "设置解析错误",
"cleaning.0010": "任务ID不能为空",
"cleaning.0011": "无法删除预制模板",
"cleaning.0012": "清洗任务日志文件不存在",
"cleaning.0013": "任务状态无效,无法执行此操作",
"operator.0001": "算子不存在",
"operator.0002": "算子被编排于模版中或处在正在进行的任务中,无法删除",
"operator.0002": "算子被编排于模版中或处在尚未结束的任务中,无法删除",
"operator.0003": "无法删除预置算子",
"operator.0004": "不支持的文件类型,当前仅支持tar和zip",
"operator.0005": "解析算子包失败",
Expand Down Expand Up @@ -49,4 +51,4 @@
"404": "请求的资源不存在",
"500": "服务器内部错误,请稍后重试",
"502": "网关错误"
}
}
2 changes: 1 addition & 1 deletion frontend/src/components/ActionDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const ActionDropdown = ({
<>
<Dropdown
menu={{ items: [] }}
dropdownRender={() => dropdownContent}
popupRender={() => dropdownContent}
trigger={["click"]}
placement={placement}
open={open}
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/components/DetailHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,8 @@ function DetailHeader<T>({
</div>
<p className="text-gray-700 mb-4 line-clamp-2">{(data as any)?.description}</p>
<div className="flex items-center gap-6 text-sm">
{statistics.map((stat: any) => (
<div key={stat.key} className="flex items-center gap-1 shrink-0">
{statistics.map((stat: StatisticItem, index: number) => (
<div key={stat.label || index} className="flex items-center gap-1 shrink-0">
{stat.icon}
<span>{stat.value}</span>
</div>
Expand All @@ -281,10 +281,11 @@ function DetailHeader<T>({
</div>
</div>
<div className="flex items-center gap-2">
{operations.map((op: any) => {
{operations.map((op: OperationItem) => {
if (op.isDropdown) {
return (
<ActionDropdown
key={op.key}
actions={op?.items}
onAction={op?.onMenuClick}
/>
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/i18n/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -1458,6 +1458,9 @@
"deleteDesc": "Are you sure you want to delete \"{{itemName}}\"? This action cannot be undone."
}
},
"create": {
"typeMismatch": "Type mismatch: previous operator outputs \"{{from}}\", but current operator requires \"{{to}}\""
},
"template": {
"columns": {
"templateName": "Template Name",
Expand Down Expand Up @@ -1594,6 +1597,7 @@
},
"status": {
"completed": "Completed",
"partialSuccess": "Partial Success",
"failed": "Failed",
"running": "Running",
"pending": "Pending",
Expand Down Expand Up @@ -2600,6 +2604,7 @@
"unknown": "Unknown",
"processing": "Processing",
"completed": "Completed",
"partialSuccess": "Partial Success",
"failed": "Failed"
},
"operations": {
Expand Down
6 changes: 5 additions & 1 deletion frontend/src/i18n/locales/zh/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -1458,6 +1458,9 @@
"deleteDesc": "删除「{{itemName}}」后将无法恢复,确定要执行此操作吗?"
}
},
"create": {
"typeMismatch": "类型不兼容:上一个算子输出类型为「{{from}}」,当前算子输入类型为「{{to}}」"
},
"template": {
"columns": {
"templateName": "模板名称",
Expand Down Expand Up @@ -1526,7 +1529,7 @@
"currentDisplay": "当前展示: 第 {{num}} 次",
"nthRun": "第 {{num}} 次",
"noLogs": "当前任务无可用日志",
"streaming": "实时流式输出中...",
"streaming": "实时输出中...",
"download": "下载日志",
"downloadFailed": "下载日志文件失败"
},
Expand Down Expand Up @@ -1594,6 +1597,7 @@
},
"status": {
"completed": "已完成",
"partialSuccess": "部分成功",
"failed": "失败",
"running": "运行中",
"pending": "等待中",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect, useState } from "react";
import { useEffect, useState, useMemo } from "react";
import { OperatorI } from "@/pages/OperatorMarket/operator.model";
import { CleansingTemplate } from "../../cleansing.model";
import {queryCleaningTemplateByIdUsingGet, queryCleaningTemplatesUsingGet} from "../../cleansing.api";
Expand All @@ -8,9 +8,22 @@ import {
} from "@/pages/OperatorMarket/operator.api";
import {useParams} from "react-router";
import i18n from "@/i18n";
import { App } from "antd";

function checkTypeCompatible(
prevOutputs: string | undefined,
nextInputs: string | undefined
): boolean {
if (!prevOutputs || !nextInputs) return true;
const outputs = prevOutputs.toLowerCase().trim();
const inputs = nextInputs.toLowerCase().trim();
if (outputs === "multimodal" || inputs === "multimodal") return true;
return outputs === inputs;
}

export function useOperatorOperations() {
const { id = "" } = useParams();
const { message } = App.useApp();
const [currentStep, setCurrentStep] = useState(1);

const [operators, setOperators] = useState<OperatorI[]>([]);
Expand Down Expand Up @@ -115,6 +128,19 @@ export function useOperatorOperations() {
selectedOperators.filter((op) => op.id !== operator.id)
);
} else {
// Validate type compatibility with the last selected operator
if (selectedOperators.length > 0) {
const lastOp = selectedOperators[selectedOperators.length - 1];
if (!checkTypeCompatible(lastOp.outputs, operator.inputs)) {
message.warning(
i18n.t("dataCleansing.create.typeMismatch", {
from: lastOp.outputs,
to: operator.inputs,
})
);
return;
}
}
setSelectedOperators([...selectedOperators, { ...operator }]);
}
};
Expand Down
16 changes: 7 additions & 9 deletions frontend/src/pages/DataCleansing/Detail/TaskDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,24 +119,22 @@ export default function CleansingTaskDetail() {
{
icon: <CheckCircle className="w-4 h-4 text-green-500" />,
label: t("dataCleansing.detail.statistics.successFiles"),
value: task?.progress?.succeedFileNum || "0",
value: task?.progress?.succeedFileNum || 0,
},
{
icon: <AlertCircle className="w-4 h-4 text-red-500" />,
label: t("dataCleansing.detail.statistics.failedFiles"),
value: (task?.status.value === TaskStatus.RUNNING || task?.status.value === TaskStatus.PENDING) ?
task?.progress.failedFileNum :
task?.progress?.totalFileNum - task?.progress.succeedFileNum,
value: task?.progress?.failedFileNum || 0,
},
{
icon: <Activity className="w-4 h-4 text-purple-500" />,
label: t("dataCleansing.detail.statistics.successRate"),
value: task?.progress?.successRate ? task?.progress?.successRate + "%" : "--",
value: task?.progress?.process ? task?.progress?.process + "%" : "--",
},
];

const operations = [
...(task?.status === TaskStatus.RUNNING
...(task?.status?.value === TaskStatus.RUNNING
? [
{
key: "pause",
Expand All @@ -146,11 +144,11 @@ export default function CleansingTaskDetail() {
},
]
: []),
...([TaskStatus.PENDING, TaskStatus.STOPPED, TaskStatus.FAILED].includes(task?.status?.value)
...([TaskStatus.PENDING, TaskStatus.STOPPED, TaskStatus.FAILED, TaskStatus.PARTIAL_SUCCESS].includes(task?.status?.value)
? [
{
key: "start",
label: t("dataCleansing.actions.updateTask"),
label: t("dataCleansing.actions.start"),
icon: <Play className="w-4 h-4" />,
onClick: startTask,
},
Expand Down Expand Up @@ -217,7 +215,7 @@ export default function CleansingTaskDetail() {
)}
{activeTab === "operators" && <OperatorTable task={task} />}
{activeTab === "files" && <FileTable result={result} fetchTaskResult={fetchTaskResult} />}
{activeTab === "logs" && <LogsTable taskLog={taskLog} fetchTaskLog={fetchTaskLog} retryCount={task.retryCount} taskName={task.name} />}
{activeTab === "logs" && <LogsTable taskLog={taskLog} fetchTaskLog={fetchTaskLog} retryCount={task.retryCount} taskName={task.name} taskStatus={task?.status?.value} />}
</div>
</div>
</>
Expand Down
26 changes: 14 additions & 12 deletions frontend/src/pages/DataCleansing/Detail/components/BasicInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,16 @@ export default function BasicInfo({ task }: { task: CleansingTask }) {
<div className="text-center p-4 bg-gradient-to-br from-green-50 to-green-100 rounded-lg">
<CheckCircle className="w-8 h-8 text-green-500 mb-2 mx-auto" />
<div className="text-xl font-bold text-green-500">
{task?.progress?.succeedFileNum || "0"}
{task?.progress?.succeedFileNum ?? 0}
</div>
<div className="text-sm text-gray-600">{t("dataCleansing.detail.statistics.successFiles")}</div>
</div>
<div className="text-center p-4 bg-gradient-to-br from-red-50 to-red-100 rounded-lg">
<AlertCircle className="w-8 h-8 text-red-500 mb-2 mx-auto" />
<div className="text-xl font-bold text-red-500">
{(task?.status.value === TaskStatus.RUNNING || task?.status.value === TaskStatus.PENDING) ?
task?.progress.failedFileNum :
task?.progress?.totalFileNum - task?.progress.succeedFileNum}
(task?.progress?.failedFileNum ?? 0) :
Math.max(0, (task?.progress?.totalFileNum ?? 0) - (task?.progress?.succeedFileNum ?? 0))}
</div>
<div className="text-sm text-gray-600">{t("dataCleansing.detail.statistics.failedFiles")}</div>
</div>
Expand All @@ -113,33 +113,35 @@ export default function BasicInfo({ task }: { task: CleansingTask }) {
column={2}
bordered={false}
size="middle"
labelStyle={{ fontWeight: 500, color: "#555" }}
contentStyle={{ fontSize: 14 }}
styles={{ label: { fontWeight: 500, color: "#555" }, content: { fontSize: 14 } }}
items={descriptionItems}
></Descriptions>
</div>
{/* 处理进度 */}
<div>
<h3 className="text-lg font-semibold text-gray-900 mb-4">{t("dataCleansing.detail.basicInfo.processingProgress")}</h3>
{ task?.status?.value === TaskStatus.FAILED ?
{ task?.status?.value === TaskStatus.FAILED ? (
<Progress percent={task?.progress?.process} size="small" status="exception" />
: <Progress percent={task?.progress?.process} size="small"/>
}
) : task?.status?.value === TaskStatus.PARTIAL_SUCCESS ? (
<Progress percent={task?.progress?.process} size="small" strokeColor="#f59e0b" />
) : (
<Progress percent={task?.progress?.process} size="small"/>
)}
<div className="grid grid-cols-2 gap-4 text-sm mt-4">
<div className="flex items-center gap-2">
<span className="w-3 h-3 bg-green-500 rounded-full inline-block" />
<span>{t("dataCleansing.detail.basicInfo.completed", { count: task?.progress?.succeedFileNum || "0" })}</span>
<span>{t("dataCleansing.detail.basicInfo.completed", { count: task?.progress?.succeedFileNum ?? 0 })}</span>
</div>
<div className="flex items-center gap-2">
<span className="w-3 h-3 bg-blue-500 rounded-full inline-block" />
<span>{t("dataCleansing.detail.basicInfo.processing", { count: (task?.status.value === TaskStatus.RUNNING || task?.status.value === TaskStatus.PENDING) ?
task?.progress?.totalFileNum - task?.progress.succeedFileNum : 0 })}</span>
Math.max(0, (task?.progress?.totalFileNum ?? 0) - (task?.progress?.succeedFileNum ?? 0)) : 0 })}</span>
</div>
<div className="flex items-center gap-2">
<span className="w-3 h-3 bg-red-500 rounded-full inline-block" />
<span>{t("dataCleansing.detail.basicInfo.failed", { count: (task?.status.value === TaskStatus.RUNNING || task?.status.value === TaskStatus.PENDING) ?
task?.progress.failedFileNum :
task?.progress?.totalFileNum - task?.progress.succeedFileNum })}</span>
(task?.progress?.failedFileNum ?? 0) :
Math.max(0, (task?.progress?.totalFileNum ?? 0) - (task?.progress?.succeedFileNum ?? 0)) })}</span>
</div>
</div>
</div>
Expand Down
Loading
Loading