Skip to content

Commit 621f092

Browse files
authored
Show task-specific tools (#4713)
1 parent 5829ae1 commit 621f092

File tree

9 files changed

+98
-41
lines changed

9 files changed

+98
-41
lines changed

ui/src/components/tool-selection-bar/icon-wrapper.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { ReactNode } from 'react';
55

66
import { clsx } from 'clsx';
77

8-
import classes from './tool-selection-bar.module.scss';
8+
import classes from './icon-wrapper.module.scss';
99

1010
export const IconWrapper = ({
1111
children,
Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,3 @@
1-
.section {
2-
background-color: var(--spectrum-global-color-gray-50);
3-
padding: var(--spectrum-global-dimension-size-100);
4-
border-radius: var(--spectrum-global-dimension-size-50);
5-
gap: var(--spectrum-global-dimension-size-50);
6-
flex-direction: column;
7-
align-items: center;
8-
}
9-
101
.iconWrapper {
112
display: flex;
123
width: var(--spectrum-global-dimension-size-400);
@@ -28,11 +19,3 @@
2819
fill: var(--spectrum-global-color-gray-50);
2920
}
3021
}
31-
32-
.grid {
33-
grid-template-rows: 'auto auto auto';
34-
gap: var(--spectrum-global-dimension-size-50);
35-
background-color: var(--spectrum-global-color-gray-200);
36-
border-radius: var(--spectrum-global-dimension-size-100);
37-
padding: var(--spectrum-global-dimension-size-50);
38-
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
// Copyright (C) 2025 Intel Corporation
22
// SPDX-License-Identifier: Apache-2.0
33

4+
import { ComponentType, SVGProps } from 'react';
5+
46
export type ToolType = 'selection' | 'bounding-box' | 'polygon' | 'sam';
7+
8+
export interface ToolConfig {
9+
type: ToolType;
10+
icon: ComponentType<SVGProps<SVGSVGElement>>;
11+
}
Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
11
// Copyright (C) 2025 Intel Corporation
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import { Divider } from '@geti/ui';
5-
import { BoundingBox, Selector } from '@geti/ui/icons';
4+
import { Fragment } from 'react/jsx-runtime';
65

7-
import { useAnnotator } from '../../../features/annotator/annotator-provider.component';
86
import { IconWrapper } from '../icon-wrapper.component';
7+
import { ToolConfig, ToolType } from './interface';
98

10-
export const Tools = () => {
11-
const { activeTool, setActiveTool } = useAnnotator();
9+
interface ToolsProps {
10+
tools: ToolConfig[];
11+
activeTool: ToolType | null;
12+
setActiveTool: (tool: ToolType) => void;
13+
}
14+
export const Tools = ({ tools, activeTool, setActiveTool }: ToolsProps) => {
15+
if (tools.length === 0) {
16+
return null;
17+
}
1218

1319
return (
1420
<>
15-
<IconWrapper onPress={() => setActiveTool('selection')} isSelected={activeTool === 'selection'}>
16-
<Selector data-tool='selection' />
17-
</IconWrapper>
18-
19-
<Divider size='S' />
20-
21-
<IconWrapper onPress={() => setActiveTool('bounding-box')} isSelected={activeTool === 'bounding-box'}>
22-
<BoundingBox />
23-
</IconWrapper>
21+
{tools.map((tool) => (
22+
<Fragment key={tool.type}>
23+
<IconWrapper onPress={() => setActiveTool(tool.type)} isSelected={activeTool === tool.type}>
24+
<tool.icon data-tool={tool.type} />
25+
</IconWrapper>
26+
</Fragment>
27+
))}
2428
</>
2529
);
2630
};
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright (C) 2025 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { Divider } from '@geti/ui';
5+
import { BoundingBox, Selector } from '@geti/ui/icons';
6+
7+
import { ToolConfig } from '../../../components/tool-selection-bar/tools/interface';
8+
import { Tools } from '../../../components/tool-selection-bar/tools/tools.component';
9+
import { useProjectTask } from '../../../hooks/use-project-task.hook';
10+
import { useAnnotator } from '../annotator-provider.component';
11+
12+
const TASK_TOOL_CONFIG: Record<string, ToolConfig[]> = {
13+
classification: [],
14+
detection: [
15+
{ type: 'selection', icon: Selector },
16+
{ type: 'bounding-box', icon: BoundingBox },
17+
],
18+
segmentation: [
19+
{ type: 'selection', icon: Selector },
20+
// TODO: Add 'polygon' and 'sam' tools later
21+
],
22+
};
23+
24+
export const AnnotatorTools = () => {
25+
const projectTask = useProjectTask();
26+
const { activeTool, setActiveTool } = useAnnotator();
27+
const availableTools = TASK_TOOL_CONFIG[projectTask] || [];
28+
29+
return (
30+
<>
31+
<Tools tools={availableTools} activeTool={activeTool} setActiveTool={setActiveTool} />
32+
{availableTools.length > 0 && <Divider size='S' />}
33+
</>
34+
);
35+
};

ui/src/components/tool-selection-bar/tool-selection-bar.component.tsx renamed to ui/src/features/annotator/tools/tool-selection-bar.component.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// Copyright (C) 2025 Intel Corporation
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import { Divider, Flex, Grid } from '@geti/ui';
4+
import { Flex, Grid } from '@geti/ui';
55

6-
import { Hotkeys } from './hotkeys/hotkeys.component';
7-
import { Settings } from './settings/settings.component';
8-
import { Tools } from './tools/tools.component';
9-
import { UndoRedo } from './undo-redo/undo-redo.component';
6+
import { Hotkeys } from '../../../components/tool-selection-bar/hotkeys/hotkeys.component';
7+
import { Settings } from '../../../components/tool-selection-bar/settings/settings.component';
8+
import { UndoRedo } from '../../../components/tool-selection-bar/undo-redo/undo-redo.component';
9+
import { AnnotatorTools } from './annotator-tools.component';
1010

1111
import classes from './tool-selection-bar.module.scss';
1212

@@ -15,9 +15,7 @@ export const ToolSelectionBar = () => {
1515
<Flex height={'100%'} alignItems={'center'} justifyContent={'center'}>
1616
<Grid UNSAFE_className={classes.grid}>
1717
<Flex UNSAFE_className={classes.section}>
18-
<Tools />
19-
20-
<Divider size='S' />
18+
<AnnotatorTools />
2119

2220
<UndoRedo />
2321
</Flex>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.section {
2+
background-color: var(--spectrum-global-color-gray-50);
3+
padding: var(--spectrum-global-dimension-size-100);
4+
border-radius: var(--spectrum-global-dimension-size-50);
5+
gap: var(--spectrum-global-dimension-size-50);
6+
flex-direction: column;
7+
align-items: center;
8+
}
9+
10+
.grid {
11+
grid-template-rows: 'auto auto auto';
12+
gap: var(--spectrum-global-dimension-size-50);
13+
background-color: var(--spectrum-global-color-gray-200);
14+
border-radius: var(--spectrum-global-dimension-size-100);
15+
padding: var(--spectrum-global-dimension-size-50);
16+
}

ui/src/features/dataset/media-preview/media-preview.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import { useState } from 'react';
55

66
import { Button, ButtonGroup, Content, Dialog, Divider, Grid, Heading, ToggleButton, View } from '@geti/ui';
77

8-
import { ToolSelectionBar } from '../../../components/tool-selection-bar/tool-selection-bar.component';
98
import { AnnotatorCanvas } from '../../annotator/annotator-canvas';
109
import { AnnotatorProvider } from '../../annotator/annotator-provider.component';
10+
import { ToolSelectionBar } from '../../annotator/tools/tool-selection-bar.component';
1111
import { response } from '../mock-response';
1212

1313
type Item = (typeof response.items)[number];
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright (C) 2025 Intel Corporation
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { $api } from '../api/client';
5+
import { useProjectIdentifier } from './use-project-identifier.hook';
6+
7+
export const useProjectTask = () => {
8+
const projectId = useProjectIdentifier();
9+
const projectTask = $api.useQuery('get', '/api/projects/{project_id}', {
10+
params: { path: { project_id: projectId } },
11+
});
12+
13+
return projectTask.data?.task.task_type || 'detection';
14+
};

0 commit comments

Comments
 (0)