From 68a3425aac2cd71972e3cd2fcc7deb911eaba7ae Mon Sep 17 00:00:00 2001 From: gary-Shen Date: Mon, 11 Aug 2025 19:18:22 +0800 Subject: [PATCH 01/45] fix(frontend): fix #245 --- .../components/annotationRightCorner/index.tsx | 8 +++++--- .../src/pages/tasks.[id].samples.[id]/index.tsx | 12 +++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/apps/frontend/src/pages/tasks.[id].samples.[id]/components/annotationRightCorner/index.tsx b/apps/frontend/src/pages/tasks.[id].samples.[id]/components/annotationRightCorner/index.tsx index 614fbd8d1..24a31ffd2 100644 --- a/apps/frontend/src/pages/tasks.[id].samples.[id]/components/annotationRightCorner/index.tsx +++ b/apps/frontend/src/pages/tasks.[id].samples.[id]/components/annotationRightCorner/index.tsx @@ -29,6 +29,8 @@ interface AnnotationRightCornerProps { fetchNext?: () => void; totalSize: number; + + isLastPage: boolean; } export const SAMPLE_CHANGED = 'sampleChanged'; @@ -63,7 +65,7 @@ export interface AnnotationLoaderData { samples: SampleListResponse; } -const AnnotationRightCorner = ({ noSave, fetchNext, totalSize }: AnnotationRightCornerProps) => { +const AnnotationRightCorner = ({ noSave, fetchNext, totalSize, isLastPage }: AnnotationRightCornerProps) => { const isFetching = useIsFetching(); const isMutating = useIsMutating(); const isGlobalLoading = isFetching > 0 || isMutating > 0; @@ -86,11 +88,11 @@ const AnnotationRightCorner = ({ noSave, fetchNext, totalSize }: AnnotationRight // 第一次进入就是40的倍数时,获取下一页数据 useEffect(() => { - if (isLastSample && samples.length < totalSize) { + if (isLastSample && samples.length < totalSize && !isLastPage) { // TODO: fetchNext 调用两次 fetchNext?.(); } - }, [fetchNext, isLastSample, samples.length, totalSize]); + }, [fetchNext, isLastSample, samples.length, totalSize, isLastPage]); const navigateWithSearch = useCallback( (to: string) => { diff --git a/apps/frontend/src/pages/tasks.[id].samples.[id]/index.tsx b/apps/frontend/src/pages/tasks.[id].samples.[id]/index.tsx index 13a5b1e46..fd57f1f04 100644 --- a/apps/frontend/src/pages/tasks.[id].samples.[id]/index.tsx +++ b/apps/frontend/src/pages/tasks.[id].samples.[id]/index.tsx @@ -152,6 +152,7 @@ const AnnotationPage = () => { const PAGE_SIZE = 40; // 滚动加载 const [totalCount, setTotalCount] = useState(0); + const [serverPage, setServerPage] = useState(1); const currentPage = useRef(1); if (currentPage.current === 1) { currentPage.current = sample?.data.inner_id ? Math.floor(sample.data.inner_id / PAGE_SIZE) + 1 : 1; @@ -170,7 +171,7 @@ const AnnotationPage = () => { currentPage.current += 1; setTotalCount(meta_data?.total ?? 0); - + setServerPage(meta_data?.page ?? 1); return data; }, [routeParams.taskId]); const [samples = [] as SampleResponse[], loading, setSamples, svc] = useScrollFetch( @@ -180,14 +181,19 @@ const AnnotationPage = () => { document.querySelector('.labelu-audio__sidebar div') || document.querySelector('.labelu-video__sidebar div'), { - isEnd: () => totalCount === samples.length, + isEnd: () => totalCount === samples.length || serverPage === Math.ceil(totalCount / PAGE_SIZE), }, ); const leftSiderContent = useMemo(() => , []); const topActionContent = ( - + = Math.ceil(totalCount / PAGE_SIZE)} + noSave={!!searchParams.get('noSave')} + /> ); const annotationContextValue = useMemo(() => { From a2159af887042954ba98f2e581c80ed6af98f3f9 Mon Sep 17 00:00:00 2001 From: gary Date: Mon, 11 Aug 2025 19:24:49 +0800 Subject: [PATCH 02/45] chore: update frontend package.json version to 5.9.1 [skip ci] --- apps/frontend/package.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/frontend/package.json b/apps/frontend/package.json index dbe7dab09..384a62b6d 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/frontend", - "version": "5.9.0", + "version": "5.9.1", "private": true, "dependencies": { "@ant-design/icons": "^4.6.2", diff --git a/package.json b/package.json index a962c01f1..5cc59ad18 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "packages/*", "apps/*" ], - "version": "5.9.0", + "version": "5.9.1", "scripts": { "prepare": "husky install", "build": "pnpm --filter @labelu/interface --filter @labelu/i18n --filter @labelu/formatter --filter @labelu/image --filter @labelu/components-react --filter @labelu/image-annotator-react --filter @labelu/audio-react --filter @labelu/video-react --filter @labelu/audio-annotator-react --filter @labelu/video-annotator-react build", From 6ed8ca2adc09525ba712eb73227f2a4e2cecb81a Mon Sep 17 00:00:00 2001 From: Little-King2022 <110970384+Little-King2022@users.noreply.github.com> Date: Tue, 18 Nov 2025 23:11:36 +0800 Subject: [PATCH 03/45] fix: make file extension check case-insensitive in isCorrectFileType --- apps/frontend/src/utils/common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/frontend/src/utils/common.ts b/apps/frontend/src/utils/common.ts index 9249d30f4..d4995c797 100644 --- a/apps/frontend/src/utils/common.ts +++ b/apps/frontend/src/utils/common.ts @@ -118,7 +118,7 @@ const commonController = { const correctType = FileExtension[type]; const dotIndex = fileName.lastIndexOf('.'); if (dotIndex > -1) { - const _type = fileName.slice(dotIndex + 1); + const _type = fileName.slice(dotIndex + 1).toLowerCase(); if (correctType.indexOf(_type) > -1) { result = true; } From 107f3533233c3e889d9769ca22bafb25f8fda882 Mon Sep 17 00:00:00 2001 From: shlab Date: Wed, 18 Mar 2026 20:03:03 +0800 Subject: [PATCH 04/45] =?UTF-8?q?fix(image,=20image-annotator-react):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=B5=8F=E8=A7=88=E5=99=A8=E7=BC=A9=E6=94=BE?= =?UTF-8?q?/=E5=85=A8=E5=B1=8F=E5=88=87=E6=8D=A2=E5=90=8E=E6=A0=87?= =?UTF-8?q?=E6=B3=A8=E6=A1=86=E4=BD=8D=E7=BD=AE=E5=81=8F=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Renderer.resize() 中重新获取 devicePixelRatio,避免使用构造时的缓存值 - useImageAnnotator 新增 matchMedia 监听 devicePixelRatio 变化,在浏览器缩放或全屏切换时自动触发 resize 重新校准坐标 Co-Authored-By: Claude Opus 4.6 --- .../src/hooks/useImageAnnotator.ts | 41 +++++++++++++++---- packages/image/src/core/Renderer.ts | 3 ++ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/packages/image-annotator-react/src/hooks/useImageAnnotator.ts b/packages/image-annotator-react/src/hooks/useImageAnnotator.ts index 0a399ff4f..1f0d7b880 100644 --- a/packages/image-annotator-react/src/hooks/useImageAnnotator.ts +++ b/packages/image-annotator-react/src/hooks/useImageAnnotator.ts @@ -11,6 +11,22 @@ export const useImageAnnotator = (containerRef: React.RefObject, const ignoredFirstRun = useRef(true); useLayoutEffect(() => { + const handleResize = () => { + if (!containerRef.current || !engine) { + return; + } + + const width = containerRef.current.clientWidth; + const height = containerRef.current.clientHeight; + + engine.resize(width, height); + + // 需要加载图片后才能居中,否则标注坐标计算会有误差 + if (engine.backgroundRenderer?.image) { + engine.center(); + } + }; + const resizeObserver = new ResizeObserver((entries) => { if (entries.length === 0) { return; @@ -23,21 +39,28 @@ export const useImageAnnotator = (containerRef: React.RefObject, return; } - const height = entries[0].contentRect.height; - const width = entries[0].contentRect.width; - - engine?.resize(width, height); - - // 需要加载图片后才能居中,否则标注坐标计算会有误差 - if (engine?.backgroundRenderer?.image) { - engine?.center(); - } + handleResize(); }); resizeObserver.observe(containerRef.current as HTMLElement); + // 监听 devicePixelRatio 变化(浏览器缩放、全屏切换等场景) + let dprMediaQuery: MediaQueryList | null = null; + const handleDprChange = () => { + handleResize(); + + // dpr 变化后需要重新监听新的 dpr 值 + dprMediaQuery?.removeEventListener('change', handleDprChange); + dprMediaQuery = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`); + dprMediaQuery.addEventListener('change', handleDprChange); + }; + + dprMediaQuery = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`); + dprMediaQuery.addEventListener('change', handleDprChange); + return () => { resizeObserver.disconnect(); + dprMediaQuery?.removeEventListener('change', handleDprChange); }; }, [containerRef, engine]); diff --git a/packages/image/src/core/Renderer.ts b/packages/image/src/core/Renderer.ts index 58f369bd0..6f915b502 100644 --- a/packages/image/src/core/Renderer.ts +++ b/packages/image/src/core/Renderer.ts @@ -66,6 +66,9 @@ export class Renderer extends EventEmitter { public resize(width: number, height: number) { const { canvas } = this; + // 每次 resize 时重新获取 devicePixelRatio,避免浏览器缩放或全屏切换后坐标偏移 + this.ratio = window.devicePixelRatio || 1; + canvas.width = width * this.ratio; canvas.height = height * this.ratio; canvas.style.width = `${width}px`; From 0d3f2f8913d79405d6ce70f58546fbd8e086a9e8 Mon Sep 17 00:00:00 2001 From: shlab Date: Mon, 20 Apr 2026 12:21:43 +0800 Subject: [PATCH 05/45] feat(frontend): add s3 datasrouce and ai annotation --- apps/frontend/src/api/mutations/datasource.ts | 51 ++++ .../src/api/queryKeyFactories/datasource.ts | 11 + .../src/api/queryKeyFactories/index.ts | 1 + apps/frontend/src/api/services/datasource.ts | 58 ++++ apps/frontend/src/api/services/samples.ts | 14 + apps/frontend/src/api/types.ts | 117 +++++++- apps/frontend/src/assets/svg/empty.svg | 12 + apps/frontend/src/assets/svg/spark.svg | 1 + apps/frontend/src/components/CustomEmpty.tsx | 12 + .../src/components/Navigate/index.tsx | 7 +- .../pages/datasources/DataSourceFormModal.tsx | 122 ++++++++ apps/frontend/src/pages/datasources/index.tsx | 177 ++++++++++++ apps/frontend/src/pages/datasources/style.ts | 16 ++ .../partials/InputData/S3ImportModal.style.ts | 27 ++ .../partials/InputData/S3ImportModal.tsx | 271 ++++++++++++++++++ .../partials/InputData/index.tsx | 40 ++- .../annotationRightCorner/index.tsx | 41 ++- .../components/sliderCard/index.tsx | 3 +- .../pages/tasks.[id].samples.[id]/index.tsx | 17 +- apps/frontend/src/pages/tasks.[id]/index.tsx | 6 +- apps/frontend/src/routes.tsx | 17 ++ apps/frontend/tsconfig.tsbuildinfo | 1 + apps/frontend/vite.config.ts | 4 +- 23 files changed, 1005 insertions(+), 21 deletions(-) create mode 100644 apps/frontend/src/api/mutations/datasource.ts create mode 100644 apps/frontend/src/api/queryKeyFactories/datasource.ts create mode 100644 apps/frontend/src/api/services/datasource.ts create mode 100644 apps/frontend/src/assets/svg/empty.svg create mode 100644 apps/frontend/src/assets/svg/spark.svg create mode 100644 apps/frontend/src/components/CustomEmpty.tsx create mode 100644 apps/frontend/src/pages/datasources/DataSourceFormModal.tsx create mode 100644 apps/frontend/src/pages/datasources/index.tsx create mode 100644 apps/frontend/src/pages/datasources/style.ts create mode 100644 apps/frontend/src/pages/tasks.[id].edit/partials/InputData/S3ImportModal.style.ts create mode 100644 apps/frontend/src/pages/tasks.[id].edit/partials/InputData/S3ImportModal.tsx create mode 100644 apps/frontend/tsconfig.tsbuildinfo diff --git a/apps/frontend/src/api/mutations/datasource.ts b/apps/frontend/src/api/mutations/datasource.ts new file mode 100644 index 000000000..666f015ab --- /dev/null +++ b/apps/frontend/src/api/mutations/datasource.ts @@ -0,0 +1,51 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query'; + +import { createDataSource, deleteDataSource, importS3Samples, updateDataSource } from '@/api/services/datasource'; +import { datasourceKey } from '@/api/queryKeyFactories/datasource'; +import { sampleKey } from '@/api/queryKeyFactories/sample'; + +import type { CreateDataSourceCommand, ImportS3SamplesCommand, UpdateDataSourceCommand } from '../types'; + +export function useCreateDataSourceMutation() { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (data: CreateDataSourceCommand) => createDataSource(data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: datasourceKey.lists() }); + }, + }); +} + +export function useUpdateDataSourceMutation(dsId: number) { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (data: UpdateDataSourceCommand) => updateDataSource(dsId, data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: datasourceKey.lists() }); + }, + }); +} + +export function useDeleteDataSourceMutation() { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (dsId: number) => deleteDataSource(dsId), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: datasourceKey.lists() }); + }, + }); +} + +export function useImportS3SamplesMutation(taskId: number) { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: (data: ImportS3SamplesCommand) => importS3Samples(taskId, data), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: sampleKey.lists() }); + }, + }); +} diff --git a/apps/frontend/src/api/queryKeyFactories/datasource.ts b/apps/frontend/src/api/queryKeyFactories/datasource.ts new file mode 100644 index 000000000..17f167b6c --- /dev/null +++ b/apps/frontend/src/api/queryKeyFactories/datasource.ts @@ -0,0 +1,11 @@ +import type { ListDataSourcesParams, ListS3ObjectsParams } from '../types'; + +export const datasourceKey = { + all: ['datasourceKey'] as const, + lists: () => [...datasourceKey.all, 'list'] as const, + list: (filter: ListDataSourcesParams) => [...datasourceKey.lists(), filter] as const, + details: () => [...datasourceKey.all, 'details'] as const, + detail: (id: number) => [...datasourceKey.details(), id] as const, + objects: () => [...datasourceKey.all, 'objects'] as const, + objectList: (filter: ListS3ObjectsParams) => [...datasourceKey.objects(), filter] as const, +}; diff --git a/apps/frontend/src/api/queryKeyFactories/index.ts b/apps/frontend/src/api/queryKeyFactories/index.ts index 03327e455..74331471d 100644 --- a/apps/frontend/src/api/queryKeyFactories/index.ts +++ b/apps/frontend/src/api/queryKeyFactories/index.ts @@ -1,2 +1,3 @@ export * from './sample'; export * from './task'; +export * from './datasource'; diff --git a/apps/frontend/src/api/services/datasource.ts b/apps/frontend/src/api/services/datasource.ts new file mode 100644 index 000000000..2b7c80451 --- /dev/null +++ b/apps/frontend/src/api/services/datasource.ts @@ -0,0 +1,58 @@ +import request from '../request'; +import type { + CreateDataSourceCommand, + UpdateDataSourceCommand, + ListDataSourcesParams, + DataSourceListResponse, + DataSourceResponse, + ListS3ObjectsParams, + S3ObjectListResponse, + ImportS3SamplesCommand, + OkResponse, + OkRespCommonDataResp, + OkRespCreateSampleResponse, +} from '../types'; + +export async function getDataSources({ page, ...params }: ListDataSourcesParams): Promise { + return await request.get('/v1/datasources', { + params: { + ...params, + page: typeof page === 'undefined' ? 0 : page - 1, + }, + }); +} + +export async function getDataSource(dsId: number): Promise> { + return await request.get(`/v1/datasources/${dsId}`); +} + +export async function createDataSource(data: CreateDataSourceCommand): Promise> { + return await request.post('/v1/datasources', data); +} + +export async function updateDataSource( + dsId: number, + data: UpdateDataSourceCommand, +): Promise> { + return await request.patch(`/v1/datasources/${dsId}`, data); +} + +export async function deleteDataSource(dsId: number): Promise { + return await request.delete(`/v1/datasources/${dsId}`); +} + +export async function listS3Objects({ + ds_id, + ...params +}: ListS3ObjectsParams): Promise> { + return await request.get(`/v1/datasources/${ds_id}/objects`, { + params, + }); +} + +export async function importS3Samples( + taskId: number, + data: ImportS3SamplesCommand, +): Promise { + return await request.post(`/v1/tasks/${taskId}/samples/import_s3`, data); +} diff --git a/apps/frontend/src/api/services/samples.ts b/apps/frontend/src/api/services/samples.ts index 7904d3491..3162361a3 100644 --- a/apps/frontend/src/api/services/samples.ts +++ b/apps/frontend/src/api/services/samples.ts @@ -3,6 +3,7 @@ import commonController from '@/utils/common'; import request from '../request'; import { getTask } from './task'; import { + type AutoLabelCommand, ExportType, type DeleteApiV1TasksTaskIdDeleteParams, type DeleteSampleCommand, @@ -11,6 +12,7 @@ import { type ListByApiV1TasksTaskIdSamplesGetParams, type OkRespCommonDataResp, type OkRespCreateSampleResponse, + type OkRespAutoLabelResponse, type OkRespSampleResponse, type PatchSampleCommand, type SampleData, @@ -80,6 +82,18 @@ export async function updateSampleAnnotationResult( ); } +export async function autoLabelSample( + taskId: number, + sampleId: number, + body: AutoLabelCommand = {}, +): Promise { + return await request.post(`/v1/tasks/${taskId}/samples/${sampleId}/auto_label`, body, { + params: { + sample_id: sampleId, + }, + }); +} + export async function outputSample(taskId: number, sampleIds: number[], activeTxt: ExportType) { const headers = {} as any; diff --git a/apps/frontend/src/api/types.ts b/apps/frontend/src/api/types.ts index 407ec3344..437858a8e 100644 --- a/apps/frontend/src/api/types.ts +++ b/apps/frontend/src/api/types.ts @@ -11,6 +11,9 @@ export interface AttachmentResponse { filename?: string; /** Url description: upload file url */ url?: string; + thumbnail_url?: string | null; + stream_url?: string | null; + storage_backend?: string | null; } export interface GetUsersApiV1UsersGetParams { @@ -100,6 +103,24 @@ export interface ExportApiV1TasksTaskIdSamplesExportPostParams { export_type: ExportType; } +export interface AutoLabelCommand { + overwrite?: boolean; + template_id?: number | null; + prompt?: string | null; +} + +export interface AutoLabelResponse { + status: string; + task_id: number; + sample_id: number; + media_type: MediaType; + provider: string; + model?: string | null; + latency_ms?: number | null; + pre_annotation_id?: number | null; + warning_message?: string | null; +} + export interface ExportSampleCommand { /** Sample Ids description: sample id */ sample_ids?: number[]; @@ -212,6 +233,10 @@ export interface OkRespSampleResponse { data: SampleResponse; } +export interface OkRespAutoLabelResponse { + data: AutoLabelResponse; +} + export interface OkRespSignupResponse { data: SignupResponse; } @@ -247,6 +272,9 @@ export interface SampleResponse { id: number; url: string; filename: string; + thumbnail_url?: string | null; + stream_url?: string | null; + storage_backend?: string | null; }; /** Annotated Count description: annotate result count */ annotated_count?: number; @@ -265,11 +293,14 @@ export interface PreAnnotationResponse { id?: number; /** Data description: sample data, include filename, file url, or result */ data?: PreAnnotationType[]; - file: { + file?: { id: string; url: string; filename: string; - }; + thumbnail_url?: string | null; + stream_url?: string | null; + storage_backend?: string | null; + } | null; /** Created At description: task created at time */ created_at?: string; /** Created By description: task created by */ @@ -831,3 +862,85 @@ export interface FrameTool { label: string; attributes?: Attribute; } + +// ── Data Source (S3) ──────────────────────────────────────────────── + +export interface DataSourceResponse { + id: number; + name: string; + type: string; + endpoint?: string; + region?: string; + bucket: string; + prefix?: string; + path_style?: boolean; + use_ssl?: boolean; + presign_expire_secs?: number; + created_by?: number; + created_at?: string; + updated_at?: string; +} + +export interface CreateDataSourceCommand { + name: string; + type?: string; + endpoint?: string; + region?: string; + bucket: string; + prefix?: string; + access_key_id: string; + secret_access_key: string; + path_style?: boolean; + use_ssl?: boolean; + presign_expire_secs?: number; +} + +export interface UpdateDataSourceCommand { + name?: string; + endpoint?: string; + region?: string; + bucket?: string; + prefix?: string; + access_key_id?: string; + secret_access_key?: string; + path_style?: boolean; + use_ssl?: boolean; + presign_expire_secs?: number; +} + +export interface ListDataSourcesParams { + page?: number; + size?: number; +} + +export interface DataSourceListResponse { + meta_data?: MetaData; + data: DataSourceResponse[]; +} + +export interface S3ObjectItem { + key: string; + size: number; + last_modified?: string | null; +} + +export interface S3ObjectListResponse { + objects: S3ObjectItem[]; + next_page_token?: string | null; + truncated: boolean; +} + +export interface ListS3ObjectsParams { + ds_id: number; + prefix?: string; + extension?: string; + page_token?: string | null; + size?: number; +} + +export interface ImportS3SamplesCommand { + data_source_id: number; + object_keys?: string[]; + prefix?: string; + extension?: string; +} diff --git a/apps/frontend/src/assets/svg/empty.svg b/apps/frontend/src/assets/svg/empty.svg new file mode 100644 index 000000000..eba867df2 --- /dev/null +++ b/apps/frontend/src/assets/svg/empty.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/frontend/src/assets/svg/spark.svg b/apps/frontend/src/assets/svg/spark.svg new file mode 100644 index 000000000..bc5af8cb9 --- /dev/null +++ b/apps/frontend/src/assets/svg/spark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/frontend/src/components/CustomEmpty.tsx b/apps/frontend/src/components/CustomEmpty.tsx new file mode 100644 index 000000000..03aff6693 --- /dev/null +++ b/apps/frontend/src/components/CustomEmpty.tsx @@ -0,0 +1,12 @@ +import React from 'react'; + +import { ReactComponent as EmptyElement } from '@/assets/svg/empty.svg'; + +export default function CustomEmpty({ description }: { description?: React.ReactNode }) { + return ( +
+ +

{description ?? '暂无数据'}

+
+ ); +} diff --git a/apps/frontend/src/components/Navigate/index.tsx b/apps/frontend/src/components/Navigate/index.tsx index 18dcc6fa8..7c12223a8 100644 --- a/apps/frontend/src/components/Navigate/index.tsx +++ b/apps/frontend/src/components/Navigate/index.tsx @@ -1,4 +1,4 @@ -import Icon, { BellOutlined, PoweroffOutlined } from '@ant-design/icons'; +import Icon, { BellOutlined, DatabaseOutlined, PoweroffOutlined } from '@ant-design/icons'; import { FlexLayout } from '@labelu/components-react'; import { Button, Divider, Dropdown, Popover, Tag } from 'antd'; import { Link, useMatch, useNavigate } from 'react-router-dom'; @@ -76,6 +76,11 @@ const Homepage = () => { )} + + + + handleDelete(record.id)}> + + + + ), + }, + ]; + + const total = data?.meta_data?.total ?? 0; + + return ( + +
+ +
+ + }} + /> + + {total > pageSize && ( +
+ { + searchParams.set('page', String(value)); + searchParams.set('size', String(_pageSize)); + setSearchParams(searchParams); + }} + /> +
+ )} + setModalOpen(false)} + onSubmit={handleSubmit} + loading={createMutation.isPending || updateMutation.isPending} + /> + + ); +}; + +export default DataSources; diff --git a/apps/frontend/src/pages/datasources/style.ts b/apps/frontend/src/pages/datasources/style.ts new file mode 100644 index 000000000..134ec4364 --- /dev/null +++ b/apps/frontend/src/pages/datasources/style.ts @@ -0,0 +1,16 @@ +import styled from 'styled-components'; +import { FlexLayout } from '@labelu/components-react'; + +export const Wrapper = styled(FlexLayout)` + height: calc(100vh - var(--header-height)); + padding: 0 1.5rem; + box-sizing: border-box; +`; + +export const Header = styled(FlexLayout.Header)` + padding: 1rem 0; +`; + +export const Footer = styled(FlexLayout.Footer)` + padding: 1rem 0; +`; diff --git a/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/S3ImportModal.style.ts b/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/S3ImportModal.style.ts new file mode 100644 index 000000000..0e0005777 --- /dev/null +++ b/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/S3ImportModal.style.ts @@ -0,0 +1,27 @@ +import styled from 'styled-components'; + +export const BreadcrumbNav = styled.div` + display: flex; + align-items: center; + gap: 0.25rem; + margin-bottom: 0.75rem; + font-size: 13px; + color: var(--color-text-secondary); + + .breadcrumb-separator { + margin: 0 0.125rem; + } + + .breadcrumb-item { + cursor: pointer; + color: var(--color-primary); + + &:hover { + text-decoration: underline; + } + } + + .breadcrumb-current { + color: var(--color-text); + } +`; diff --git a/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/S3ImportModal.tsx b/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/S3ImportModal.tsx new file mode 100644 index 000000000..fdf244929 --- /dev/null +++ b/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/S3ImportModal.tsx @@ -0,0 +1,271 @@ +import { useState, useMemo, useCallback } from 'react'; +import { Modal, Select, Button, Table, message } from 'antd'; +import { FolderOutlined } from '@ant-design/icons'; +import { useQuery } from '@tanstack/react-query'; +import { FlexLayout } from '@labelu/components-react'; +import { useTranslation } from '@labelu/i18n'; +import { Link } from 'react-router-dom'; +import formatter from '@labelu/formatter'; + +import type { MediaType, S3ObjectItem } from '@/api/types'; +import { getDataSources, listS3Objects } from '@/api/services/datasource'; +import { datasourceKey } from '@/api/queryKeyFactories/datasource'; +import { useImportS3SamplesMutation } from '@/api/mutations/datasource'; +import { FileExtension } from '@/constants/mediaType'; + +import { BreadcrumbNav } from './S3ImportModal.style'; + +interface S3ImportModalProps { + open: boolean; + onClose: () => void; + taskId: number; + mediaType: MediaType; + onImportSuccess: (fileNames: string[]) => void; +} + +function formatFileSize(bytes: number): string { + if (bytes < 1024) return `${bytes} B`; + if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; + if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; + return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`; +} + +const S3ImportModal = ({ open, onClose, taskId, mediaType, onImportSuccess }: S3ImportModalProps) => { + const { t } = useTranslation(); + const [selectedDsId, setSelectedDsId] = useState(); + const [prefix, setPrefix] = useState(undefined); + const [objects, setObjects] = useState([]); + const [pageToken, setPageToken] = useState(null); + const [truncated, setTruncated] = useState(false); + const [selectedKeys, setSelectedKeys] = useState([]); + + const extension = useMemo(() => { + const exts = FileExtension[mediaType]; + return exts ? exts.join(',') : undefined; + }, [mediaType]); + + const { data: dsListData } = useQuery({ + queryKey: datasourceKey.list({ page: 1, size: 100 }), + queryFn: () => getDataSources({ page: 1, size: 100 }), + enabled: open, + }); + + const { isFetching } = useQuery({ + queryKey: datasourceKey.objectList({ ds_id: selectedDsId!, prefix, extension, page_token: null, size: 100 }), + queryFn: async () => { + const res = await listS3Objects({ ds_id: selectedDsId!, prefix, extension, page_token: null, size: 100 }); + setObjects(res.data.objects); + setPageToken(res.data.next_page_token ?? null); + setTruncated(res.data.truncated); + return res; + }, + enabled: open && !!selectedDsId, + }); + + const importMutation = useImportS3SamplesMutation(taskId); + + const handleLoadMore = useCallback(async () => { + if (!selectedDsId || !pageToken) return; + const res = await listS3Objects({ ds_id: selectedDsId, prefix, extension, page_token: pageToken, size: 100 }); + setObjects((prev) => [...prev, ...res.data.objects]); + setPageToken(res.data.next_page_token ?? null); + setTruncated(res.data.truncated); + }, [selectedDsId, prefix, extension, pageToken]); + + const handleDsChange = (dsId: number) => { + setSelectedDsId(dsId); + setPrefix(undefined); + setObjects([]); + setPageToken(null); + setTruncated(false); + setSelectedKeys([]); + }; + + const handleFolderClick = (key: string) => { + setPrefix(key); + setObjects([]); + setPageToken(null); + setTruncated(false); + setSelectedKeys([]); + }; + + const prefixSegments = useMemo(() => { + if (!prefix) return []; + const parts = prefix.replace(/\/$/, '').split('/'); + return parts.map((part, i) => ({ + label: part, + prefix: parts.slice(0, i + 1).join('/') + '/', + })); + }, [prefix]); + + const isFolder = (key: string) => key.endsWith('/'); + + const handleImport = () => { + if (!selectedDsId || selectedKeys.length === 0) return; + importMutation.mutate( + { data_source_id: selectedDsId, object_keys: selectedKeys }, + { + onSuccess: () => { + message.success(t('importSuccess').replace('{count}', String(selectedKeys.length))); + const fileNames = selectedKeys.map((key) => key.split('/').pop() ?? key); + setSelectedKeys([]); + onImportSuccess(fileNames); + onClose(); + }, + }, + ); + }; + + const handleImportAll = () => { + if (!selectedDsId) return; + const currentFileNames = objects.filter((o) => !isFolder(o.key)).map((o) => o.key.split('/').pop() ?? o.key); + importMutation.mutate( + { data_source_id: selectedDsId, prefix: prefix ?? '', extension }, + { + onSuccess: (res) => { + const count = res?.data?.ids?.length ?? 0; + message.success(t('importSuccess').replace('{count}', String(count))); + setSelectedKeys([]); + onImportSuccess(count > 0 ? (currentFileNames.length > 0 ? currentFileNames : [`${count} files`]) : []); + onClose(); + }, + }, + ); + }; + + const columns = [ + { + title: t('filename'), + dataIndex: 'key', + key: 'key', + render: (key: string) => { + const name = key.replace(prefix ?? '', ''); + if (isFolder(key)) { + return ( + + ); + } + return name; + }, + }, + { + title: t('fileSize'), + dataIndex: 'size', + key: 'size', + width: 120, + render: (size: number, record: S3ObjectItem) => (isFolder(record.key) ? '-' : formatFileSize(size)), + }, + { + title: t('lastModified'), + dataIndex: 'last_modified', + key: 'last_modified', + width: 180, + render: (v: string) => (v ? formatter.format('dateTime', v, { style: 'YYYY-MM-DD HH:mm' }) : '-'), + }, + ]; + + const rowSelection = { + selectedRowKeys: selectedKeys, + onChange: (keys: React.Key[]) => setSelectedKeys(keys as string[]), + getCheckboxProps: (record: S3ObjectItem) => ({ + disabled: isFolder(record.key), + }), + }; + + return ( + + + {selectedKeys.length > 0 && `${selectedKeys.length} ${t('select')}`} + + + + + + + } + destroyOnClose + > + + +
+ + {truncated && ( + + )} + + )} + + + ); +}; + +export default S3ImportModal; diff --git a/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/index.tsx b/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/index.tsx index 11c18d965..2111427b6 100644 --- a/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/index.tsx +++ b/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/index.tsx @@ -1,9 +1,15 @@ -import { useMemo, useCallback, useContext } from 'react'; +import { useMemo, useCallback, useContext, useState } from 'react'; import type { TableColumnType } from 'antd'; import { Popconfirm, Button, Table, Tooltip, Tag } from 'antd'; import _ from 'lodash-es'; import formatter from '@labelu/formatter'; -import { FileOutlined, FolderOpenOutlined, QuestionCircleOutlined, UploadOutlined } from '@ant-design/icons'; +import { + FileOutlined, + FolderOpenOutlined, + CloudServerOutlined, + QuestionCircleOutlined, + UploadOutlined, +} from '@ant-design/icons'; import type { RcFile } from 'antd/lib/upload/interface'; import { FlexLayout } from '@labelu/components-react'; import { useRevalidator } from 'react-router'; @@ -33,6 +39,7 @@ import videoJsonSchema from './videoPreAnnotationJson.schema.json'; import audioSchema from './audioPreAnnotationJsonl.schema.json'; import videoSchema from './videoPreAnnotationJsonl.schema.json'; import { isCorrectFiles, isPreAnnotationFile, normalizeFiles, readFile, UploadStatus } from './utils'; +import S3ImportModal from './S3ImportModal'; const jsonlMapping = { [MediaType.IMAGE]: imageSchema, @@ -69,6 +76,7 @@ const InputData = () => { const uploadMutation = useUploadFileMutation(); const revalidator = useRevalidator(); const { t, i18n } = useTranslation(); + const [s3ImportOpen, setS3ImportOpen] = useState(false); const statusTextMapping = useMemo( () => ({ @@ -458,6 +466,13 @@ const InputData = () => { +

{t('importFromS3')}

+ + +
{t('importFromS3Description')}
+
{fileQueue.length > 0 && ( @@ -489,6 +504,27 @@ const InputData = () => { + {taskId && task.media_type && ( + setS3ImportOpen(false)} + taskId={taskId} + mediaType={task.media_type} + onImportSuccess={(fileNames) => { + setFileQueue((prev) => [ + ...prev, + ...fileNames.map((name) => ({ + uid: `s3-${Date.now()}-${name}`, + name, + size: 0, + status: UploadStatus.Success, + file: new File([], name), + })), + ]); + revalidator.revalidate(); + }} + /> + )} ); }; diff --git a/apps/frontend/src/pages/tasks.[id].samples.[id]/components/annotationRightCorner/index.tsx b/apps/frontend/src/pages/tasks.[id].samples.[id]/components/annotationRightCorner/index.tsx index 24a31ffd2..61ae20ca5 100644 --- a/apps/frontend/src/pages/tasks.[id].samples.[id]/components/annotationRightCorner/index.tsx +++ b/apps/frontend/src/pages/tasks.[id].samples.[id]/components/annotationRightCorner/index.tsx @@ -1,4 +1,4 @@ -import { useEffect, useCallback, useContext } from 'react'; +import { useEffect, useCallback, useContext, useState } from 'react'; import { useNavigate, useParams, useRevalidator, useRouteLoaderData, useSearchParams } from 'react-router-dom'; import { Button, Tooltip } from 'antd'; import _, { debounce } from 'lodash-es'; @@ -9,12 +9,13 @@ import { useHotkeys } from 'react-hotkeys-hook'; import { FlexLayout } from '@labelu/components-react'; import { QuestionCircleOutlined } from '@ant-design/icons'; +import { ReactComponent as SparklesIcon } from '@/assets/svg/spark.svg'; import commonController from '@/utils/common'; import { imageAnnotationRef, videoAnnotationRef, audioAnnotationRef } from '@/pages/tasks.[id].samples.[id]'; import type { SampleListResponse, SampleResponse } from '@/api/types'; import { MediaType, SampleState } from '@/api/types'; import type { getSample } from '@/api/services/samples'; -import { updateSampleState, updateSampleAnnotationResult } from '@/api/services/samples'; +import { autoLabelSample, updateSampleState, updateSampleAnnotationResult } from '@/api/services/samples'; import { message } from '@/StaticAnt'; import useMe from '@/hooks/useMe'; import { UserAvatar } from '@/components/UserAvatar'; @@ -85,6 +86,7 @@ const AnnotationRightCorner = ({ noSave, fetchNext, totalSize, isLastPage }: Ann const { t } = useTranslation(); const me = useMe(); const isMeTheCurrentUser = currentEditingUser && me.data && currentEditingUser?.user_id === me.data?.id; + const [isAutoLabeling, setIsAutoLabeling] = useState(false); // 第一次进入就是40的倍数时,获取下一页数据 useEffect(() => { @@ -370,6 +372,30 @@ const AnnotationRightCorner = ({ noSave, fetchNext, totalSize, isLastPage }: Ann saveCurrentSample, ]); + const handleAutoLabel = useCallback(async () => { + if (noSave || !isMeTheCurrentUser || !taskId || !sampleId || task?.media_type !== MediaType.IMAGE) { + return; + } + + setIsAutoLabeling(true); + try { + const response = await autoLabelSample(+taskId, +sampleId, { + overwrite: true, + }); + await revalidator.revalidate(); + if (response.data.warning_message) { + message.warning(response.data.warning_message); + } else { + message.success(t('aiAutoLabelSuccess')); + } + } catch (error: any) { + const backendMsg = error?.response?.data?.msg; + commonController.notificationErrorMessage({ message: backendMsg || t('aiAutoLabelFailed') }, 2); + } finally { + setIsAutoLabeling(false); + } + }, [isMeTheCurrentUser, noSave, revalidator, sampleId, t, task?.media_type, taskId]); + const handlePrevSample = useCallback(async () => { if (sampleIndex === 0) { return; @@ -509,6 +535,17 @@ const AnnotationRightCorner = ({ noSave, fetchNext, totalSize, isLastPage }: Ann )} + {task?.media_type === MediaType.IMAGE && ( + + )} {isSampleSkipped ? ( + )} {isSampleSkipped ? ( - + + + + + {task?.media_type === MediaType.IMAGE && ( + + )} + {batchProgress && ( + 0 ? 'exception' : 'active'} + style={{ width: 200, display: 'inline-flex' }} + format={() => ( + + + {batchProgress.success} + + + {batchProgress.failed} + + / {batchProgress.total} + + )} + /> + )} + Date: Mon, 20 Apr 2026 19:53:54 +0800 Subject: [PATCH 14/45] update(i18n): update translates --- packages/i18n/src/locales/en-US.json | 6 +++++- packages/i18n/src/locales/zh-CN.json | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/i18n/src/locales/en-US.json b/packages/i18n/src/locales/en-US.json index 583d87a5a..86402079f 100644 --- a/packages/i18n/src/locales/en-US.json +++ b/packages/i18n/src/locales/en-US.json @@ -406,5 +406,9 @@ "aiAutoLabeling": "AI Annotating...", "aiAutoLabelSuccess": "AI annotation completed", "aiAutoLabelFailed": "AI annotation failed", - "filterByLabels": "Only keep configured labels" + "filterByLabels": "Only keep configured labels", + "batchAutoLabel": "Batch AI Annotate", + "batchAutoLabelStarted": "Batch annotation job started", + "batchAutoLabelCompleted": "Batch annotation completed: {{success}} succeeded, {{failed}} failed", + "batchAutoLabelNoSamples": "No unannotated samples" } diff --git a/packages/i18n/src/locales/zh-CN.json b/packages/i18n/src/locales/zh-CN.json index a521a3256..296e6852a 100644 --- a/packages/i18n/src/locales/zh-CN.json +++ b/packages/i18n/src/locales/zh-CN.json @@ -404,5 +404,9 @@ "aiAutoLabeling": "AI 标注中...", "aiAutoLabelSuccess": "AI 标注完成", "aiAutoLabelFailed": "AI 标注失败", - "filterByLabels": "只保留配置标签" + "filterByLabels": "只保留配置标签", + "batchAutoLabel": "AI 批量标注", + "batchAutoLabelStarted": "批量标注任务已开始", + "batchAutoLabelCompleted": "批量标注完成,成功 {{success}} 个,失败 {{failed}} 个", + "batchAutoLabelNoSamples": "没有未标注的样本" } From 9ab69693a031612e7c47ea855125a49f42464550 Mon Sep 17 00:00:00 2001 From: shlab Date: Tue, 21 Apr 2026 11:46:02 +0800 Subject: [PATCH 15/45] update(frontend): update ui --- .../components/annotationRightCorner/index.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/frontend/src/pages/tasks.[id].samples.[id]/components/annotationRightCorner/index.tsx b/apps/frontend/src/pages/tasks.[id].samples.[id]/components/annotationRightCorner/index.tsx index f517aadc7..6d5932966 100644 --- a/apps/frontend/src/pages/tasks.[id].samples.[id]/components/annotationRightCorner/index.tsx +++ b/apps/frontend/src/pages/tasks.[id].samples.[id]/components/annotationRightCorner/index.tsx @@ -565,8 +565,10 @@ const AnnotationRightCorner = ({ noSave, fetchNext, totalSize, isLastPage }: Ann ], }} > - - {isAutoLabeling ? t('aiAutoLabeling') : t('aiAutoLabel')} + + + {isAutoLabeling ? t('aiAutoLabeling') : t('aiAutoLabel')} + )} {isSampleSkipped ? ( From 224ee72e090b6f7f3a4dc135b67ac2a00de420b2 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 04:01:33 +0000 Subject: [PATCH 16/45] chore(release): 1.6.1 [skip ci] ## @labelu/audio-react [1.6.1](https://github.com/opendatalab/labelU-Kit/compare/@labelu/audio-react@1.6.0...@labelu/audio-react@1.6.1) (2026-04-21) ### Dependencies * **@labelu/components-react:** upgraded to 1.8.1 --- packages/audio-react/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/audio-react/package.json b/packages/audio-react/package.json index c452efcb5..af784e7ae 100644 --- a/packages/audio-react/package.json +++ b/packages/audio-react/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/audio-react", - "version": "1.6.0", + "version": "1.6.1", "description": "labelu audio annotation component for react", "main": "./dist/index.mjs", "module": "./dist/index.mjs", @@ -40,7 +40,7 @@ "vite-tsconfig-paths": "^3.5.0" }, "dependencies": { - "@labelu/components-react": "1.8.0", + "@labelu/components-react": "1.8.1", "polished": "^4.2.2", "react-hotkeys-hook": "^4.4.1", "styled-components": "^6.1.15", From ccbef3d0937e9bac27a6d1b13e27eeb08551115d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 04:01:37 +0000 Subject: [PATCH 17/45] chore(release): 1.9.1 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [1.9.1](https://github.com/opendatalab/labelU-Kit/compare/@labelu/audio-annotator-react@1.9.0...@labelu/audio-annotator-react@1.9.1) (2026-04-21) ### Bug Fixes * **audio-annotator-react:** replace noneLabel to input label ([c84291a](https://github.com/opendatalab/labelU-Kit/commit/c84291aa23ec15447e27df7af0f3959fb97c5469)) * **frontend:** fix [#245](https://github.com/opendatalab/labelU-Kit/issues/245) ([68a3425](https://github.com/opendatalab/labelU-Kit/commit/68a3425aac2cd71972e3cd2fcc7deb911eaba7ae)) * **i18n:** update translation ([730d3e4](https://github.com/opendatalab/labelU-Kit/commit/730d3e4fc9aa4b82aa7f790b951cd10eceb18737)) * **image-annotator-react:** replace noneLabel to input label ([48fe581](https://github.com/opendatalab/labelU-Kit/commit/48fe581a511e1a7bf980289adb640cdd6f4a2f8c)) * **image, image-annotator-react:** 修复浏览器缩放/全屏切换后标注框位置偏移 ([107f353](https://github.com/opendatalab/labelU-Kit/commit/107f3533233c3e889d9769ca22bafb25f8fda882)) * **image:** replace noneLabel to input label ([645ee26](https://github.com/opendatalab/labelU-Kit/commit/645ee262e1bf57eac63753057c3cc2a3b4641419)) * make file extension check case-insensitive in isCorrectFileType ([6ed8ca2](https://github.com/opendatalab/labelU-Kit/commit/6ed8ca2adc09525ba712eb73227f2a4e2cecb81a)) ### Features * **frontend:** add s3 datasrouce and ai annotation ([0d3f2f8](https://github.com/opendatalab/labelU-Kit/commit/0d3f2f8913d79405d6ce70f58546fbd8e086a9e8)) ### Reverts * Revert "fix(audio-annotator-react): replace noneLabel to input label" ([e1629a2](https://github.com/opendatalab/labelU-Kit/commit/e1629a253b71b120f650571af938c250c4956d7b)) --- packages/audio-annotator-react/package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/audio-annotator-react/package.json b/packages/audio-annotator-react/package.json index c17df6b78..ff6b95916 100644 --- a/packages/audio-annotator-react/package.json +++ b/packages/audio-annotator-react/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/audio-annotator-react", - "version": "1.9.0", + "version": "1.9.1", "description": "audio annotator for react", "main": "./dist/index.mjs", "module": "./dist/index.mjs", @@ -28,9 +28,9 @@ "react" ], "dependencies": { - "@labelu/i18n": "1.1.0", - "@labelu/audio-react": "1.6.0", - "@labelu/components-react": "1.8.0", + "@labelu/i18n": "1.1.1", + "@labelu/audio-react": "1.6.1", + "@labelu/components-react": "1.8.1", "@labelu/interface": "1.3.1", "lodash.clonedeep": "^4.5.0", "polished": "^4.2.2", From 387693ccd1775482e2b75f26c9dbde344c85486c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 04:01:42 +0000 Subject: [PATCH 18/45] chore(release): 1.8.1 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [1.8.1](https://github.com/opendatalab/labelU-Kit/compare/@labelu/components-react@1.8.0...@labelu/components-react@1.8.1) (2026-04-21) ### Bug Fixes * **audio-annotator-react:** replace noneLabel to input label ([c84291a](https://github.com/opendatalab/labelU-Kit/commit/c84291aa23ec15447e27df7af0f3959fb97c5469)) * **frontend:** fix [#245](https://github.com/opendatalab/labelU-Kit/issues/245) ([68a3425](https://github.com/opendatalab/labelU-Kit/commit/68a3425aac2cd71972e3cd2fcc7deb911eaba7ae)) * **i18n:** update translation ([730d3e4](https://github.com/opendatalab/labelU-Kit/commit/730d3e4fc9aa4b82aa7f790b951cd10eceb18737)) * **image-annotator-react:** replace noneLabel to input label ([48fe581](https://github.com/opendatalab/labelU-Kit/commit/48fe581a511e1a7bf980289adb640cdd6f4a2f8c)) * **image, image-annotator-react:** 修复浏览器缩放/全屏切换后标注框位置偏移 ([107f353](https://github.com/opendatalab/labelU-Kit/commit/107f3533233c3e889d9769ca22bafb25f8fda882)) * **image:** replace noneLabel to input label ([645ee26](https://github.com/opendatalab/labelU-Kit/commit/645ee262e1bf57eac63753057c3cc2a3b4641419)) * make file extension check case-insensitive in isCorrectFileType ([6ed8ca2](https://github.com/opendatalab/labelU-Kit/commit/6ed8ca2adc09525ba712eb73227f2a4e2cecb81a)) ### Features * **frontend:** add s3 datasrouce and ai annotation ([0d3f2f8](https://github.com/opendatalab/labelU-Kit/commit/0d3f2f8913d79405d6ce70f58546fbd8e086a9e8)) ### Reverts * Revert "fix(audio-annotator-react): replace noneLabel to input label" ([e1629a2](https://github.com/opendatalab/labelU-Kit/commit/e1629a253b71b120f650571af938c250c4956d7b)) --- packages/components-react/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components-react/package.json b/packages/components-react/package.json index d22afa67f..3401d505f 100644 --- a/packages/components-react/package.json +++ b/packages/components-react/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/components-react", - "version": "1.8.0", + "version": "1.8.1", "description": "basic react components for labelU", "main": "./dist/index.mjs", "module": "./dist/index.mjs", @@ -35,7 +35,7 @@ "react" ], "dependencies": { - "@labelu/i18n": "1.1.0", + "@labelu/i18n": "1.1.1", "polished": "^4.2.2", "rc-collapse": "^3.7.1", "rc-dialog": "^9.2.0", From 1cd60ce217f6a4242f8e82e5a911ad96035551fe Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 04:01:46 +0000 Subject: [PATCH 19/45] chore(release): 1.1.1 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [1.1.1](https://github.com/opendatalab/labelU-Kit/compare/@labelu/i18n@1.1.0...@labelu/i18n@1.1.1) (2026-04-21) ### Bug Fixes * **audio-annotator-react:** replace noneLabel to input label ([c84291a](https://github.com/opendatalab/labelU-Kit/commit/c84291aa23ec15447e27df7af0f3959fb97c5469)) * **frontend:** fix [#245](https://github.com/opendatalab/labelU-Kit/issues/245) ([68a3425](https://github.com/opendatalab/labelU-Kit/commit/68a3425aac2cd71972e3cd2fcc7deb911eaba7ae)) * **i18n:** update translation ([730d3e4](https://github.com/opendatalab/labelU-Kit/commit/730d3e4fc9aa4b82aa7f790b951cd10eceb18737)) * **image-annotator-react:** replace noneLabel to input label ([48fe581](https://github.com/opendatalab/labelU-Kit/commit/48fe581a511e1a7bf980289adb640cdd6f4a2f8c)) * **image, image-annotator-react:** 修复浏览器缩放/全屏切换后标注框位置偏移 ([107f353](https://github.com/opendatalab/labelU-Kit/commit/107f3533233c3e889d9769ca22bafb25f8fda882)) * **image:** replace noneLabel to input label ([645ee26](https://github.com/opendatalab/labelU-Kit/commit/645ee262e1bf57eac63753057c3cc2a3b4641419)) * make file extension check case-insensitive in isCorrectFileType ([6ed8ca2](https://github.com/opendatalab/labelU-Kit/commit/6ed8ca2adc09525ba712eb73227f2a4e2cecb81a)) ### Features * **frontend:** add s3 datasrouce and ai annotation ([0d3f2f8](https://github.com/opendatalab/labelU-Kit/commit/0d3f2f8913d79405d6ce70f58546fbd8e086a9e8)) ### Reverts * Revert "fix(audio-annotator-react): replace noneLabel to input label" ([e1629a2](https://github.com/opendatalab/labelU-Kit/commit/e1629a253b71b120f650571af938c250c4956d7b)) --- packages/i18n/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 1320b5646..7c4857f52 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/i18n", - "version": "1.1.0", + "version": "1.1.1", "description": "i18n for labelu and components", "scripts": { "build": "vite build && npm run build:types", From dc465c754fa7ab67047e823251404dc4426986a5 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 04:01:51 +0000 Subject: [PATCH 20/45] chore(release): 1.5.1 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [1.5.1](https://github.com/opendatalab/labelU-Kit/compare/@labelu/image@1.5.0...@labelu/image@1.5.1) (2026-04-21) ### Bug Fixes * **audio-annotator-react:** replace noneLabel to input label ([c84291a](https://github.com/opendatalab/labelU-Kit/commit/c84291aa23ec15447e27df7af0f3959fb97c5469)) * **frontend:** fix [#245](https://github.com/opendatalab/labelU-Kit/issues/245) ([68a3425](https://github.com/opendatalab/labelU-Kit/commit/68a3425aac2cd71972e3cd2fcc7deb911eaba7ae)) * **i18n:** update translation ([730d3e4](https://github.com/opendatalab/labelU-Kit/commit/730d3e4fc9aa4b82aa7f790b951cd10eceb18737)) * **image-annotator-react:** replace noneLabel to input label ([48fe581](https://github.com/opendatalab/labelU-Kit/commit/48fe581a511e1a7bf980289adb640cdd6f4a2f8c)) * **image, image-annotator-react:** 修复浏览器缩放/全屏切换后标注框位置偏移 ([107f353](https://github.com/opendatalab/labelU-Kit/commit/107f3533233c3e889d9769ca22bafb25f8fda882)) * **image:** replace noneLabel to input label ([645ee26](https://github.com/opendatalab/labelU-Kit/commit/645ee262e1bf57eac63753057c3cc2a3b4641419)) * make file extension check case-insensitive in isCorrectFileType ([6ed8ca2](https://github.com/opendatalab/labelU-Kit/commit/6ed8ca2adc09525ba712eb73227f2a4e2cecb81a)) ### Features * **frontend:** add s3 datasrouce and ai annotation ([0d3f2f8](https://github.com/opendatalab/labelU-Kit/commit/0d3f2f8913d79405d6ce70f58546fbd8e086a9e8)) ### Reverts * Revert "fix(audio-annotator-react): replace noneLabel to input label" ([e1629a2](https://github.com/opendatalab/labelU-Kit/commit/e1629a253b71b120f650571af938c250c4956d7b)) --- packages/image/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/image/package.json b/packages/image/package.json index 9388f0d77..bcd55b870 100644 --- a/packages/image/package.json +++ b/packages/image/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/image", - "version": "1.5.0", + "version": "1.5.1", "description": "Image annotation tool for labelU", "author": { "name": "GaryShen", From 290300f8af40dab98c83892200ec8e7d26756224 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 04:01:55 +0000 Subject: [PATCH 21/45] chore(release): 2.5.1 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [2.5.1](https://github.com/opendatalab/labelU-Kit/compare/@labelu/image-annotator-react@2.5.0...@labelu/image-annotator-react@2.5.1) (2026-04-21) ### Bug Fixes * **audio-annotator-react:** replace noneLabel to input label ([c84291a](https://github.com/opendatalab/labelU-Kit/commit/c84291aa23ec15447e27df7af0f3959fb97c5469)) * **frontend:** fix [#245](https://github.com/opendatalab/labelU-Kit/issues/245) ([68a3425](https://github.com/opendatalab/labelU-Kit/commit/68a3425aac2cd71972e3cd2fcc7deb911eaba7ae)) * **i18n:** update translation ([730d3e4](https://github.com/opendatalab/labelU-Kit/commit/730d3e4fc9aa4b82aa7f790b951cd10eceb18737)) * **image-annotator-react:** replace noneLabel to input label ([48fe581](https://github.com/opendatalab/labelU-Kit/commit/48fe581a511e1a7bf980289adb640cdd6f4a2f8c)) * **image, image-annotator-react:** 修复浏览器缩放/全屏切换后标注框位置偏移 ([107f353](https://github.com/opendatalab/labelU-Kit/commit/107f3533233c3e889d9769ca22bafb25f8fda882)) * **image:** replace noneLabel to input label ([645ee26](https://github.com/opendatalab/labelU-Kit/commit/645ee262e1bf57eac63753057c3cc2a3b4641419)) * make file extension check case-insensitive in isCorrectFileType ([6ed8ca2](https://github.com/opendatalab/labelU-Kit/commit/6ed8ca2adc09525ba712eb73227f2a4e2cecb81a)) ### Features * **frontend:** add s3 datasrouce and ai annotation ([0d3f2f8](https://github.com/opendatalab/labelU-Kit/commit/0d3f2f8913d79405d6ce70f58546fbd8e086a9e8)) ### Reverts * Revert "fix(audio-annotator-react): replace noneLabel to input label" ([e1629a2](https://github.com/opendatalab/labelU-Kit/commit/e1629a253b71b120f650571af938c250c4956d7b)) --- packages/image-annotator-react/package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/image-annotator-react/package.json b/packages/image-annotator-react/package.json index 5d3710f1f..a3b0a385b 100644 --- a/packages/image-annotator-react/package.json +++ b/packages/image-annotator-react/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/image-annotator-react", - "version": "2.5.0", + "version": "2.5.1", "description": "image annotator for react", "main": "./dist/index.mjs", "module": "./dist/index.mjs", @@ -29,10 +29,10 @@ "react" ], "dependencies": { - "@labelu/components-react": "1.8.0", - "@labelu/image": "1.5.0", + "@labelu/components-react": "1.8.1", + "@labelu/image": "1.5.1", "@labelu/interface": "1.3.1", - "@labelu/i18n": "1.1.0", + "@labelu/i18n": "1.1.1", "lodash.clonedeep": "^4.5.0", "polished": "^4.2.2", "react-hotkeys-hook": "^4.4.1", From 1fa7c02c5c7f58dba9e31484a9708a3ceb9b5957 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 04:01:59 +0000 Subject: [PATCH 22/45] chore(release): 1.5.1 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [1.5.1](https://github.com/opendatalab/labelU-Kit/compare/@labelu/video-annotator-react@1.5.0...@labelu/video-annotator-react@1.5.1) (2026-04-21) ### Bug Fixes * **audio-annotator-react:** replace noneLabel to input label ([c84291a](https://github.com/opendatalab/labelU-Kit/commit/c84291aa23ec15447e27df7af0f3959fb97c5469)) * **frontend:** fix [#245](https://github.com/opendatalab/labelU-Kit/issues/245) ([68a3425](https://github.com/opendatalab/labelU-Kit/commit/68a3425aac2cd71972e3cd2fcc7deb911eaba7ae)) * **i18n:** update translation ([730d3e4](https://github.com/opendatalab/labelU-Kit/commit/730d3e4fc9aa4b82aa7f790b951cd10eceb18737)) * **image-annotator-react:** replace noneLabel to input label ([48fe581](https://github.com/opendatalab/labelU-Kit/commit/48fe581a511e1a7bf980289adb640cdd6f4a2f8c)) * **image, image-annotator-react:** 修复浏览器缩放/全屏切换后标注框位置偏移 ([107f353](https://github.com/opendatalab/labelU-Kit/commit/107f3533233c3e889d9769ca22bafb25f8fda882)) * **image:** replace noneLabel to input label ([645ee26](https://github.com/opendatalab/labelU-Kit/commit/645ee262e1bf57eac63753057c3cc2a3b4641419)) * make file extension check case-insensitive in isCorrectFileType ([6ed8ca2](https://github.com/opendatalab/labelU-Kit/commit/6ed8ca2adc09525ba712eb73227f2a4e2cecb81a)) ### Features * **frontend:** add s3 datasrouce and ai annotation ([0d3f2f8](https://github.com/opendatalab/labelU-Kit/commit/0d3f2f8913d79405d6ce70f58546fbd8e086a9e8)) ### Reverts * Revert "fix(audio-annotator-react): replace noneLabel to input label" ([e1629a2](https://github.com/opendatalab/labelU-Kit/commit/e1629a253b71b120f650571af938c250c4956d7b)) --- packages/video-annotator-react/package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/video-annotator-react/package.json b/packages/video-annotator-react/package.json index f0fdaebb8..5a82e023e 100644 --- a/packages/video-annotator-react/package.json +++ b/packages/video-annotator-react/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/video-annotator-react", - "version": "1.5.0", + "version": "1.5.1", "description": "video annotator for react", "main": "./dist/index.mjs", "module": "./dist/index.mjs", @@ -29,11 +29,11 @@ "react" ], "dependencies": { - "@labelu/components-react": "1.8.0", + "@labelu/components-react": "1.8.1", "@labelu/interface": "1.3.1", - "@labelu/i18n": "1.1.0", - "@labelu/audio-annotator-react": "1.9.0", - "@labelu/video-react": "1.6.0", + "@labelu/i18n": "1.1.1", + "@labelu/audio-annotator-react": "1.9.1", + "@labelu/video-react": "1.6.1", "polished": "^4.2.2", "react-hotkeys-hook": "^4.4.1", "styled-components": "^6.1.15" From 97981ef699caf2627712848a9155c2c762953f16 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 04:02:04 +0000 Subject: [PATCH 23/45] chore(release): 1.6.1 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## [1.6.1](https://github.com/opendatalab/labelU-Kit/compare/@labelu/video-react@1.6.0...@labelu/video-react@1.6.1) (2026-04-21) ### Bug Fixes * **audio-annotator-react:** replace noneLabel to input label ([c84291a](https://github.com/opendatalab/labelU-Kit/commit/c84291aa23ec15447e27df7af0f3959fb97c5469)) * **frontend:** fix [#245](https://github.com/opendatalab/labelU-Kit/issues/245) ([68a3425](https://github.com/opendatalab/labelU-Kit/commit/68a3425aac2cd71972e3cd2fcc7deb911eaba7ae)) * **i18n:** update translation ([730d3e4](https://github.com/opendatalab/labelU-Kit/commit/730d3e4fc9aa4b82aa7f790b951cd10eceb18737)) * **image-annotator-react:** replace noneLabel to input label ([48fe581](https://github.com/opendatalab/labelU-Kit/commit/48fe581a511e1a7bf980289adb640cdd6f4a2f8c)) * **image, image-annotator-react:** 修复浏览器缩放/全屏切换后标注框位置偏移 ([107f353](https://github.com/opendatalab/labelU-Kit/commit/107f3533233c3e889d9769ca22bafb25f8fda882)) * **image:** replace noneLabel to input label ([645ee26](https://github.com/opendatalab/labelU-Kit/commit/645ee262e1bf57eac63753057c3cc2a3b4641419)) * make file extension check case-insensitive in isCorrectFileType ([6ed8ca2](https://github.com/opendatalab/labelU-Kit/commit/6ed8ca2adc09525ba712eb73227f2a4e2cecb81a)) ### Features * **frontend:** add s3 datasrouce and ai annotation ([0d3f2f8](https://github.com/opendatalab/labelU-Kit/commit/0d3f2f8913d79405d6ce70f58546fbd8e086a9e8)) ### Reverts * Revert "fix(audio-annotator-react): replace noneLabel to input label" ([e1629a2](https://github.com/opendatalab/labelU-Kit/commit/e1629a253b71b120f650571af938c250c4956d7b)) --- packages/video-react/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/video-react/package.json b/packages/video-react/package.json index 15b0845ff..8f04b0d80 100644 --- a/packages/video-react/package.json +++ b/packages/video-react/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/video-react", - "version": "1.6.0", + "version": "1.6.1", "description": "labelu video annotation component for react", "main": "./dist/index.mjs", "module": "./dist/index.mjs", @@ -39,7 +39,7 @@ "styled-components": "^6.1.15" }, "dependencies": { - "@labelu/components-react": "1.8.0", + "@labelu/components-react": "1.8.1", "polished": "^4.2.2", "rc-tooltip": "^6.0.1", "react-hotkeys-hook": "^4.4.1", From c30626181e353a2b5ef83a4d5f51b07ec3c0bd9f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 04:04:59 +0000 Subject: [PATCH 24/45] chore(release): 5.10.0 [skip ci] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # [5.10.0](https://github.com/opendatalab/labelU-Kit/compare/v5.9.1...v5.10.0) (2026-04-21) ### Bug Fixes * **audio-annotator-react:** replace noneLabel to input label ([c84291a](https://github.com/opendatalab/labelU-Kit/commit/c84291aa23ec15447e27df7af0f3959fb97c5469)) * **i18n:** update translation ([730d3e4](https://github.com/opendatalab/labelU-Kit/commit/730d3e4fc9aa4b82aa7f790b951cd10eceb18737)) * **image-annotator-react:** replace noneLabel to input label ([48fe581](https://github.com/opendatalab/labelU-Kit/commit/48fe581a511e1a7bf980289adb640cdd6f4a2f8c)) * **image, image-annotator-react:** 修复浏览器缩放/全屏切换后标注框位置偏移 ([107f353](https://github.com/opendatalab/labelU-Kit/commit/107f3533233c3e889d9769ca22bafb25f8fda882)) * **image:** replace noneLabel to input label ([645ee26](https://github.com/opendatalab/labelU-Kit/commit/645ee262e1bf57eac63753057c3cc2a3b4641419)) * make file extension check case-insensitive in isCorrectFileType ([6ed8ca2](https://github.com/opendatalab/labelU-Kit/commit/6ed8ca2adc09525ba712eb73227f2a4e2cecb81a)) ### Features * **frontend:** add s3 datasrouce and ai annotation ([0d3f2f8](https://github.com/opendatalab/labelU-Kit/commit/0d3f2f8913d79405d6ce70f58546fbd8e086a9e8)) ### Reverts * Revert "fix(audio-annotator-react): replace noneLabel to input label" ([e1629a2](https://github.com/opendatalab/labelU-Kit/commit/e1629a253b71b120f650571af938c250c4956d7b)) --- apps/frontend/package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 384a62b6d..4e14e64ed 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -4,15 +4,15 @@ "private": true, "dependencies": { "@ant-design/icons": "^4.6.2", - "@labelu/i18n": "1.1.0", - "@labelu/audio-annotator-react": "1.9.0", - "@labelu/components-react": "1.8.0", - "@labelu/image": "1.5.0", + "@labelu/i18n": "1.1.1", + "@labelu/audio-annotator-react": "1.9.1", + "@labelu/components-react": "1.8.1", + "@labelu/image": "1.5.1", "@labelu/formatter": "1.0.2", - "@labelu/image-annotator-react": "2.5.0", + "@labelu/image-annotator-react": "2.5.1", "@labelu/interface": "1.3.1", - "@labelu/video-annotator-react": "1.5.0", - "@labelu/video-react": "1.6.0", + "@labelu/video-annotator-react": "1.5.1", + "@labelu/video-react": "1.6.1", "@tanstack/react-query": "^5.0.0", "antd": "5.10.1", "axios": "^1.3.4", From f1b8639f780fc887d24dba79900e39176576f136 Mon Sep 17 00:00:00 2001 From: gary Date: Tue, 21 Apr 2026 12:05:03 +0800 Subject: [PATCH 25/45] chore: update frontend package.json version to 5.10.0 [skip ci] --- apps/frontend/package.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 4e14e64ed..6dcdec66a 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/frontend", - "version": "5.9.1", + "version": "5.10.0", "private": true, "dependencies": { "@ant-design/icons": "^4.6.2", diff --git a/package.json b/package.json index 5cc59ad18..a7952f05a 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "packages/*", "apps/*" ], - "version": "5.9.1", + "version": "5.10.0", "scripts": { "prepare": "husky install", "build": "pnpm --filter @labelu/interface --filter @labelu/i18n --filter @labelu/formatter --filter @labelu/image --filter @labelu/components-react --filter @labelu/image-annotator-react --filter @labelu/audio-react --filter @labelu/video-react --filter @labelu/audio-annotator-react --filter @labelu/video-annotator-react build", From 83318272c1341c9736cb014bef0507a4b3e5ddca Mon Sep 17 00:00:00 2001 From: shlab Date: Tue, 21 Apr 2026 12:08:59 +0800 Subject: [PATCH 26/45] fix(website): build error --- apps/website/src/pages/image/index.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/website/src/pages/image/index.tsx b/apps/website/src/pages/image/index.tsx index c0a810509..718ebfe54 100644 --- a/apps/website/src/pages/image/index.tsx +++ b/apps/website/src/pages/image/index.tsx @@ -726,12 +726,6 @@ export default function ImagePage() { }; }, []); - const initialValues = useMemo(() => { - return { - tools: defaultConfig, - }; - }, []); - return ( <> Date: Tue, 21 Apr 2026 12:14:36 +0800 Subject: [PATCH 27/45] chore: update frontend package.json version to 5.10.1 [skip ci] --- apps/frontend/package.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 6dcdec66a..53fc0f9d8 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/frontend", - "version": "5.10.0", + "version": "5.10.1", "private": true, "dependencies": { "@ant-design/icons": "^4.6.2", diff --git a/package.json b/package.json index a7952f05a..39889cbc4 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "packages/*", "apps/*" ], - "version": "5.10.0", + "version": "5.10.1", "scripts": { "prepare": "husky install", "build": "pnpm --filter @labelu/interface --filter @labelu/i18n --filter @labelu/formatter --filter @labelu/image --filter @labelu/components-react --filter @labelu/image-annotator-react --filter @labelu/audio-react --filter @labelu/video-react --filter @labelu/audio-annotator-react --filter @labelu/video-annotator-react build", From 88979e64f5627e196e37627a0fc1aed5a75516dd Mon Sep 17 00:00:00 2001 From: shlab Date: Tue, 21 Apr 2026 12:53:21 +0800 Subject: [PATCH 28/45] fix(frontend): add vis3 link to s3 datasource --- apps/frontend/src/pages/datasources/index.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/apps/frontend/src/pages/datasources/index.tsx b/apps/frontend/src/pages/datasources/index.tsx index 2128b9c54..9f17172e9 100644 --- a/apps/frontend/src/pages/datasources/index.tsx +++ b/apps/frontend/src/pages/datasources/index.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { Button, Pagination, Popconfirm, Table, message } from 'antd'; +import { Alert, Button, Pagination, Popconfirm, Table, message } from 'antd'; import { PlusOutlined } from '@ant-design/icons'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useSearchParams } from 'react-router-dom'; @@ -139,6 +139,18 @@ const DataSources = () => { {t('createDataSource')} + + 如果想要更强大的S3数据可视化,试试{' '} + + vis3 + + + } + />
Date: Tue, 21 Apr 2026 13:00:24 +0800 Subject: [PATCH 29/45] chore: update frontend package.json version to 5.10.2 [skip ci] --- apps/frontend/package.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 53fc0f9d8..fe47f7fd3 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/frontend", - "version": "5.10.1", + "version": "5.10.2", "private": true, "dependencies": { "@ant-design/icons": "^4.6.2", diff --git a/package.json b/package.json index 39889cbc4..834877ee8 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "packages/*", "apps/*" ], - "version": "5.10.1", + "version": "5.10.2", "scripts": { "prepare": "husky install", "build": "pnpm --filter @labelu/interface --filter @labelu/i18n --filter @labelu/formatter --filter @labelu/image --filter @labelu/components-react --filter @labelu/image-annotator-react --filter @labelu/audio-react --filter @labelu/video-react --filter @labelu/audio-annotator-react --filter @labelu/video-annotator-react build", From fbf1838482c4eaf6ac0e2de6435869c181752883 Mon Sep 17 00:00:00 2001 From: shlab Date: Tue, 21 Apr 2026 17:29:27 +0800 Subject: [PATCH 30/45] fix(frontend): fix s3 datasource import --- apps/frontend/src/api/services/samples.ts | 1 + apps/frontend/src/pages/datasources/index.tsx | 2 +- .../partials/InputData/S3ImportModal.tsx | 15 ++++++++++----- .../tasks.[id].edit/partials/InputData/index.tsx | 8 +++++--- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/apps/frontend/src/api/services/samples.ts b/apps/frontend/src/api/services/samples.ts index 54a7b101a..05b90b185 100644 --- a/apps/frontend/src/api/services/samples.ts +++ b/apps/frontend/src/api/services/samples.ts @@ -90,6 +90,7 @@ export async function autoLabelSample( body: AutoLabelCommand = {}, ): Promise { return await request.post(`/v1/tasks/${taskId}/samples/${sampleId}/auto_label`, body, { + timeout: 5 * 60 * 1000, params: { sample_id: sampleId, }, diff --git a/apps/frontend/src/pages/datasources/index.tsx b/apps/frontend/src/pages/datasources/index.tsx index 9f17172e9..1bb0d2a28 100644 --- a/apps/frontend/src/pages/datasources/index.tsx +++ b/apps/frontend/src/pages/datasources/index.tsx @@ -144,7 +144,7 @@ const DataSources = () => { type="info" message={
- 如果想要更强大的S3数据可视化,试试{' '} + {t('s3VizTip')}{' '} vis3 diff --git a/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/S3ImportModal.tsx b/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/S3ImportModal.tsx index fdf244929..45fb8c5a1 100644 --- a/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/S3ImportModal.tsx +++ b/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/S3ImportModal.tsx @@ -20,7 +20,7 @@ interface S3ImportModalProps { onClose: () => void; taskId: number; mediaType: MediaType; - onImportSuccess: (fileNames: string[]) => void; + onImportSuccess: (fileNames: string[], sampleIds: number[]) => void; } function formatFileSize(bytes: number): string { @@ -105,11 +105,12 @@ const S3ImportModal = ({ open, onClose, taskId, mediaType, onImportSuccess }: S3 importMutation.mutate( { data_source_id: selectedDsId, object_keys: selectedKeys }, { - onSuccess: () => { + onSuccess: (res) => { message.success(t('importSuccess').replace('{count}', String(selectedKeys.length))); const fileNames = selectedKeys.map((key) => key.split('/').pop() ?? key); + const sampleIds = res?.data?.ids ?? []; setSelectedKeys([]); - onImportSuccess(fileNames); + onImportSuccess(fileNames, sampleIds); onClose(); }, }, @@ -123,10 +124,14 @@ const S3ImportModal = ({ open, onClose, taskId, mediaType, onImportSuccess }: S3 { data_source_id: selectedDsId, prefix: prefix ?? '', extension }, { onSuccess: (res) => { - const count = res?.data?.ids?.length ?? 0; + const sampleIds = res?.data?.ids ?? []; + const count = sampleIds.length; message.success(t('importSuccess').replace('{count}', String(count))); setSelectedKeys([]); - onImportSuccess(count > 0 ? (currentFileNames.length > 0 ? currentFileNames : [`${count} files`]) : []); + onImportSuccess( + count > 0 ? (currentFileNames.length > 0 ? currentFileNames : [`${count} files`]) : [], + sampleIds, + ); onClose(); }, }, diff --git a/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/index.tsx b/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/index.tsx index 2111427b6..eb423b7de 100644 --- a/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/index.tsx +++ b/apps/frontend/src/pages/tasks.[id].edit/partials/InputData/index.tsx @@ -335,6 +335,7 @@ const InputData = () => { responsive: ['md', 'lg'], key: 'url', render: (text: string) => { + if (!text) return '-'; return formatter.format('ellipsis', `${location.protocol}//${location.host}${text}`, { maxWidth: 160, type: 'tooltip', @@ -489,7 +490,7 @@ const InputData = () => { {amountMapping.succeeded} - 个, + {t('uploadSuccessCount')} {t('uploadFailed')} @@ -510,15 +511,16 @@ const InputData = () => { onClose={() => setS3ImportOpen(false)} taskId={taskId} mediaType={task.media_type} - onImportSuccess={(fileNames) => { + onImportSuccess={(fileNames, sampleIds) => { setFileQueue((prev) => [ ...prev, - ...fileNames.map((name) => ({ + ...fileNames.map((name, index) => ({ uid: `s3-${Date.now()}-${name}`, name, size: 0, status: UploadStatus.Success, file: new File([], name), + refId: sampleIds[index], })), ]); revalidator.revalidate(); From c25486cc127641c02ccf9cce80344a59ced3445a Mon Sep 17 00:00:00 2001 From: shlab Date: Tue, 21 Apr 2026 17:30:01 +0800 Subject: [PATCH 31/45] fix(i18n): update translation --- packages/i18n/src/locales/en-US.json | 4 +++- packages/i18n/src/locales/zh-CN.json | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/i18n/src/locales/en-US.json b/packages/i18n/src/locales/en-US.json index 86402079f..9043f052b 100644 --- a/packages/i18n/src/locales/en-US.json +++ b/packages/i18n/src/locales/en-US.json @@ -410,5 +410,7 @@ "batchAutoLabel": "Batch AI Annotate", "batchAutoLabelStarted": "Batch annotation job started", "batchAutoLabelCompleted": "Batch annotation completed: {{success}} succeeded, {{failed}} failed", - "batchAutoLabelNoSamples": "No unannotated samples" + "batchAutoLabelNoSamples": "No unannotated samples", + "s3VizTip": "For more powerful S3 data visualization, try", + "uploadSuccessCount": "," } diff --git a/packages/i18n/src/locales/zh-CN.json b/packages/i18n/src/locales/zh-CN.json index 296e6852a..300fd9edb 100644 --- a/packages/i18n/src/locales/zh-CN.json +++ b/packages/i18n/src/locales/zh-CN.json @@ -408,5 +408,7 @@ "batchAutoLabel": "AI 批量标注", "batchAutoLabelStarted": "批量标注任务已开始", "batchAutoLabelCompleted": "批量标注完成,成功 {{success}} 个,失败 {{failed}} 个", - "batchAutoLabelNoSamples": "没有未标注的样本" + "batchAutoLabelNoSamples": "没有未标注的样本", + "s3VizTip": "如果想要更强大的S3数据可视化,试试", + "uploadSuccessCount": "个," } From 34b6c6d8382b2a4e28ea44cd5033cf75d18afcf6 Mon Sep 17 00:00:00 2001 From: shlab Date: Tue, 21 Apr 2026 17:40:17 +0800 Subject: [PATCH 32/45] fix(frontend): data export from labelu[276](https://github.com/opendatalab/labelU/issues/276) --- apps/frontend/src/api/services/samples.ts | 79 +++++++++++------------ 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/apps/frontend/src/api/services/samples.ts b/apps/frontend/src/api/services/samples.ts index 05b90b185..875b77da4 100644 --- a/apps/frontend/src/api/services/samples.ts +++ b/apps/frontend/src/api/services/samples.ts @@ -109,60 +109,55 @@ export async function getAutoLabelJobStatus(taskId: number, jobId: number): Prom } export async function outputSample(taskId: number, sampleIds: number[], activeTxt: ExportType) { - const headers = {} as any; - - if ( - [ - ExportType.MASK, - ExportType.LABEL_ME, - ExportType.YOLO, - ExportType.CSV, - ExportType.XML, - ExportType.TF_RECORD, - ExportType.PASCAL_VOC, - ].includes(activeTxt) - ) { - headers.responseType = 'blob'; - } - - const data = await request.post( + // 1. Create export job + const jobRes = await request.post( `/v1/tasks/${taskId}/samples/export`, - { - sample_ids: sampleIds, - }, - { - params: { - task_id: taskId, - export_type: activeTxt, - }, - ...headers, - }, + { sample_ids: sampleIds }, + { params: { export_type: activeTxt } }, ); - const taskRes = await getTask(taskId); - const blobData = new Blob([JSON.stringify(data)]); - let url = window.URL.createObjectURL(blobData); - const a = document.createElement('a'); - let filename = taskRes.data.name; + const jobId = jobRes.data.id; + + // 2. Poll until completed + let job = jobRes.data; + while (job.status !== 'COMPLETED' && job.status !== 'FAILED') { + await new Promise((resolve) => setTimeout(resolve, 2000)); + const statusRes = await request.get(`/v1/tasks/${taskId}/samples/export/${jobId}`); + job = statusRes.data; + } + + if (job.status === 'FAILED') { + commonController.notificationErrorMessage({ message: job.error_message || 'Export failed' }, 3); + return; + } + + // 3. Download the exported file + const blob = await request.get(`/v1/tasks/${taskId}/samples/export/${jobId}/download`, { + responseType: 'blob', + }); + + const taskRes = await getTask(taskId); + let filename = taskRes.data.name || 'export'; switch (activeTxt) { case ExportType.JSON: case ExportType.COCO: - filename = filename + '.json'; + filename += '.json'; break; - case ExportType.MASK: - case ExportType.CSV: case ExportType.XML: - case ExportType.LABEL_ME: - case ExportType.YOLO: - case ExportType.TF_RECORD: - case ExportType.PASCAL_VOC: - url = window.URL.createObjectURL(data as any); + filename += '.xml'; + break; + default: + filename += '.zip'; break; } - a.download = filename!; + + const url = window.URL.createObjectURL(blob as Blob); + const a = document.createElement('a'); a.href = url; + a.download = filename; a.click(); + window.URL.revokeObjectURL(url); } export async function outputSamples(taskId: number, activeTxt: ExportType) { @@ -175,7 +170,7 @@ export async function outputSamples(taskId: number, activeTxt: ExportType) { } if (sampleIds.length === 0) { - commonController.notificationErrorMessage({ message: '后端返回数据出现问题' }, 1); + commonController.notificationErrorMessage({ message: 'No samples to export' }, 1); return; } From 83d6fd45ed09efc81e1d7503bdf8800d788dce01 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 09:46:26 +0000 Subject: [PATCH 33/45] chore(release): 1.8.2 [skip ci] ## @labelu/components-react [1.8.2](https://github.com/opendatalab/labelU-Kit/compare/@labelu/components-react@1.8.1...@labelu/components-react@1.8.2) (2026-04-21) ### Dependencies * **@labelu/i18n:** upgraded to 1.1.2 --- packages/components-react/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components-react/package.json b/packages/components-react/package.json index 3401d505f..b035ecc7c 100644 --- a/packages/components-react/package.json +++ b/packages/components-react/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/components-react", - "version": "1.8.1", + "version": "1.8.2", "description": "basic react components for labelU", "main": "./dist/index.mjs", "module": "./dist/index.mjs", @@ -35,7 +35,7 @@ "react" ], "dependencies": { - "@labelu/i18n": "1.1.1", + "@labelu/i18n": "1.1.2", "polished": "^4.2.2", "rc-collapse": "^3.7.1", "rc-dialog": "^9.2.0", From b36f653f316c53095f56682e43b5a602202952a0 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 09:46:30 +0000 Subject: [PATCH 34/45] chore(release): 1.9.2 [skip ci] ## [1.9.2](https://github.com/opendatalab/labelU-Kit/compare/@labelu/audio-annotator-react@1.9.1...@labelu/audio-annotator-react@1.9.2) (2026-04-21) ### Bug Fixes * **frontend:** add vis3 link to s3 datasource ([88979e6](https://github.com/opendatalab/labelU-Kit/commit/88979e64f5627e196e37627a0fc1aed5a75516dd)) * **frontend:** data export from labelu[276](https://github.com/opendatalab/labelU/issues/276) ([34b6c6d](https://github.com/opendatalab/labelU-Kit/commit/34b6c6d8382b2a4e28ea44cd5033cf75d18afcf6)) * **frontend:** fix s3 datasource import ([fbf1838](https://github.com/opendatalab/labelU-Kit/commit/fbf1838482c4eaf6ac0e2de6435869c181752883)) * **i18n:** update translation ([c25486c](https://github.com/opendatalab/labelU-Kit/commit/c25486cc127641c02ccf9cce80344a59ced3445a)) * **website:** build error ([8331827](https://github.com/opendatalab/labelU-Kit/commit/83318272c1341c9736cb014bef0507a4b3e5ddca)) --- packages/audio-annotator-react/package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/audio-annotator-react/package.json b/packages/audio-annotator-react/package.json index ff6b95916..811619319 100644 --- a/packages/audio-annotator-react/package.json +++ b/packages/audio-annotator-react/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/audio-annotator-react", - "version": "1.9.1", + "version": "1.9.2", "description": "audio annotator for react", "main": "./dist/index.mjs", "module": "./dist/index.mjs", @@ -28,9 +28,9 @@ "react" ], "dependencies": { - "@labelu/i18n": "1.1.1", - "@labelu/audio-react": "1.6.1", - "@labelu/components-react": "1.8.1", + "@labelu/i18n": "1.1.2", + "@labelu/audio-react": "1.6.2", + "@labelu/components-react": "1.8.2", "@labelu/interface": "1.3.1", "lodash.clonedeep": "^4.5.0", "polished": "^4.2.2", From 2cbe0bfe99a5ca6b325abb4a11a7a65e53e3f48a Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 09:46:35 +0000 Subject: [PATCH 35/45] chore(release): 1.6.2 [skip ci] ## [1.6.2](https://github.com/opendatalab/labelU-Kit/compare/@labelu/audio-react@1.6.1...@labelu/audio-react@1.6.2) (2026-04-21) ### Bug Fixes * **frontend:** add vis3 link to s3 datasource ([88979e6](https://github.com/opendatalab/labelU-Kit/commit/88979e64f5627e196e37627a0fc1aed5a75516dd)) * **frontend:** data export from labelu[276](https://github.com/opendatalab/labelU/issues/276) ([34b6c6d](https://github.com/opendatalab/labelU-Kit/commit/34b6c6d8382b2a4e28ea44cd5033cf75d18afcf6)) * **frontend:** fix s3 datasource import ([fbf1838](https://github.com/opendatalab/labelU-Kit/commit/fbf1838482c4eaf6ac0e2de6435869c181752883)) * **i18n:** update translation ([c25486c](https://github.com/opendatalab/labelU-Kit/commit/c25486cc127641c02ccf9cce80344a59ced3445a)) * **website:** build error ([8331827](https://github.com/opendatalab/labelU-Kit/commit/83318272c1341c9736cb014bef0507a4b3e5ddca)) --- packages/audio-react/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/audio-react/package.json b/packages/audio-react/package.json index af784e7ae..5bfdd16f5 100644 --- a/packages/audio-react/package.json +++ b/packages/audio-react/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/audio-react", - "version": "1.6.1", + "version": "1.6.2", "description": "labelu audio annotation component for react", "main": "./dist/index.mjs", "module": "./dist/index.mjs", @@ -40,7 +40,7 @@ "vite-tsconfig-paths": "^3.5.0" }, "dependencies": { - "@labelu/components-react": "1.8.1", + "@labelu/components-react": "1.8.2", "polished": "^4.2.2", "react-hotkeys-hook": "^4.4.1", "styled-components": "^6.1.15", From f5b2b79a8281806b64b1efa427e9b9e8647d2dcd Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 09:46:39 +0000 Subject: [PATCH 36/45] chore(release): 1.1.2 [skip ci] ## [1.1.2](https://github.com/opendatalab/labelU-Kit/compare/@labelu/i18n@1.1.1...@labelu/i18n@1.1.2) (2026-04-21) ### Bug Fixes * **frontend:** add vis3 link to s3 datasource ([88979e6](https://github.com/opendatalab/labelU-Kit/commit/88979e64f5627e196e37627a0fc1aed5a75516dd)) * **frontend:** data export from labelu[276](https://github.com/opendatalab/labelU/issues/276) ([34b6c6d](https://github.com/opendatalab/labelU-Kit/commit/34b6c6d8382b2a4e28ea44cd5033cf75d18afcf6)) * **frontend:** fix s3 datasource import ([fbf1838](https://github.com/opendatalab/labelU-Kit/commit/fbf1838482c4eaf6ac0e2de6435869c181752883)) * **i18n:** update translation ([c25486c](https://github.com/opendatalab/labelU-Kit/commit/c25486cc127641c02ccf9cce80344a59ced3445a)) * **website:** build error ([8331827](https://github.com/opendatalab/labelU-Kit/commit/83318272c1341c9736cb014bef0507a4b3e5ddca)) --- packages/i18n/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 7c4857f52..5fbfa2712 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/i18n", - "version": "1.1.1", + "version": "1.1.2", "description": "i18n for labelu and components", "scripts": { "build": "vite build && npm run build:types", From 6a01a4c3ed01bc21c6225feec67bf9fcd8fd4d7d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 09:46:43 +0000 Subject: [PATCH 37/45] chore(release): 2.5.2 [skip ci] ## [2.5.2](https://github.com/opendatalab/labelU-Kit/compare/@labelu/image-annotator-react@2.5.1...@labelu/image-annotator-react@2.5.2) (2026-04-21) ### Bug Fixes * **frontend:** add vis3 link to s3 datasource ([88979e6](https://github.com/opendatalab/labelU-Kit/commit/88979e64f5627e196e37627a0fc1aed5a75516dd)) * **frontend:** data export from labelu[276](https://github.com/opendatalab/labelU/issues/276) ([34b6c6d](https://github.com/opendatalab/labelU-Kit/commit/34b6c6d8382b2a4e28ea44cd5033cf75d18afcf6)) * **frontend:** fix s3 datasource import ([fbf1838](https://github.com/opendatalab/labelU-Kit/commit/fbf1838482c4eaf6ac0e2de6435869c181752883)) * **i18n:** update translation ([c25486c](https://github.com/opendatalab/labelU-Kit/commit/c25486cc127641c02ccf9cce80344a59ced3445a)) * **website:** build error ([8331827](https://github.com/opendatalab/labelU-Kit/commit/83318272c1341c9736cb014bef0507a4b3e5ddca)) --- packages/image-annotator-react/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/image-annotator-react/package.json b/packages/image-annotator-react/package.json index a3b0a385b..235fe1580 100644 --- a/packages/image-annotator-react/package.json +++ b/packages/image-annotator-react/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/image-annotator-react", - "version": "2.5.1", + "version": "2.5.2", "description": "image annotator for react", "main": "./dist/index.mjs", "module": "./dist/index.mjs", @@ -29,10 +29,10 @@ "react" ], "dependencies": { - "@labelu/components-react": "1.8.1", + "@labelu/components-react": "1.8.2", "@labelu/image": "1.5.1", "@labelu/interface": "1.3.1", - "@labelu/i18n": "1.1.1", + "@labelu/i18n": "1.1.2", "lodash.clonedeep": "^4.5.0", "polished": "^4.2.2", "react-hotkeys-hook": "^4.4.1", From 94c486aaae7fda5374f0b3f79f1c243aa048f6c2 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 09:46:47 +0000 Subject: [PATCH 38/45] chore(release): 1.5.2 [skip ci] ## [1.5.2](https://github.com/opendatalab/labelU-Kit/compare/@labelu/video-annotator-react@1.5.1...@labelu/video-annotator-react@1.5.2) (2026-04-21) ### Bug Fixes * **frontend:** add vis3 link to s3 datasource ([88979e6](https://github.com/opendatalab/labelU-Kit/commit/88979e64f5627e196e37627a0fc1aed5a75516dd)) * **frontend:** data export from labelu[276](https://github.com/opendatalab/labelU/issues/276) ([34b6c6d](https://github.com/opendatalab/labelU-Kit/commit/34b6c6d8382b2a4e28ea44cd5033cf75d18afcf6)) * **frontend:** fix s3 datasource import ([fbf1838](https://github.com/opendatalab/labelU-Kit/commit/fbf1838482c4eaf6ac0e2de6435869c181752883)) * **i18n:** update translation ([c25486c](https://github.com/opendatalab/labelU-Kit/commit/c25486cc127641c02ccf9cce80344a59ced3445a)) * **website:** build error ([8331827](https://github.com/opendatalab/labelU-Kit/commit/83318272c1341c9736cb014bef0507a4b3e5ddca)) --- packages/video-annotator-react/package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/video-annotator-react/package.json b/packages/video-annotator-react/package.json index 5a82e023e..3ef44920c 100644 --- a/packages/video-annotator-react/package.json +++ b/packages/video-annotator-react/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/video-annotator-react", - "version": "1.5.1", + "version": "1.5.2", "description": "video annotator for react", "main": "./dist/index.mjs", "module": "./dist/index.mjs", @@ -29,11 +29,11 @@ "react" ], "dependencies": { - "@labelu/components-react": "1.8.1", + "@labelu/components-react": "1.8.2", "@labelu/interface": "1.3.1", - "@labelu/i18n": "1.1.1", - "@labelu/audio-annotator-react": "1.9.1", - "@labelu/video-react": "1.6.1", + "@labelu/i18n": "1.1.2", + "@labelu/audio-annotator-react": "1.9.2", + "@labelu/video-react": "1.6.2", "polished": "^4.2.2", "react-hotkeys-hook": "^4.4.1", "styled-components": "^6.1.15" From 783e137eedb0d6d76981aac22d9fa0d87feca2b8 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 09:46:51 +0000 Subject: [PATCH 39/45] chore(release): 1.6.2 [skip ci] ## [1.6.2](https://github.com/opendatalab/labelU-Kit/compare/@labelu/video-react@1.6.1...@labelu/video-react@1.6.2) (2026-04-21) ### Bug Fixes * **frontend:** add vis3 link to s3 datasource ([88979e6](https://github.com/opendatalab/labelU-Kit/commit/88979e64f5627e196e37627a0fc1aed5a75516dd)) * **frontend:** data export from labelu[276](https://github.com/opendatalab/labelU/issues/276) ([34b6c6d](https://github.com/opendatalab/labelU-Kit/commit/34b6c6d8382b2a4e28ea44cd5033cf75d18afcf6)) * **frontend:** fix s3 datasource import ([fbf1838](https://github.com/opendatalab/labelU-Kit/commit/fbf1838482c4eaf6ac0e2de6435869c181752883)) * **i18n:** update translation ([c25486c](https://github.com/opendatalab/labelU-Kit/commit/c25486cc127641c02ccf9cce80344a59ced3445a)) * **website:** build error ([8331827](https://github.com/opendatalab/labelU-Kit/commit/83318272c1341c9736cb014bef0507a4b3e5ddca)) --- packages/video-react/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/video-react/package.json b/packages/video-react/package.json index 8f04b0d80..9ab5c03bf 100644 --- a/packages/video-react/package.json +++ b/packages/video-react/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/video-react", - "version": "1.6.1", + "version": "1.6.2", "description": "labelu video annotation component for react", "main": "./dist/index.mjs", "module": "./dist/index.mjs", @@ -39,7 +39,7 @@ "styled-components": "^6.1.15" }, "dependencies": { - "@labelu/components-react": "1.8.1", + "@labelu/components-react": "1.8.2", "polished": "^4.2.2", "rc-tooltip": "^6.0.1", "react-hotkeys-hook": "^4.4.1", From c403ea24dbba6ad95f76c6007decad6925e9c5ef Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 21 Apr 2026 09:49:33 +0000 Subject: [PATCH 40/45] chore(release): 5.10.3 [skip ci] ## [5.10.3](https://github.com/opendatalab/labelU-Kit/compare/v5.10.2...v5.10.3) (2026-04-21) ### Bug Fixes * **frontend:** data export from labelu[276](https://github.com/opendatalab/labelU/issues/276) ([34b6c6d](https://github.com/opendatalab/labelU-Kit/commit/34b6c6d8382b2a4e28ea44cd5033cf75d18afcf6)) * **frontend:** fix s3 datasource import ([fbf1838](https://github.com/opendatalab/labelU-Kit/commit/fbf1838482c4eaf6ac0e2de6435869c181752883)) * **i18n:** update translation ([c25486c](https://github.com/opendatalab/labelU-Kit/commit/c25486cc127641c02ccf9cce80344a59ced3445a)) --- apps/frontend/package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/frontend/package.json b/apps/frontend/package.json index fe47f7fd3..cc7dd64bc 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -4,15 +4,15 @@ "private": true, "dependencies": { "@ant-design/icons": "^4.6.2", - "@labelu/i18n": "1.1.1", - "@labelu/audio-annotator-react": "1.9.1", - "@labelu/components-react": "1.8.1", + "@labelu/i18n": "1.1.2", + "@labelu/audio-annotator-react": "1.9.2", + "@labelu/components-react": "1.8.2", "@labelu/image": "1.5.1", "@labelu/formatter": "1.0.2", - "@labelu/image-annotator-react": "2.5.1", + "@labelu/image-annotator-react": "2.5.2", "@labelu/interface": "1.3.1", - "@labelu/video-annotator-react": "1.5.1", - "@labelu/video-react": "1.6.1", + "@labelu/video-annotator-react": "1.5.2", + "@labelu/video-react": "1.6.2", "@tanstack/react-query": "^5.0.0", "antd": "5.10.1", "axios": "^1.3.4", From da5c612497d2c7dd26299f8494b4c1d05a13dceb Mon Sep 17 00:00:00 2001 From: gary Date: Tue, 21 Apr 2026 17:49:37 +0800 Subject: [PATCH 41/45] chore: update frontend package.json version to 5.10.3 [skip ci] --- apps/frontend/package.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/frontend/package.json b/apps/frontend/package.json index cc7dd64bc..f278585c2 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/frontend", - "version": "5.10.2", + "version": "5.10.3", "private": true, "dependencies": { "@ant-design/icons": "^4.6.2", diff --git a/package.json b/package.json index 834877ee8..2f318aa33 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "packages/*", "apps/*" ], - "version": "5.10.2", + "version": "5.10.3", "scripts": { "prepare": "husky install", "build": "pnpm --filter @labelu/interface --filter @labelu/i18n --filter @labelu/formatter --filter @labelu/image --filter @labelu/components-react --filter @labelu/image-annotator-react --filter @labelu/audio-react --filter @labelu/video-react --filter @labelu/audio-annotator-react --filter @labelu/video-annotator-react build", From 2d4fba97ab1ad68219eb72a887646b778b5e626b Mon Sep 17 00:00:00 2001 From: shlab Date: Mon, 1 Jun 2026 18:01:42 +0800 Subject: [PATCH 42/45] feat(frontend): consume X-New-Token header for sliding token refresh The backend re-issues a token via the X-New-Token response header when the current one is near expiry. Read that header in both axios response interceptors and update localStorage.token so active users stay logged in. The header value uses the same `Bearer xxx` format the login endpoint returns, so it drops straight into the existing Authorization flow. Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/frontend/src/api/request.tsx | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/apps/frontend/src/api/request.tsx b/apps/frontend/src/api/request.tsx index 2a42e5ade..92088d058 100644 --- a/apps/frontend/src/api/request.tsx +++ b/apps/frontend/src/api/request.tsx @@ -6,12 +6,25 @@ import axios from 'axios'; import commonController from '@/utils/common'; import { goLogin } from '@/utils/sso'; +/** + * 滑动续期:后端在响应头 `X-New-Token` 中返回新签发的 token 时,更新本地存储, + * 使活跃用户的登录态自动延续,不会到点被强制登出。 + * @param response + */ +function applyRefreshedToken(response: AxiosResponse) { + const newToken = response?.headers?.['x-new-token']; + if (newToken) { + localStorage.token = newToken; + } +} + /** * 后端返回的结构由 { data, meta_data } 包裹 * @param response * @returns */ export function successHandler(response: AxiosResponse) { + applyRefreshedToken(response); return response.data; } @@ -79,7 +92,10 @@ const request = axios.create(requestConfig); export const requestWithHeaders = axios.create(requestConfig); requestWithHeaders.interceptors.request.use(authorizationBearerSuccess, authorizationBearerFailed); -requestWithHeaders.interceptors.response.use(undefined, authorizationBearerFailed); +requestWithHeaders.interceptors.response.use((response) => { + applyRefreshedToken(response); + return response; +}, authorizationBearerFailed); requestWithHeaders.interceptors.response.use(undefined, errorHandler); request.interceptors.request.use(authorizationBearerSuccess, authorizationBearerFailed); From 05288755658f3340973e42ebcb4e8a1621f668ce Mon Sep 17 00:00:00 2001 From: gary Date: Tue, 2 Jun 2026 15:42:18 +0800 Subject: [PATCH 43/45] chore: update frontend package.json version to 5.11.0 [skip ci] --- apps/frontend/package.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/frontend/package.json b/apps/frontend/package.json index f278585c2..28055e440 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -1,6 +1,6 @@ { "name": "@labelu/frontend", - "version": "5.10.3", + "version": "5.11.0", "private": true, "dependencies": { "@ant-design/icons": "^4.6.2", diff --git a/package.json b/package.json index 2f318aa33..e7c45cf69 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "packages/*", "apps/*" ], - "version": "5.10.3", + "version": "5.11.0", "scripts": { "prepare": "husky install", "build": "pnpm --filter @labelu/interface --filter @labelu/i18n --filter @labelu/formatter --filter @labelu/image --filter @labelu/components-react --filter @labelu/image-annotator-react --filter @labelu/audio-react --filter @labelu/video-react --filter @labelu/audio-annotator-react --filter @labelu/video-annotator-react build", From 452a0d66a05a0c07d58db0156d58fe39b339a15c Mon Sep 17 00:00:00 2001 From: shlab Date: Mon, 13 Jul 2026 17:26:44 +0800 Subject: [PATCH 44/45] =?UTF-8?q?fix(frontend):=20online=20401=20=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=20goAuth=20=E8=B7=B3=E8=BD=AC=20SSO=20/authentication?= =?UTF-8?q?=20=E7=AB=AF=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 合并 release 后 online 的 401 跳转被改成 goLogin(/login), 恢复为 goAuth(/authentication),保留 release 的滑动续期等改进。 Co-Authored-By: Claude Opus 4.8 --- apps/frontend/src/api/request.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/frontend/src/api/request.tsx b/apps/frontend/src/api/request.tsx index 92088d058..37c484f92 100644 --- a/apps/frontend/src/api/request.tsx +++ b/apps/frontend/src/api/request.tsx @@ -4,7 +4,7 @@ import type { AxiosError, AxiosResponse } from 'axios'; import axios from 'axios'; import commonController from '@/utils/common'; -import { goLogin } from '@/utils/sso'; +import { goAuth } from '@/utils/sso'; /** * 滑动续期:后端在响应头 `X-New-Token` 中返回新签发的 token 时,更新本地存储, @@ -72,7 +72,7 @@ const authorizationBearerFailed = (error: any) => { localStorage.removeItem('token'); setTimeout(() => { if (window.IS_ONLINE) { - goLogin(); + goAuth(); } else if (window.location.pathname !== '/login') { window.location.href = '/login'; } From 3898072cf18a54c84f1c0ce81f4e21635df4be34 Mon Sep 17 00:00:00 2001 From: shlab Date: Mon, 13 Jul 2026 20:06:53 +0800 Subject: [PATCH 45/45] =?UTF-8?q?fix(workspace):=20multi-semantic-release?= =?UTF-8?q?=20=E5=A2=9E=E5=8A=A0=20--sequential-init=20=E9=81=BF=E5=85=8D?= =?UTF-8?q?=E5=B9=B6=E5=8F=91=E6=8A=A2=20release=20ref=20=E9=94=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 多个包并发执行 git fetch +refs/heads/release 时会抢同一个 refs/heads/release.lock 导致 'cannot lock ref' 报错, --sequential-init 让各包初始化/fetch 串行执行。 Co-Authored-By: Claude Opus 4.8 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e7c45cf69..f1367615b 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,8 @@ "commit": "cz", "docs": "typedoc", "docs-all": "npm run docs --workspaces --if-present", - "release-dry": "multi-semantic-release --dry-run --ignore-private-packages --no-ci", - "release": "multi-semantic-release --ignore-private-packages" + "release-dry": "multi-semantic-release --dry-run --ignore-private-packages --no-ci --sequential-init", + "release": "multi-semantic-release --ignore-private-packages --sequential-init" }, "author": "gary-shen", "contributors": [