Skip to content

Commit

Permalink
Task moving between projects (#3164)
Browse files Browse the repository at this point in the history
  • Loading branch information
ActiveChooN authored May 20, 2021
1 parent e0f10d7 commit a2df499
Show file tree
Hide file tree
Showing 24 changed files with 726 additions and 45 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Hotkeys to switch a label of existing object or to change default label (for objects created with N) (<https://github.com/openvinotoolkit/cvat/pull/3070>)
- A script to convert some kinds of DICOM files to regular images (<https://github.com/openvinotoolkit/cvat/pull/3095>)
- Helm chart prototype (<https://github.com/openvinotoolkit/cvat/pull/3102>)
- Initial implementation of moving tasks between projects (<https://github.com/openvinotoolkit/cvat/pull/3164>)

### Changed

Expand Down
2 changes: 1 addition & 1 deletion cvat-core/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cvat-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cvat-core",
"version": "3.13.0",
"version": "3.12.3",
"description": "Part of Computer Vision Tool which presents an interface for client-side integration",
"main": "babel.config.js",
"scripts": {
Expand Down
32 changes: 32 additions & 0 deletions cvat-core/src/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,37 @@
}
negativeIDGenerator.start = -1;

class FieldUpdateTrigger {
constructor(initialFields) {
const data = { ...initialFields };

Object.defineProperties(
this,
Object.freeze({
...Object.assign(
{},
...Array.from(Object.keys(data), (key) => ({
[key]: {
get: () => data[key],
set: (value) => {
data[key] = value;
},
enumerable: true,
},
})),
),
reset: {
value: () => {
Object.keys(data).forEach((key) => {
data[key] = false;
});
},
},
}),
);
}
}

module.exports = {
isBoolean,
isInteger,
Expand All @@ -114,5 +145,6 @@
negativeIDGenerator,
checkExclusiveFields,
camelToSnake,
FieldUpdateTrigger,
};
})();
4 changes: 3 additions & 1 deletion cvat-core/src/server-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -1082,7 +1082,9 @@

const closureId = Date.now();
predictAnnotations.latestRequest.id = closureId;
const predicate = () => !predictAnnotations.latestRequest.fetching || predictAnnotations.latestRequest.id !== closureId;
const predicate = () => (
!predictAnnotations.latestRequest.fetching || predictAnnotations.latestRequest.id !== closureId
);
if (predictAnnotations.latestRequest.fetching) {
waitFor(5, predicate).then(() => {
if (predictAnnotations.latestRequest.id !== closureId) {
Expand Down
42 changes: 19 additions & 23 deletions cvat-core/src/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
const User = require('./user');
const Issue = require('./issue');
const Review = require('./review');
const { FieldUpdateTrigger } = require('./common');

function buildDublicatedAPI(prototype) {
Object.defineProperties(prototype, {
Expand Down Expand Up @@ -734,11 +735,11 @@
task: undefined,
};

let updatedFields = {
const updatedFields = new FieldUpdateTrigger({
assignee: false,
reviewer: false,
status: false,
};
});

for (const property in data) {
if (Object.prototype.hasOwnProperty.call(data, property)) {
Expand Down Expand Up @@ -865,9 +866,6 @@
},
__updatedFields: {
get: () => updatedFields,
set: (fields) => {
updatedFields = fields;
},
},
}),
);
Expand Down Expand Up @@ -1040,13 +1038,14 @@
dimension: undefined,
};

let updatedFields = {
const updatedFields = new FieldUpdateTrigger({
name: false,
assignee: false,
bug_tracker: false,
subset: false,
labels: false,
};
project_id: false,
});

for (const property in data) {
if (Object.prototype.hasOwnProperty.call(data, property) && property in initialData) {
Expand Down Expand Up @@ -1126,11 +1125,18 @@
* @name projectId
* @type {integer|null}
* @memberof module:API.cvat.classes.Task
* @readonly
* @instance
*/
projectId: {
get: () => data.project_id,
set: (projectId) => {
if (!Number.isInteger(projectId) || projectId <= 0) {
throw new ArgumentError('Value must be a positive integer');
}

updatedFields.project_id = true;
data.project_id = projectId;
},
},
/**
* @name status
Expand Down Expand Up @@ -1558,9 +1564,6 @@
},
__updatedFields: {
get: () => updatedFields,
set: (fields) => {
updatedFields = fields;
},
},
}),
);
Expand Down Expand Up @@ -1721,11 +1724,7 @@

await serverProxy.jobs.save(this.id, jobData);

this.__updatedFields = {
status: false,
assignee: false,
reviewer: false,
};
this.__updatedFields.reset();

return this;
}
Expand Down Expand Up @@ -2000,6 +1999,9 @@
case 'subset':
taskData.subset = this.subset;
break;
case 'project_id':
taskData.project_id = this.projectId;
break;
case 'labels':
taskData.labels = [...this._internalData.labels.map((el) => el.toJSON())];
break;
Expand All @@ -2011,13 +2013,7 @@

await serverProxy.tasks.saveTask(this.id, taskData);

this.updatedFields = {
assignee: false,
name: false,
bugTracker: false,
subset: false,
labels: false,
};
this.__updatedFields.reset();

return this;
}
Expand Down
44 changes: 44 additions & 0 deletions cvat-ui/src/actions/tasks-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export enum TasksActionTypes {
UPDATE_TASK_SUCCESS = 'UPDATE_TASK_SUCCESS',
UPDATE_TASK_FAILED = 'UPDATE_TASK_FAILED',
HIDE_EMPTY_TASKS = 'HIDE_EMPTY_TASKS',
SWITCH_MOVE_TASK_MODAL_VISIBLE = 'SWITCH_MOVE_TASK_MODAL_VISIBLE',
}

function getTasks(): AnyAction {
Expand Down Expand Up @@ -519,3 +520,46 @@ export function hideEmptyTasks(hideEmpty: boolean): AnyAction {

return action;
}

export function switchMoveTaskModalVisible(visible: boolean, taskId: number | null = null): AnyAction {
const action = {
type: TasksActionTypes.SWITCH_MOVE_TASK_MODAL_VISIBLE,
payload: {
taskId,
visible,
},
};

return action;
}

interface LabelMap {
label_id: number;
new_label_name: string | null;
clear_attributes: boolean;
}

export function moveTaskToProjectAsync(
taskInstance: any,
projectId: any,
labelMap: LabelMap[],
): ThunkAction<Promise<void>, {}, {}, AnyAction> {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
dispatch(updateTask());
try {
// eslint-disable-next-line no-param-reassign
taskInstance.labels = labelMap.map((mapper) => {
const [label] = taskInstance.labels.filter((_label: any) => mapper.label_id === _label.id);
label.name = mapper.new_label_name;
return label;
});
// eslint-disable-next-line no-param-reassign
taskInstance.projectId = projectId;
await taskInstance.save();
const [task] = await cvat.tasks.get({ id: taskInstance.id });
dispatch(updateTaskSuccess(task, task.id));
} catch (error) {
dispatch(updateTaskFailed(error, taskInstance));
}
};
}
1 change: 1 addition & 0 deletions cvat-ui/src/base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ $layout-lg-grid-color: rgba(0, 0, 0, 0.15);

$header-color: #d8d8d8;
$text-color: #303030;
$text-color-secondary: rgba(0, 0, 0, 0.45);
$hover-menu-color: rgba(24, 144, 255, 0.05);
$completed-progress-color: #61c200;
$inprogress-progress-color: #1890ff;
Expand Down
2 changes: 2 additions & 0 deletions cvat-ui/src/components/actions-menu/actions-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export enum Actions {
EXPORT_TASK_DATASET = 'export_task_dataset',
DELETE_TASK = 'delete_task',
RUN_AUTO_ANNOTATION = 'run_auto_annotation',
MOVE_TASK_TO_PROJECT = 'move_task_to_project',
OPEN_BUG_TRACKER = 'open_bug_tracker',
}

Expand Down Expand Up @@ -128,6 +129,7 @@ export default function ActionsMenuComponent(props: Props): JSX.Element {
Automatic annotation
</Menu.Item>
<hr />
<Menu.Item key={Actions.MOVE_TASK_TO_PROJECT}>Move to project</Menu.Item>
<Menu.Item key={Actions.DELETE_TASK}>Delete</Menu.Item>
</Menu>
);
Expand Down
7 changes: 6 additions & 1 deletion cvat-ui/src/components/actions-menu/load-submenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ export default function LoadSubmenu(props: Props): JSX.Element {
return false;
}}
>
<Button block type='link' disabled={disabled} className='cvat-menu-load-submenu-item-button'>
<Button
block
type='link'
disabled={disabled}
className='cvat-menu-load-submenu-item-button'
>
<UploadOutlined />
<Text>{loader.name}</Text>
{pending && <LoadingOutlined style={{ marginLeft: 10 }} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT

import React, { useEffect, useState } from 'react';
import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons';
import { SelectValue } from 'antd/lib/select';
Expand Down
11 changes: 8 additions & 3 deletions cvat-ui/src/components/create-task-page/project-search-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const core = getCore();
type Props = {
value: number | null;
onSelect: (id: number | null) => void;
filter?: (value: Project, index: number, array: Project[]) => unknown
};

type Project = {
Expand All @@ -21,7 +22,7 @@ type Project = {
};

export default function ProjectSearchField(props: Props): JSX.Element {
const { value, onSelect } = props;
const { value, filter, onSelect } = props;
const [searchPhrase, setSearchPhrase] = useState('');

const [projects, setProjects] = useState<Project[]>([]);
Expand All @@ -43,8 +44,12 @@ export default function ProjectSearchField(props: Props): JSX.Element {
const handleFocus = (open: boolean): void => {
if (!projects.length && open) {
core.projects.searchNames().then((result: Project[]) => {
if (result) {
setProjects(result);
let projectsResponse = result;
if (typeof filter === 'function') {
projectsResponse = projectsResponse.filter(filter);
}
if (projectsResponse) {
setProjects(projectsResponse);
}
});
}
Expand Down
Loading

0 comments on commit a2df499

Please sign in to comment.