Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React & Antd UI: Export dataset, refactoring & fixes #872

Merged
merged 15 commits into from
Nov 28, 2019
Merged
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ $ python3 -m venv .env
$ . .env/bin/activate
$ pip install -U pip wheel
$ pip install -r cvat/requirements/development.txt
$ pip install -r datumaro/requirements.txt
$ python manage.py migrate
$ python manage.py collectstatic
```
Expand Down
3 changes: 2 additions & 1 deletion cvat-core/src/server-proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@
`${encodeURIComponent('password')}=${encodeURIComponent(password)}`,
]).join('&').replace(/%20/g, '+');

Axios.defaults.headers.common.Authorization = '';
let authenticationResponse = null;
try {
authenticationResponse = await Axios.post(
Expand Down Expand Up @@ -246,7 +247,7 @@
try {
await Axios.delete(`${backendAPI}/tasks/${id}`);
} catch (errorData) {
throw generateError(errorData, 'Could not delete the task from the server');
throw generateError(errorData, `Could not delete the task ${id} from the server`);
}
}

Expand Down
39 changes: 27 additions & 12 deletions cvat-ui/src/actions/formats-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,53 @@ import getCore from '../core';
const cvat = getCore();

export enum FormatsActionTypes {
GETTING_FORMATS_SUCCESS = 'GETTING_FORMATS_SUCCESS',
GETTING_FORMATS_FAILED = 'GETTING_FORMATS_FAILED',
GET_FORMATS = 'GET_FORMATS',
GET_FORMATS_SUCCESS = 'GET_FORMATS_SUCCESS',
GET_FORMATS_FAILED = 'GET_FORMATS_FAILED',
}

export function gettingFormatsSuccess(formats: any): AnyAction {
function getFormats(): AnyAction {
return {
type: FormatsActionTypes.GETTING_FORMATS_SUCCESS,
type: FormatsActionTypes.GET_FORMATS,
payload: {},
};
}

function getFormatsSuccess(
annotationFormats: any[],
datasetFormats: any[],
): AnyAction {
return {
type: FormatsActionTypes.GET_FORMATS_SUCCESS,
payload: {
formats,
annotationFormats,
datasetFormats,
},
};
}

export function gettingFormatsFailed(error: any): AnyAction {
function getFormatsFailed(error: any): AnyAction {
return {
type: FormatsActionTypes.GETTING_FORMATS_FAILED,
type: FormatsActionTypes.GET_FORMATS_FAILED,
payload: {
error,
},
};
}

export function gettingFormatsAsync(): ThunkAction<Promise<void>, {}, {}, AnyAction> {
export function getFormatsAsync(): ThunkAction<Promise<void>, {}, {}, AnyAction> {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
let formats = null;
dispatch(getFormats());
let annotationFormats = null;
let datasetFormats = null;
try {
formats = await cvat.server.formats();
annotationFormats = await cvat.server.formats();
datasetFormats = await cvat.server.datasetFormats();
} catch (error) {
dispatch(gettingFormatsFailed(error));
dispatch(getFormatsFailed(error));
return;
}

dispatch(gettingFormatsSuccess(formats));
dispatch(getFormatsSuccess(annotationFormats, datasetFormats));
};
}
202 changes: 201 additions & 1 deletion cvat-ui/src/actions/models-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ import { ThunkAction } from 'redux-thunk';

import getCore from '../core';
import { getCVATStore } from '../store';
import { Model, ModelFiles, CombinedState } from '../reducers/interfaces';
import {
Model,
ModelFiles,
ActiveInference,
CombinedState,
} from '../reducers/interfaces';

export enum ModelsActionTypes {
GET_MODELS = 'GET_MODELS',
Expand Down Expand Up @@ -324,6 +329,199 @@ ThunkAction<Promise<void>, {}, {}, AnyAction> {
};
}


function getInferenceStatusSuccess(
taskID: number,
activeInference: ActiveInference,
): AnyAction {
const action = {
type: ModelsActionTypes.GET_INFERENCE_STATUS_SUCCESS,
payload: {
taskID,
activeInference,
},
};

return action;
}

function getInferenceStatusFailed(taskID: number, error: any): AnyAction {
const action = {
type: ModelsActionTypes.GET_INFERENCE_STATUS_FAILED,
payload: {
taskID,
error,
},
};

return action;
}

interface InferenceMeta {
active: boolean;
taskID: number;
requestID: string;
}

const timers: any = {};

async function timeoutCallback(
url: string,
taskID: number,
dispatch: ActionCreator<Dispatch>,
): Promise<void> {
try {
delete timers[taskID];

const response = await core.server.request(url, {
method: 'GET',
});

const activeInference: ActiveInference = {
status: response.status,
progress: +response.progress || 0,
error: response.error || response.stderr || '',
};


if (activeInference.status === 'unknown') {
dispatch(getInferenceStatusFailed(
taskID,
new Error(
`Inference status for the task ${taskID} is unknown.`,
),
));

return;
}

if (activeInference.status === 'failed') {
dispatch(getInferenceStatusFailed(
taskID,
new Error(
`Inference status for the task ${taskID} is failed. ${activeInference.error}`,
),
));

return;
}

if (activeInference.status !== 'finished') {
timers[taskID] = setTimeout(
timeoutCallback.bind(
null,
url,
taskID,
dispatch,
), 3000,
);
}

dispatch(getInferenceStatusSuccess(taskID, activeInference));
} catch (error) {
dispatch(getInferenceStatusFailed(taskID, error));
}
}

function subscribe(
urlPath: string,
inferenceMeta: InferenceMeta,
dispatch: ActionCreator<Dispatch>,
): void {
if (!(inferenceMeta.taskID in timers)) {
const requestURL = `${baseURL}/${urlPath}/${inferenceMeta.requestID}`;
timers[inferenceMeta.taskID] = setTimeout(
timeoutCallback.bind(
null,
requestURL,
inferenceMeta.taskID,
dispatch,
),
);
}
}

export function getInferenceStatusAsync(tasks: number[]):
ThunkAction<Promise<void>, {}, {}, AnyAction> {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
function parse(response: any): InferenceMeta[] {
return Object.keys(response).map((key: string): InferenceMeta => ({
taskID: +key,
requestID: response[key].rq_id || key,
active: typeof (response[key].active) === 'undefined' ? ['queued', 'started']
.includes(response[key].status.toLowerCase()) : response[key].active,
}));
}

const store = getCVATStore();
const state: CombinedState = store.getState();
const OpenVINO = state.plugins.plugins.AUTO_ANNOTATION;
const RCNN = state.plugins.plugins.TF_ANNOTATION;
const MaskRCNN = state.plugins.plugins.TF_SEGMENTATION;

try {
if (OpenVINO) {
const response = await core.server.request(
`${baseURL}/auto_annotation/meta/get`, {
method: 'POST',
data: JSON.stringify(tasks),
headers: {
'Content-Type': 'application/json',
},
},
);

parse(response.run)
.filter((inferenceMeta: InferenceMeta): boolean => inferenceMeta.active)
.forEach((inferenceMeta: InferenceMeta): void => {
subscribe('auto_annotation/check', inferenceMeta, dispatch);
});
}

if (RCNN) {
const response = await core.server.request(
`${baseURL}/tensorflow/annotation/meta/get`, {
method: 'POST',
data: JSON.stringify(tasks),
headers: {
'Content-Type': 'application/json',
},
},
);

parse(response)
.filter((inferenceMeta: InferenceMeta): boolean => inferenceMeta.active)
.forEach((inferenceMeta: InferenceMeta): void => {
subscribe('tensorflow/annotation/check/task', inferenceMeta, dispatch);
});
}

if (MaskRCNN) {
const response = await core.server.request(
`${baseURL}/tensorflow/segmentation/meta/get`, {
method: 'POST',
data: JSON.stringify(tasks),
headers: {
'Content-Type': 'application/json',
},
},
);

parse(response)
.filter((inferenceMeta: InferenceMeta): boolean => inferenceMeta.active)
.forEach((inferenceMeta: InferenceMeta): void => {
subscribe('tensorflow/segmentation/check/task', inferenceMeta, dispatch);
});
}
} catch (error) {
tasks.forEach((task: number): void => {
dispatch(getInferenceStatusFailed(task, error));
});
}
};
}


function inferModel(): AnyAction {
const action = {
type: ModelsActionTypes.INFER_MODEL,
Expand Down Expand Up @@ -387,6 +585,8 @@ export function inferModelAsync(
},
);
}

dispatch(getInferenceStatusAsync([taskInstance.id]));
} catch (error) {
dispatch(inferModelFailed(error));
return;
Expand Down
24 changes: 24 additions & 0 deletions cvat-ui/src/actions/notification-actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { AnyAction } from 'redux';

export enum NotificationsActionType {
RESET_ERRORS = 'RESET_ERRORS',
RESET_MESSAGES = 'RESET_MESSAGES',
}

export function resetErrors(): AnyAction {
const action = {
type: NotificationsActionType.RESET_ERRORS,
payload: {},
};

return action;
}

export function resetMessages(): AnyAction {
const action = {
type: NotificationsActionType.RESET_MESSAGES,
payload: {},
};

return action;
}
11 changes: 11 additions & 0 deletions cvat-ui/src/actions/plugins-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,23 @@ import { SupportedPlugins } from '../reducers/interfaces';
import PluginChecker from '../utils/plugin-checker';

export enum PluginsActionTypes {
CHECK_PLUGINS = 'CHECK_PLUGINS',
CHECKED_ALL_PLUGINS = 'CHECKED_ALL_PLUGINS'
}

interface PluginObjects {
[plugin: string]: boolean;
}

function checkPlugins(): AnyAction {
const action = {
type: PluginsActionTypes.CHECK_PLUGINS,
payload: {},
};

return action;
}

function checkedAllPlugins(plugins: PluginObjects): AnyAction {
const action = {
type: PluginsActionTypes.CHECKED_ALL_PLUGINS,
Expand All @@ -25,6 +35,7 @@ function checkedAllPlugins(plugins: PluginObjects): AnyAction {
export function checkPluginsAsync():
ThunkAction<Promise<void>, {}, {}, AnyAction> {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
dispatch(checkPlugins());
const plugins: PluginObjects = {};

const promises: Promise<boolean>[] = [];
Expand Down
Loading