Skip to content

Commit 65cbabd

Browse files
authored
Added button to cancel started automatic annotation (#1198)
1 parent 401d66d commit 65cbabd

File tree

9 files changed

+283
-319
lines changed

9 files changed

+283
-319
lines changed

cvat-ui/src/actions/models-actions.ts

Lines changed: 172 additions & 258 deletions
Large diffs are not rendered by default.

cvat-ui/src/components/tasks-page/styles.scss

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -87,37 +87,11 @@
8787
padding-top: 20px;
8888
background: $background-color-1;
8989

90-
/* description */
91-
> div:nth-child(2) {
92-
word-break: break-all;
93-
max-height: 100%;
94-
overflow: hidden;
95-
}
96-
97-
/* open, actions */
98-
div:nth-child(4) {
99-
> div {
100-
margin-right: 20px;
101-
}
102-
103-
/* actions */
104-
> div:nth-child(2) {
105-
margin-right: 5px;
106-
margin-top: 10px;
107-
108-
> div {
109-
display: flex;
110-
align-items: center;
111-
}
112-
}
113-
}
114-
11590
&:hover {
11691
border: 1px solid $border-color-hover;
11792
}
11893
}
11994

120-
12195
.cvat-task-item-preview-wrapper {
12296
display: flex;
12397
justify-content: center;
@@ -131,6 +105,12 @@
131105
}
132106
}
133107

108+
.cvat-task-item-description {
109+
word-break: break-all;
110+
max-height: 100%;
111+
overflow: hidden;
112+
}
113+
134114
.cvat-task-progress {
135115
width: 100%;
136116
}
@@ -159,6 +139,26 @@
159139
margin-right: 5px;
160140
}
161141

142+
.close-auto-annotation-icon {
143+
color: $danger-icon-color;
144+
opacity: 0.7;
145+
146+
&:hover {
147+
opacity: 1;
148+
}
149+
}
150+
151+
.cvat-item-open-task-actions {
152+
margin-right: 5px;
153+
margin-top: 10px;
154+
display: flex;
155+
align-items: center;
156+
}
157+
158+
.cvat-item-open-task-button {
159+
margin-right: 20px;
160+
}
161+
162162
#cvat-create-task-button {
163163
padding: 0 30px;
164164
}

cvat-ui/src/components/tasks-page/task-item.tsx

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {
1414
Icon,
1515
Progress,
1616
Dropdown,
17+
Tooltip,
18+
Modal,
1719
} from 'antd';
1820

1921
import moment from 'moment';
@@ -28,6 +30,7 @@ export interface TaskItemProps {
2830
deleted: boolean;
2931
hidden: boolean;
3032
activeInference: ActiveInference | null;
33+
cancelAutoAnnotation(): void;
3134
}
3235

3336
class TaskItemComponent extends React.PureComponent<TaskItemProps & RouteComponentProps> {
@@ -54,7 +57,7 @@ class TaskItemComponent extends React.PureComponent<TaskItemProps & RouteCompone
5457
const name = `${taskInstance.name.substring(0, 70)}${taskInstance.name.length > 70 ? '...' : ''}`;
5558

5659
return (
57-
<Col span={10}>
60+
<Col span={10} className='cvat-task-item-description'>
5861
<Text strong type='secondary'>{`#${id}: `}</Text>
5962
<Text strong className='cvat-text-color'>{name}</Text>
6063
<br />
@@ -76,6 +79,7 @@ class TaskItemComponent extends React.PureComponent<TaskItemProps & RouteCompone
7679
const {
7780
taskInstance,
7881
activeInference,
82+
cancelAutoAnnotation,
7983
} = this.props;
8084
// Count number of jobs and performed jobs
8185
const numOfJobs = taskInstance.jobs.length;
@@ -132,8 +136,8 @@ class TaskItemComponent extends React.PureComponent<TaskItemProps & RouteCompone
132136
<Text strong>Automatic annotation</Text>
133137
</Col>
134138
</Row>
135-
<Row>
136-
<Col>
139+
<Row type='flex' justify='space-between'>
140+
<Col span={22}>
137141
<Progress
138142
percent={Math.floor(activeInference.progress)}
139143
strokeColor={{
@@ -145,6 +149,23 @@ class TaskItemComponent extends React.PureComponent<TaskItemProps & RouteCompone
145149
size='small'
146150
/>
147151
</Col>
152+
<Col span={1} className='close-auto-annotation-icon'>
153+
<Tooltip title='Cancel automatic annotation'>
154+
<Icon
155+
type='close'
156+
onClick={() => {
157+
Modal.confirm({
158+
title: 'You are going to cancel automatic annotation?',
159+
content: 'Reached progress will be lost. Continue?',
160+
okType: 'danger',
161+
onOk() {
162+
cancelAutoAnnotation();
163+
},
164+
});
165+
}}
166+
/>
167+
</Tooltip>
168+
</Col>
148169
</Row>
149170
</>
150171
)}
@@ -164,6 +185,7 @@ class TaskItemComponent extends React.PureComponent<TaskItemProps & RouteCompone
164185
<Row type='flex' justify='end'>
165186
<Col>
166187
<Button
188+
className='cvat-item-open-task-button'
167189
type='primary'
168190
size='large'
169191
ghost
@@ -174,7 +196,7 @@ class TaskItemComponent extends React.PureComponent<TaskItemProps & RouteCompone
174196
</Col>
175197
</Row>
176198
<Row type='flex' justify='end'>
177-
<Col>
199+
<Col className='cvat-item-open-task-actions'>
178200
<Text className='cvat-text-color'>Actions</Text>
179201
<Dropdown overlay={<ActionsMenuContainer taskInstance={taskInstance} />}>
180202
<Icon className='cvat-menu-icon' component={MenuIcon} />

cvat-ui/src/containers/actions-menu/actions-menu.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
CombinedState,
1111
} from 'reducers/interfaces';
1212

13-
import { showRunModelDialog } from 'actions/models-actions';
13+
import { modelsActions } from 'actions/models-actions';
1414
import {
1515
dumpAnnotationsAsync,
1616
loadAnnotationsAsync,
@@ -99,7 +99,7 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
9999
dispatch(deleteTaskAsync(taskInstance));
100100
},
101101
openRunModelWindow: (taskInstance: any): void => {
102-
dispatch(showRunModelDialog(taskInstance));
102+
dispatch(modelsActions.showRunModelDialog(taskInstance));
103103
},
104104
};
105105
}

cvat-ui/src/containers/model-runner-dialog/model-runner-dialog.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import {
1212
} from 'reducers/interfaces';
1313
import {
1414
getModelsAsync,
15-
inferModelAsync,
16-
closeRunModelDialog,
15+
startInferenceAsync,
16+
modelsActions,
1717
} from 'actions/models-actions';
1818

1919

@@ -64,13 +64,13 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
6464
},
6565
cleanOut: boolean,
6666
): void {
67-
dispatch(inferModelAsync(taskInstance, model, mapping, cleanOut));
67+
dispatch(startInferenceAsync(taskInstance, model, mapping, cleanOut));
6868
},
6969
getModels(): void {
7070
dispatch(getModelsAsync());
7171
},
7272
closeDialog(): void {
73-
dispatch(closeRunModelDialog());
73+
dispatch(modelsActions.closeRunModelDialog());
7474
},
7575
});
7676
}

cvat-ui/src/containers/tasks-page/task-item.tsx

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ import {
1313

1414
import TaskItemComponent from 'components/tasks-page/task-item';
1515

16-
import {
17-
getTasksAsync,
18-
} from 'actions/tasks-actions';
16+
import { getTasksAsync } from 'actions/tasks-actions';
17+
import { cancelInferenceAsync } from 'actions/models-actions';
1918

2019
interface StateToProps {
2120
deleted: boolean;
@@ -26,7 +25,8 @@ interface StateToProps {
2625
}
2726

2827
interface DispatchToProps {
29-
getTasks: (query: TasksQuery) => void;
28+
getTasks(query: TasksQuery): void;
29+
cancelAutoAnnotation(): void;
3030
}
3131

3232
interface OwnProps {
@@ -48,23 +48,18 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
4848
};
4949
}
5050

51-
function mapDispatchToProps(dispatch: any): DispatchToProps {
51+
function mapDispatchToProps(dispatch: any, own: OwnProps): DispatchToProps {
5252
return {
53-
getTasks: (query: TasksQuery): void => {
53+
getTasks(query: TasksQuery): void {
5454
dispatch(getTasksAsync(query));
5555
},
56+
cancelAutoAnnotation(): void {
57+
dispatch(cancelInferenceAsync(own.taskID));
58+
},
5659
};
5760
}
5861

59-
type TasksItemContainerProps = StateToProps & DispatchToProps & OwnProps;
60-
61-
function TaskItemContainer(props: TasksItemContainerProps): JSX.Element {
62-
return (
63-
<TaskItemComponent {...props} />
64-
);
65-
}
66-
6762
export default connect(
6863
mapStateToProps,
6964
mapDispatchToProps,
70-
)(TaskItemContainer);
65+
)(TaskItemComponent);

cvat-ui/src/reducers/interfaces.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,17 @@ export enum RQStatus {
134134
failed = 'failed',
135135
}
136136

137+
export enum ModelType {
138+
OPENVINO = 'openvino',
139+
RCNN = 'rcnn',
140+
MASK_RCNN = 'mask_rcnn',
141+
}
142+
137143
export interface ActiveInference {
138144
status: RQStatus;
139145
progress: number;
140146
error: string;
147+
modelType: ModelType;
141148
}
142149

143150
export interface ModelsState {
@@ -199,6 +206,7 @@ export interface NotificationsState {
199206
starting: null | ErrorState;
200207
deleting: null | ErrorState;
201208
fetching: null | ErrorState;
209+
canceling: null | ErrorState;
202210
metaFetching: null | ErrorState;
203211
inferenceStatusFetching: null | ErrorState;
204212
};

cvat-ui/src/reducers/models-reducer.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
//
33
// SPDX-License-Identifier: MIT
44

5-
import { AnyAction } from 'redux';
6-
7-
import { ModelsActionTypes } from 'actions/models-actions';
8-
import { AuthActionTypes } from 'actions/auth-actions';
5+
import { ModelsActionTypes, ModelsActions } from 'actions/models-actions';
6+
import { AuthActionTypes, AuthActions } from 'actions/auth-actions';
97
import { ModelsState } from './interfaces';
108

119
const defaultState: ModelsState = {
@@ -18,7 +16,7 @@ const defaultState: ModelsState = {
1816
inferences: {},
1917
};
2018

21-
export default function (state = defaultState, action: AnyAction): ModelsState {
19+
export default function (state = defaultState, action: ModelsActions | AuthActions): ModelsState {
2220
switch (action.type) {
2321
case ModelsActionTypes.GET_MODELS: {
2422
return {
@@ -90,7 +88,7 @@ export default function (state = defaultState, action: AnyAction): ModelsState {
9088
};
9189
}
9290
case ModelsActionTypes.GET_INFERENCE_STATUS_SUCCESS: {
93-
const inferences = { ...state.inferences };
91+
const { inferences } = state;
9492
if (action.payload.activeInference.status === 'finished') {
9593
delete inferences[action.payload.taskID];
9694
} else {
@@ -99,16 +97,25 @@ export default function (state = defaultState, action: AnyAction): ModelsState {
9997

10098
return {
10199
...state,
102-
inferences,
100+
inferences: { ...inferences },
103101
};
104102
}
105103
case ModelsActionTypes.GET_INFERENCE_STATUS_FAILED: {
106-
const inferences = { ...state.inferences };
104+
const { inferences } = state;
105+
delete inferences[action.payload.taskID];
106+
107+
return {
108+
...state,
109+
inferences: { ...inferences },
110+
};
111+
}
112+
case ModelsActionTypes.CANCEL_INFERENCE_SUCCESS: {
113+
const { inferences } = state;
107114
delete inferences[action.payload.taskID];
108115

109116
return {
110117
...state,
111-
inferences,
118+
inferences: { ...inferences },
112119
};
113120
}
114121
case AuthActionTypes.LOGOUT_SUCCESS: {

cvat-ui/src/reducers/notifications-reducer.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const defaultState: NotificationsState = {
5050
starting: null,
5151
deleting: null,
5252
fetching: null,
53+
canceling: null,
5354
metaFetching: null,
5455
inferenceStatusFetching: null,
5556
},
@@ -432,7 +433,7 @@ export default function (state = defaultState, action: AnyAction): Notifications
432433
},
433434
};
434435
}
435-
case ModelsActionTypes.INFER_MODEL_FAILED: {
436+
case ModelsActionTypes.START_INFERENCE_FAILED: {
436437
const { taskID } = action.payload;
437438
return {
438439
...state,
@@ -449,6 +450,23 @@ export default function (state = defaultState, action: AnyAction): Notifications
449450
},
450451
};
451452
}
453+
case ModelsActionTypes.CANCEL_INFERENCE_FAILED: {
454+
const { taskID } = action.payload;
455+
return {
456+
...state,
457+
errors: {
458+
...state.errors,
459+
models: {
460+
...state.errors.models,
461+
canceling: {
462+
message: 'Could not cancel model inference for the '
463+
+ `<a href="/tasks/${taskID}" target="_blank">task ${taskID}</a>`,
464+
reason: action.payload.error.toString(),
465+
},
466+
},
467+
},
468+
};
469+
}
452470
case AnnotationActionTypes.GET_JOB_FAILED: {
453471
return {
454472
...state,

0 commit comments

Comments
 (0)