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
12 changes: 4 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ build-%:
$(MAKE) $*-docker-build

.PHONY: build
build: database-docker-build backend-docker-build frontend-docker-build runtime-docker-build
build: backend-docker-build frontend-docker-build runtime-docker-build backend-python-docker-build

.PHONY: create-namespace
create-namespace:
Expand Down Expand Up @@ -117,9 +117,9 @@ frontend-docker-build:
runtime-docker-build:
docker build -t datamate-runtime:$(VERSION) . -f scripts/images/runtime/Dockerfile

.PHONY: label-studio-adapter-docker-build
label-studio-adapter-docker-build:
docker build -t label-studio-adapter:$(VERSION) . -f scripts/images/label-studio-adapter/Dockerfile
.PHONY: backend-python-docker-build
backend-python-docker-build:
docker build -t datamate-backend-python:$(VERSION) . -f scripts/images/datamate-python/Dockerfile

.PHONY: deer-flow-docker-build
deer-flow-docker-build:
Expand All @@ -132,10 +132,6 @@ deer-flow-docker-build:
mineru-docker-build:
docker build -t datamate-mineru:$(VERSION) . -f scripts/images/mineru/Dockerfile

.PHONY: backend-python-docker-build
backend-python-docker-build:
docker build -t datamate-backend-python:$(VERSION) . -f scripts/images/datamate-python/Dockerfile

.PHONY: backend-docker-install
backend-docker-install:
cd deployment/docker/datamate && docker compose up -d backend
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/hooks/useFetchData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export default function useFetchData<T>(
status: getFirstOfArray(filter?.status) || undefined,
tags: filter?.tags?.length ? filter.tags.join(",") : undefined,
page: current - pageOffset,
size: pageSize,
pageSize: pageSize, // Use camelCase for HTTP query params
}),
...additionalPollingFuncs.map((func) => func()),
];
Expand Down
67 changes: 67 additions & 0 deletions frontend/src/hooks/useTagConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useState, useEffect } from "react";
import { message } from "antd";
import { getTagConfigUsingGet } from "../pages/DataAnnotation/annotation.api";
import type { LabelStudioTagConfig } from "../pages/DataAnnotation/annotation.tagconfig";
import { parseTagConfig, type TagOption } from "../pages/DataAnnotation/annotation.tagconfig";

interface UseTagConfigReturn {
config: LabelStudioTagConfig | null;
objectOptions: TagOption[];
controlOptions: TagOption[];
loading: boolean;
error: string | null;
refetch: () => Promise<void>;
}

/**
* Hook to fetch and manage Label Studio tag configuration
* @param includeLabelingOnly - If true, only include controls with category="labeling" (default: true)
*/
export function useTagConfig(includeLabelingOnly: boolean = true): UseTagConfigReturn {
const [config, setConfig] = useState<LabelStudioTagConfig | null>(null);
const [objectOptions, setObjectOptions] = useState<TagOption[]>([]);
const [controlOptions, setControlOptions] = useState<TagOption[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);

const fetchConfig = async () => {
setLoading(true);
setError(null);
try {
const response = await getTagConfigUsingGet();
if (response.code === 200 && response.data) {
const tagConfig: LabelStudioTagConfig = response.data;
setConfig(tagConfig);

const { objectOptions: objects, controlOptions: controls } =
parseTagConfig(tagConfig, includeLabelingOnly);
setObjectOptions(objects);
setControlOptions(controls);
} else {
const errorMsg = response.message || "获取标签配置失败";
setError(errorMsg);
message.error(errorMsg);
}
} catch (err: any) {
const errorMsg = err.message || "加载标签配置时出错";
setError(errorMsg);
console.error("Failed to fetch tag config:", err);
message.error(errorMsg);
} finally {
setLoading(false);
}
};

useEffect(() => {
fetchConfig();
}, []);

return {
config,
objectOptions,
controlOptions,
loading,
error,
refetch: fetchConfig,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ export default function CreateAnnotationTask({
// Fetch datasets
const { data: datasetData } = await queryDatasetsUsingGet({
page: 0,
size: 1000,
pageSize: 1000, // Use camelCase for HTTP params
});
setDatasets(datasetData.content.map(mapDataset) || []);

// Fetch templates
const templateResponse = await queryAnnotationTemplatesUsingGet({
page: 1,
size: 100, // Backend max is 100
size: 100, // Backend max is 100 (template API uses 'size' not 'pageSize')
});

// The API returns: {code, message, data: {content, total, page, ...}}
if (templateResponse.code === 200 && templateResponse.data) {
const fetchedTemplates = templateResponse.data.content || [];
Expand Down Expand Up @@ -68,15 +68,13 @@ export default function CreateAnnotationTask({
try {
const values = await form.validateFields();
setSubmitting(true);

// Send templateId instead of labelingConfig
const requestData = {
name: values.name,
description: values.description,
datasetId: values.datasetId,
templateId: values.templateId,
};

await createAnnotationTaskUsingPost(requestData);
message?.success?.("创建标注任务成功");
onClose();
Expand Down Expand Up @@ -154,7 +152,6 @@ export default function CreateAnnotationTask({
/>
</Form.Item>
</div>

{/* 描述变为可选 */}
<Form.Item label="描述" name="description">
<TextArea placeholder="(可选)详细描述标注任务的要求和目标" rows={3} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ export default function CreateAnnotationTask({
// Fetch datasets
const { data: datasetData } = await queryDatasetsUsingGet({
page: 0,
size: 1000,
pageSize: 1000, // Use camelCase for HTTP params
});
setDatasets(datasetData.content.map(mapDataset) || []);

// Fetch templates
const templateResponse = await queryAnnotationTemplatesUsingGet({
page: 1,
size: 100, // Backend max is 100
size: 100, // Backend max is 100 (template API uses 'size' not 'pageSize')
});

// The API returns: {code, message, data: {content, total, page, ...}}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/DataAnnotation/Home/DataAnnotation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export default function DataAnnotation() {
cancelText: "取消",
onOk: async () => {
try {
await deleteAnnotationTaskByIdUsingDelete({ m: task.id, proj: task.labelingProjId });
await deleteAnnotationTaskByIdUsingDelete(task.id);
message.success("映射删除成功");
fetchData();
// clear selection if deleted item was selected
Expand Down Expand Up @@ -198,7 +198,7 @@ export default function DataAnnotation() {
onOk: async () => {
try {
await Promise.all(
selectedRows.map((r) => deleteAnnotationTaskByIdUsingDelete({ m: r.id, proj: r.labelingProjId }))
selectedRows.map((r) => deleteAnnotationTaskByIdUsingDelete(r.id))
);
message.success("批量删除已完成");
fetchData();
Expand Down
33 changes: 3 additions & 30 deletions frontend/src/pages/DataAnnotation/Template/TemplateForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
updateAnnotationTemplateByIdUsingPut,
} from "../annotation.api";
import type { AnnotationTemplate } from "../annotation.model";
import TagSelector from "./components/TagSelector";

const { TextArea } = Input;
const { Option } = Select;
Expand Down Expand Up @@ -111,22 +112,6 @@ const TemplateForm: React.FC<TemplateFormProps> = ({
}
};

const controlTypes = [
{ value: "Choices", label: "选项 (单选/多选)" },
{ value: "RectangleLabels", label: "矩形框 (目标检测)" },
{ value: "PolygonLabels", label: "多边形" },
{ value: "Labels", label: "标签 (文本高亮)" },
{ value: "TextArea", label: "文本区域" },
{ value: "Rating", label: "评分" },
];

const objectTypes = [
{ value: "Image", label: "图像" },
{ value: "Text", label: "文本" },
{ value: "Audio", label: "音频" },
{ value: "Video", label: "视频" },
];

const needsOptions = (type: string) => {
return ["Choices", "RectangleLabels", "PolygonLabels", "Labels"].includes(type);
};
Expand Down Expand Up @@ -243,13 +228,7 @@ const TemplateForm: React.FC<TemplateFormProps> = ({
rules={[{ required: true, message: "必填" }]}
style={{ marginBottom: 0, width: 150 }}
>
<Select>
{objectTypes.map((t) => (
<Option key={t.value} value={t.value}>
{t.label}
</Option>
))}
</Select>
<TagSelector type="object" />
</Form.Item>

<Form.Item
Expand Down Expand Up @@ -356,13 +335,7 @@ const TemplateForm: React.FC<TemplateFormProps> = ({
rules={[{ required: true, message: "必填" }]}
style={{ marginBottom: 0 }}
>
<Select placeholder="选择控件类型">
{controlTypes.map((t) => (
<Option key={t.value} value={t.value}>
{t.label}
</Option>
))}
</Select>
<TagSelector type="control" />
</Form.Item>

<Form.Item
Expand Down
Loading