You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
6.9 KiB
TypeScript

// Copyright (C) 2019-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT
import { Dispatch, ActionCreator } from 'redux';
import { ActionUnion, createAction, ThunkAction } from 'utils/redux';
import {
ProjectsQuery, TasksQuery, CombinedState, Indexable,
} from 'reducers';
import { getTasksAsync } from 'actions/tasks-actions';
import { getCVATStore } from 'cvat-store';
import { getCore } from 'cvat-core-wrapper';
const cvat = getCore();
export enum ProjectsActionTypes {
UPDATE_PROJECTS_GETTING_QUERY = 'UPDATE_PROJECTS_GETTING_QUERY',
GET_PROJECTS = 'GET_PROJECTS',
GET_PROJECTS_SUCCESS = 'GET_PROJECTS_SUCCESS',
GET_PROJECTS_FAILED = 'GET_PROJECTS_FAILED',
CREATE_PROJECT = 'CREATE_PROJECT',
CREATE_PROJECT_SUCCESS = 'CREATE_PROJECT_SUCCESS',
CREATE_PROJECT_FAILED = 'CREATE_PROJECT_FAILED',
UPDATE_PROJECT = 'UPDATE_PROJECT',
UPDATE_PROJECT_SUCCESS = 'UPDATE_PROJECT_SUCCESS',
UPDATE_PROJECT_FAILED = 'UPDATE_PROJECT_FAILED',
DELETE_PROJECT = 'DELETE_PROJECT',
DELETE_PROJECT_SUCCESS = 'DELETE_PROJECT_SUCCESS',
DELETE_PROJECT_FAILED = 'DELETE_PROJECT_FAILED',
}
// prettier-ignore
const projectActions = {
getProjects: () => createAction(ProjectsActionTypes.GET_PROJECTS),
getProjectsSuccess: (array: any[], previews: string[], count: number) => (
createAction(ProjectsActionTypes.GET_PROJECTS_SUCCESS, { array, previews, count })
),
getProjectsFailed: (error: any) => createAction(ProjectsActionTypes.GET_PROJECTS_FAILED, { error }),
updateProjectsGettingQuery: (query: Partial<ProjectsQuery>, tasksQuery: Partial<TasksQuery> = {}) => (
createAction(ProjectsActionTypes.UPDATE_PROJECTS_GETTING_QUERY, { query, tasksQuery })
),
createProject: () => createAction(ProjectsActionTypes.CREATE_PROJECT),
createProjectSuccess: (projectId: number) => (
createAction(ProjectsActionTypes.CREATE_PROJECT_SUCCESS, { projectId })
),
createProjectFailed: (error: any) => createAction(ProjectsActionTypes.CREATE_PROJECT_FAILED, { error }),
updateProject: () => createAction(ProjectsActionTypes.UPDATE_PROJECT),
updateProjectSuccess: (project: any) => createAction(ProjectsActionTypes.UPDATE_PROJECT_SUCCESS, { project }),
updateProjectFailed: (project: any, error: any) => (
createAction(ProjectsActionTypes.UPDATE_PROJECT_FAILED, { project, error })
),
deleteProject: (projectId: number) => createAction(ProjectsActionTypes.DELETE_PROJECT, { projectId }),
deleteProjectSuccess: (projectId: number) => (
createAction(ProjectsActionTypes.DELETE_PROJECT_SUCCESS, { projectId })
),
deleteProjectFailed: (projectId: number, error: any) => (
createAction(ProjectsActionTypes.DELETE_PROJECT_FAILED, { projectId, error })
),
};
export type ProjectActions = ActionUnion<typeof projectActions>;
export function getProjectTasksAsync(tasksQuery: Partial<TasksQuery> = {}): ThunkAction<void> {
return (dispatch: ActionCreator<Dispatch>, getState: () => CombinedState): void => {
const store = getCVATStore();
const state: CombinedState = store.getState();
dispatch(projectActions.updateProjectsGettingQuery(
getState().projects.gettingQuery,
tasksQuery,
));
const query: Partial<TasksQuery> = {
...state.projects.tasksGettingQuery,
...tasksQuery,
};
dispatch(getTasksAsync(query, false));
};
}
export function getProjectsAsync(
query: Partial<ProjectsQuery>, tasksQuery: Partial<TasksQuery> = {},
): ThunkAction {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
dispatch(projectActions.getProjects());
dispatch(projectActions.updateProjectsGettingQuery(query, tasksQuery));
// Clear query object from null fields
const filteredQuery: Partial<ProjectsQuery> = {
page: 1,
...query,
};
for (const key of Object.keys(filteredQuery)) {
const value = (filteredQuery as Indexable)[key];
if (value === null || typeof value === 'undefined') {
delete (filteredQuery as Indexable)[key];
}
}
let result = null;
try {
result = await cvat.projects.get(filteredQuery);
} catch (error) {
dispatch(projectActions.getProjectsFailed(error));
return;
}
const array = Array.from(result);
const previewPromises = array.map((project): string => (project as any).preview().catch(() => ''));
dispatch(projectActions.getProjectsSuccess(array, await Promise.all(previewPromises), result.count));
// Appropriate tasks fetching proccess needs with retrieving only a single project
if (Object.keys(filteredQuery).includes('id') && typeof filteredQuery.id === 'number') {
dispatch(getProjectTasksAsync({
...tasksQuery,
projectId: filteredQuery.id,
}));
}
};
}
export function createProjectAsync(data: any): ThunkAction {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
const projectInstance = new cvat.classes.Project(data);
dispatch(projectActions.createProject());
try {
const savedProject = await projectInstance.save();
dispatch(projectActions.createProjectSuccess(savedProject.id));
return savedProject;
} catch (error) {
dispatch(projectActions.createProjectFailed(error));
throw error;
}
};
}
export function updateProjectAsync(projectInstance: any): ThunkAction {
return async (dispatch, getState): Promise<void> => {
try {
const state = getState();
dispatch(projectActions.updateProject());
await projectInstance.save();
const [project] = await cvat.projects.get({ id: projectInstance.id });
dispatch(projectActions.updateProjectSuccess(project));
dispatch(getProjectTasksAsync(state.projects.tasksGettingQuery));
} catch (error) {
let project = null;
try {
[project] = await cvat.projects.get({ id: projectInstance.id });
} catch (fetchError) {
dispatch(projectActions.updateProjectFailed(projectInstance, error));
return;
}
dispatch(projectActions.updateProjectFailed(project, error));
}
};
}
export function deleteProjectAsync(projectInstance: any): ThunkAction {
return async (dispatch: ActionCreator<Dispatch>): Promise<void> => {
dispatch(projectActions.deleteProject(projectInstance.id));
try {
await projectInstance.delete();
dispatch(projectActions.deleteProjectSuccess(projectInstance.id));
} catch (error) {
dispatch(projectActions.deleteProjectFailed(projectInstance.id, error));
}
};
}