// Copyright (C) 2020-2021 Intel Corporation // // SPDX-License-Identifier: MIT import { AnyAction } from 'redux'; import { AuthActionTypes } from 'actions/auth-actions'; import { FormatsActionTypes } from 'actions/formats-actions'; import { ModelsActionTypes } from 'actions/models-actions'; import { ShareActionTypes } from 'actions/share-actions'; import { TasksActionTypes } from 'actions/tasks-actions'; import { ProjectsActionTypes } from 'actions/projects-actions'; import { AboutActionTypes } from 'actions/about-actions'; import { AnnotationActionTypes } from 'actions/annotation-actions'; import { NotificationsActionType } from 'actions/notification-actions'; import { BoundariesActionTypes } from 'actions/boundaries-actions'; import { UserAgreementsActionTypes } from 'actions/useragreements-actions'; import { ReviewActionTypes } from 'actions/review-actions'; import { ExportActionTypes } from 'actions/export-actions'; import { CloudStorageActionTypes } from 'actions/cloud-storage-actions'; import getCore from 'cvat-core-wrapper'; import { NotificationsState } from './interfaces'; const core = getCore(); const defaultState: NotificationsState = { errors: { auth: { authorized: null, login: null, logout: null, register: null, changePassword: null, requestPasswordReset: null, resetPassword: null, loadAuthActions: null, }, projects: { fetching: null, updating: null, deleting: null, creating: null, }, tasks: { fetching: null, updating: null, dumping: null, loading: null, exportingAsDataset: null, deleting: null, creating: null, exporting: null, importing: null, moving: null, }, formats: { fetching: null, }, users: { fetching: null, }, about: { fetching: null, }, share: { fetching: null, }, models: { starting: null, fetching: null, canceling: null, metaFetching: null, inferenceStatusFetching: null, }, annotation: { saving: null, jobFetching: null, frameFetching: null, contextImageFetching: null, changingLabelColor: null, updating: null, creating: null, merging: null, grouping: null, splitting: null, removing: null, propagating: null, collectingStatistics: null, savingJob: null, uploadAnnotations: null, removeAnnotations: null, fetchingAnnotations: null, undo: null, redo: null, search: null, searchEmptyFrame: null, savingLogs: null, }, boundaries: { resetError: null, }, userAgreements: { fetching: null, }, review: { commentingIssue: null, finishingIssue: null, initialization: null, reopeningIssue: null, resolvingIssue: null, submittingReview: null, }, predictor: { prediction: null, }, cloudStorages: { creating: null, fetching: null, updating: null, deleting: null, }, }, messages: { tasks: { loadingDone: '', importingDone: '', movingDone: '', }, models: { inferenceDone: '', }, auth: { changePasswordDone: '', registerDone: '', requestPasswordResetDone: '', resetPasswordDone: '', }, }, }; export default function (state = defaultState, action: AnyAction): NotificationsState { switch (action.type) { case AuthActionTypes.AUTHORIZED_FAILED: { return { ...state, errors: { ...state.errors, auth: { ...state.errors.auth, authorized: { message: 'Could not check authorization on the server', reason: action.payload.error.toString(), }, }, }, }; } case AuthActionTypes.LOGIN_FAILED: { return { ...state, errors: { ...state.errors, auth: { ...state.errors.auth, login: { message: 'Could not login on the server', reason: action.payload.error.toString(), className: 'cvat-notification-notice-login-failed', }, }, }, }; } case AuthActionTypes.LOGOUT_FAILED: { return { ...state, errors: { ...state.errors, auth: { ...state.errors.auth, logout: { message: 'Could not logout from the server', reason: action.payload.error.toString(), }, }, }, }; } case AuthActionTypes.REGISTER_FAILED: { return { ...state, errors: { ...state.errors, auth: { ...state.errors.auth, register: { message: 'Could not register on the server', reason: action.payload.error.toString(), }, }, }, }; } case AuthActionTypes.REGISTER_SUCCESS: { if (!action.payload.user.isVerified) { return { ...state, messages: { ...state.messages, auth: { ...state.messages.auth, registerDone: `To use your account, you need to confirm the email address. \ We have sent an email with a confirmation link to ${action.payload.user.email}.`, }, }, }; } return { ...state, }; } case AuthActionTypes.CHANGE_PASSWORD_SUCCESS: { return { ...state, messages: { ...state.messages, auth: { ...state.messages.auth, changePasswordDone: 'New password has been saved.', }, }, }; } case AuthActionTypes.CHANGE_PASSWORD_FAILED: { return { ...state, errors: { ...state.errors, auth: { ...state.errors.auth, changePassword: { message: 'Could not change password', reason: action.payload.error.toString(), className: 'cvat-notification-notice-change-password-failed', }, }, }, }; } case AuthActionTypes.REQUEST_PASSWORD_RESET_SUCCESS: { return { ...state, messages: { ...state.messages, auth: { ...state.messages.auth, requestPasswordResetDone: `Check your email for a link to reset your password. If it doesn’t appear within a few minutes, check your spam folder.`, }, }, }; } case AuthActionTypes.REQUEST_PASSWORD_RESET_FAILED: { return { ...state, errors: { ...state.errors, auth: { ...state.errors.auth, requestPasswordReset: { message: 'Could not reset password on the server.', reason: action.payload.error.toString(), }, }, }, }; } case AuthActionTypes.RESET_PASSWORD_SUCCESS: { return { ...state, messages: { ...state.messages, auth: { ...state.messages.auth, resetPasswordDone: 'Password has been reset with the new password.', }, }, }; } case AuthActionTypes.RESET_PASSWORD_FAILED: { return { ...state, errors: { ...state.errors, auth: { ...state.errors.auth, resetPassword: { message: 'Could not set new password on the server.', reason: action.payload.error.toString(), }, }, }, }; } case AuthActionTypes.LOAD_AUTH_ACTIONS_FAILED: { return { ...state, errors: { ...state.errors, auth: { ...state.errors.auth, loadAuthActions: { message: 'Could not check available auth actions', reason: action.payload.error.toString(), }, }, }, }; } case ExportActionTypes.EXPORT_DATASET_FAILED: { const instanceID = action.payload.instance.id; const instanceType = action.payload.instance instanceof core.classes.Project ? 'project' : 'task'; return { ...state, errors: { ...state.errors, tasks: { ...state.errors.tasks, exportingAsDataset: { message: 'Could not export dataset for the ' + `` + `${instanceType} ${instanceID}`, reason: action.payload.error.toString(), }, }, }, }; } case TasksActionTypes.GET_TASKS_FAILED: { return { ...state, errors: { ...state.errors, tasks: { ...state.errors.tasks, fetching: { message: 'Could not fetch tasks', reason: action.payload.error.toString(), }, }, }, }; } case TasksActionTypes.LOAD_ANNOTATIONS_FAILED: { const taskID = action.payload.task.id; return { ...state, errors: { ...state.errors, tasks: { ...state.errors.tasks, loading: { message: 'Could not upload annotation for the ' + `task ${taskID}`, reason: action.payload.error.toString(), className: 'cvat-notification-notice-load-annotation-failed', }, }, }, }; } case TasksActionTypes.LOAD_ANNOTATIONS_SUCCESS: { const taskID = action.payload.task.id; return { ...state, messages: { ...state.messages, tasks: { ...state.messages.tasks, loadingDone: 'Annotations have been loaded to the ' + `task ${taskID}`, }, }, }; } case TasksActionTypes.UPDATE_TASK_FAILED: { const taskID = action.payload.task.id; return { ...state, errors: { ...state.errors, tasks: { ...state.errors.tasks, updating: { message: `Could not update task ${taskID}`, reason: action.payload.error.toString(), className: 'cvat-notification-notice-update-task-failed', }, }, }, }; } case TasksActionTypes.DELETE_TASK_FAILED: { const { taskID } = action.payload; return { ...state, errors: { ...state.errors, tasks: { ...state.errors.tasks, deleting: { message: 'Could not delete the ' + `task ${taskID}`, reason: action.payload.error.toString(), className: 'cvat-notification-notice-delete-task-failed', }, }, }, }; } case TasksActionTypes.CREATE_TASK_FAILED: { return { ...state, errors: { ...state.errors, tasks: { ...state.errors.tasks, creating: { message: 'Could not create the task', reason: action.payload.error.toString(), className: 'cvat-notification-notice-create-task-failed', }, }, }, }; } case TasksActionTypes.EXPORT_TASK_FAILED: { return { ...state, errors: { ...state.errors, tasks: { ...state.errors.tasks, exporting: { message: 'Could not export the task', reason: action.payload.error.toString(), }, }, }, }; } case TasksActionTypes.IMPORT_TASK_FAILED: { return { ...state, errors: { ...state.errors, tasks: { ...state.errors.tasks, importing: { message: 'Could not import the task', reason: action.payload.error.toString(), }, }, }, }; } case TasksActionTypes.IMPORT_TASK_SUCCESS: { const taskID = action.payload.task.id; return { ...state, messages: { ...state.messages, tasks: { ...state.messages.tasks, importingDone: `Task has been imported succesfully Open task`, }, }, }; } case ProjectsActionTypes.GET_PROJECTS_FAILED: { return { ...state, errors: { ...state.errors, projects: { ...state.errors.projects, fetching: { message: 'Could not fetch projects', reason: action.payload.error.toString(), }, }, }, }; } case ProjectsActionTypes.CREATE_PROJECT_FAILED: { return { ...state, errors: { ...state.errors, projects: { ...state.errors.projects, creating: { message: 'Could not create the project', reason: action.payload.error.toString(), className: 'cvat-notification-notice-create-project-failed', }, }, }, }; } case ProjectsActionTypes.UPDATE_PROJECT_FAILED: { const { id: projectId } = action.payload.project; return { ...state, errors: { ...state.errors, projects: { ...state.errors.projects, updating: { message: 'Could not update ' + `project ${projectId}`, reason: action.payload.error.toString(), className: 'cvat-notification-notice-update-project-failed', }, }, }, }; } case ProjectsActionTypes.DELETE_PROJECT_FAILED: { const { projectId } = action.payload; return { ...state, errors: { ...state.errors, projects: { ...state.errors.projects, updating: { message: 'Could not delete ' + `project ${projectId}`, reason: action.payload.error.toString(), className: 'cvat-notification-notice-delete-project-failed', }, }, }, }; } case FormatsActionTypes.GET_FORMATS_FAILED: { return { ...state, errors: { ...state.errors, formats: { ...state.errors.formats, fetching: { message: 'Could not get formats from the server', reason: action.payload.error.toString(), }, }, }, }; } case AboutActionTypes.GET_ABOUT_FAILED: { return { ...state, errors: { ...state.errors, about: { ...state.errors.about, fetching: { message: 'Could not get info about the server', reason: action.payload.error.toString(), }, }, }, }; } case ShareActionTypes.LOAD_SHARE_DATA_FAILED: { return { ...state, errors: { ...state.errors, share: { ...state.errors.share, fetching: { message: 'Could not load share data from the server', reason: action.payload.error.toString(), }, }, }, }; } case ModelsActionTypes.GET_INFERENCE_STATUS_SUCCESS: { if (action.payload.activeInference.status === 'finished') { const { taskID } = action.payload; return { ...state, messages: { ...state.messages, models: { ...state.messages.models, inferenceDone: 'Automatic annotation finished for the ' + `task ${taskID}`, }, }, }; } return { ...state, }; } case ModelsActionTypes.FETCH_META_FAILED: { return { ...state, errors: { ...state.errors, models: { ...state.errors.models, metaFetching: { message: 'Could not fetch models meta information', reason: action.payload.error.toString(), }, }, }, }; } case ModelsActionTypes.GET_INFERENCE_STATUS_FAILED: { const { taskID } = action.payload; return { ...state, errors: { ...state.errors, models: { ...state.errors.models, inferenceStatusFetching: { message: 'Fetching inference status for the ' + `task ${taskID}`, reason: action.payload.error.toString(), }, }, }, }; } case ModelsActionTypes.GET_MODELS_FAILED: { return { ...state, errors: { ...state.errors, models: { ...state.errors.models, fetching: { message: 'Could not get models from the server', reason: action.payload.error.toString(), }, }, }, }; } case ModelsActionTypes.START_INFERENCE_FAILED: { const { taskID } = action.payload; return { ...state, errors: { ...state.errors, models: { ...state.errors.models, starting: { message: 'Could not infer model for the ' + `task ${taskID}`, reason: action.payload.error.toString(), }, }, }, }; } case ModelsActionTypes.CANCEL_INFERENCE_FAILED: { const { taskID } = action.payload; return { ...state, errors: { ...state.errors, models: { ...state.errors.models, canceling: { message: 'Could not cancel model inference for the ' + `task ${taskID}`, reason: action.payload.error.toString(), }, }, }, }; } case AnnotationActionTypes.GET_JOB_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, jobFetching: { message: 'Error during fetching a job', reason: action.payload.error.toString(), className: 'cvat-notification-notice-fetch-job-failed', }, }, }, }; } case AnnotationActionTypes.CHANGE_FRAME_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, frameFetching: { message: `Could not receive frame ${action.payload.number}`, reason: action.payload.error.toString(), }, }, }, }; } case AnnotationActionTypes.GET_CONTEXT_IMAGE_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, contextImageFetching: { message: 'Could not fetch context image from the server', reason: action.payload.error, }, }, }, }; } case AnnotationActionTypes.SAVE_ANNOTATIONS_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, saving: { message: 'Could not save annotations', reason: action.payload.error.toString(), className: 'cvat-notification-notice-save-annotations-failed', }, }, }, }; } case AnnotationActionTypes.UPDATE_ANNOTATIONS_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, updating: { message: 'Could not update annotations', reason: action.payload.error.toString(), className: 'cvat-notification-notice-update-annotations-failed', }, }, }, }; } case AnnotationActionTypes.CREATE_ANNOTATIONS_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, creating: { message: 'Could not create annotations', reason: action.payload.error.toString(), }, }, }, }; } case AnnotationActionTypes.MERGE_ANNOTATIONS_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, merging: { message: 'Could not merge annotations', reason: action.payload.error.toString(), }, }, }, }; } case AnnotationActionTypes.GROUP_ANNOTATIONS_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, grouping: { message: 'Could not group annotations', reason: action.payload.error.toString(), }, }, }, }; } case AnnotationActionTypes.SPLIT_ANNOTATIONS_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, splitting: { message: 'Could not split the track', reason: action.payload.error.toString(), }, }, }, }; } case AnnotationActionTypes.REMOVE_OBJECT_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, removing: { message: 'Could not remove the object', reason: action.payload.error.toString(), className: 'cvat-notification-notice-remove-object-failed', }, }, }, }; } case AnnotationActionTypes.PROPAGATE_OBJECT_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, propagating: { message: 'Could not propagate the object', reason: action.payload.error.toString(), }, }, }, }; } case AnnotationActionTypes.COLLECT_STATISTICS_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, collectingStatistics: { message: 'Could not collect annotations statistics', reason: action.payload.error.toString(), }, }, }, }; } case AnnotationActionTypes.UPLOAD_JOB_ANNOTATIONS_FAILED: { const { job, error } = action.payload; const { id: jobID, task: { id: taskID }, } = job; return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, uploadAnnotations: { message: 'Could not upload annotations for the ' + `job ${taskID}`, reason: error.toString(), className: 'cvat-notification-notice-upload-annotations-fail', }, }, }, }; } case AnnotationActionTypes.REMOVE_JOB_ANNOTATIONS_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, removeAnnotations: { message: 'Could not remove annotations', reason: action.payload.error.toString(), }, }, }, }; } case AnnotationActionTypes.FETCH_ANNOTATIONS_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, fetchingAnnotations: { message: 'Could not fetch annotations', reason: action.payload.error.toString(), }, }, }, }; } case AnnotationActionTypes.REDO_ACTION_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, redo: { message: 'Could not redo', reason: action.payload.error.toString(), }, }, }, }; } case AnnotationActionTypes.UNDO_ACTION_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, undo: { message: 'Could not undo', reason: action.payload.error.toString(), }, }, }, }; } case AnnotationActionTypes.SEARCH_ANNOTATIONS_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, search: { message: 'Could not execute search annotations', reason: action.payload.error.toString(), }, }, }, }; } case AnnotationActionTypes.SEARCH_EMPTY_FRAME_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, searchEmptyFrame: { message: 'Could not search an empty frame', reason: action.payload.error.toString(), }, }, }, }; } case AnnotationActionTypes.SAVE_LOGS_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, savingLogs: { message: 'Could not send logs to the server', reason: action.payload.error.toString(), }, }, }, }; } case BoundariesActionTypes.THROW_RESET_ERROR: { return { ...state, errors: { ...state.errors, boundaries: { ...state.errors.annotation, resetError: { message: 'Could not reset the state', reason: action.payload.error.toString(), }, }, }, }; } case UserAgreementsActionTypes.GET_USER_AGREEMENTS_FAILED: { return { ...state, errors: { ...state.errors, userAgreements: { ...state.errors.userAgreements, fetching: { message: 'Could not get user agreements from the server', reason: action.payload.error.toString(), }, }, }, }; } case ReviewActionTypes.INITIALIZE_REVIEW_FAILED: { return { ...state, errors: { ...state.errors, review: { ...state.errors.review, initialization: { message: 'Could not initialize review session', reason: action.payload.error.toString(), }, }, }, }; } case ReviewActionTypes.FINISH_ISSUE_FAILED: { return { ...state, errors: { ...state.errors, review: { ...state.errors.review, finishingIssue: { message: 'Could not open a new issue', reason: action.payload.error.toString(), }, }, }, }; } case ReviewActionTypes.RESOLVE_ISSUE_FAILED: { return { ...state, errors: { ...state.errors, review: { ...state.errors.review, resolvingIssue: { message: 'Could not resolve the issue', reason: action.payload.error.toString(), }, }, }, }; } case ReviewActionTypes.REOPEN_ISSUE_FAILED: { return { ...state, errors: { ...state.errors, review: { ...state.errors.review, reopeningIssue: { message: 'Could not reopen the issue', reason: action.payload.error.toString(), }, }, }, }; } case ReviewActionTypes.COMMENT_ISSUE_FAILED: { return { ...state, errors: { ...state.errors, review: { ...state.errors.review, commentingIssue: { message: 'Could not comment the issue', reason: action.payload.error.toString(), }, }, }, }; } case ReviewActionTypes.SUBMIT_REVIEW_FAILED: { return { ...state, errors: { ...state.errors, review: { ...state.errors.review, submittingReview: { message: 'Could not submit review session to the server', reason: action.payload.error.toString(), }, }, }, }; } case NotificationsActionType.RESET_ERRORS: { return { ...state, errors: { ...defaultState.errors, }, }; } case NotificationsActionType.RESET_MESSAGES: { return { ...state, messages: { ...defaultState.messages, }, }; } case AnnotationActionTypes.GET_DATA_FAILED: { return { ...state, errors: { ...state.errors, annotation: { ...state.errors.annotation, jobFetching: { message: 'Could not fetch frame data from the server', reason: action.payload.error, }, }, }, }; } case AnnotationActionTypes.GET_PREDICTIONS_FAILED: { return { ...state, errors: { ...state.errors, predictor: { ...state.errors.predictor, prediction: { message: 'Could not fetch prediction data', reason: action.payload.error, }, }, }, }; } case CloudStorageActionTypes.GET_CLOUD_STORAGE_FAILED: { return { ...state, errors: { ...state.errors, cloudStorages: { ...state.errors.cloudStorages, fetching: { message: 'Could not fetch cloud storage', reason: action.payload.error.toString(), }, }, }, }; } case CloudStorageActionTypes.CREATE_CLOUD_STORAGE_FAILED: { return { ...state, errors: { ...state.errors, cloudStorages: { ...state.errors.cloudStorages, creating: { message: 'Could not create the cloud storage', reason: action.payload.error.toString(), className: 'cvat-notification-notice-create-cloud-storage-failed', }, }, }, }; } case CloudStorageActionTypes.UPDATE_CLOUD_STORAGE_FAILED: { const { cloudStorage, error } = action.payload; return { ...state, errors: { ...state.errors, cloudStorages: { ...state.errors.cloudStorages, updating: { message: `Could not update cloud storage #${cloudStorage.id}`, reason: error.toString(), className: 'cvat-notification-notice-update-cloud-storage-failed', }, }, }, }; } case CloudStorageActionTypes.DELETE_CLOUD_STORAGE_FAILED: { const { cloudStorageID } = action.payload; return { ...state, errors: { ...state.errors, cloudStorages: { ...state.errors.cloudStorages, deleting: { message: 'Could not delete ' + ` cloud storage ${cloudStorageID}`, reason: action.payload.error.toString(), className: 'cvat-notification-notice-delete-cloud-storage-failed', }, }, }, }; } case CloudStorageActionTypes.LOAD_CLOUD_STORAGE_CONTENT_FAILED: { const { cloudStorageID } = action.payload; return { ...state, errors: { ...state.errors, cloudStorages: { ...state.errors.cloudStorages, fetching: { message: `Could not fetch content for cloud storage #${cloudStorageID}`, reason: action.payload.error.toString(), className: 'cvat-notification-notice-fetch-cloud-storage-content-failed', }, }, }, }; } case CloudStorageActionTypes.GET_CLOUD_STORAGE_STATUS_FAILED: { const { cloudStorageID } = action.payload; return { ...state, errors: { ...state.errors, cloudStorages: { ...state.errors.cloudStorages, fetching: { message: `Could not fetch cloud storage #${cloudStorageID} status`, reason: action.payload.error.toString(), className: 'cvat-notification-notice-fetch-cloud-storage-status-failed', }, }, }, }; } case CloudStorageActionTypes.GET_CLOUD_STORAGE_PREVIEW_FAILED: { const { cloudStorageID } = action.payload; return { ...state, errors: { ...state.errors, cloudStorages: { ...state.errors.cloudStorages, fetching: { message: `Could not fetch preview for cloud storage #${cloudStorageID}`, reason: action.payload.error.toString(), className: 'cvat-notification-notice-fetch-cloud-storage-preview-failed', }, }, }, }; } case BoundariesActionTypes.RESET_AFTER_ERROR: case AuthActionTypes.LOGOUT_SUCCESS: { return { ...defaultState }; } default: { return state; } } }