From 89ec2db1860fcc6d6e10af4539bd31145ad0481c Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Tue, 7 May 2024 10:28:47 +0300 Subject: [PATCH 1/3] Fixed cannot read property 'annotations' of null --- cvat-ui/src/actions/annotation-actions.ts | 9 ++++++- cvat-ui/src/actions/import-actions.ts | 26 +++++++++---------- .../annotation-page/annotation-page.tsx | 8 ++---- cvat-ui/src/reducers/annotation-reducer.ts | 14 +++++----- cvat-ui/src/reducers/notifications-reducer.ts | 17 ++++++++---- cvat-ui/src/reducers/review-reducer.ts | 2 +- cvat-ui/src/reducers/tasks-reducer.ts | 8 +----- 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/cvat-ui/src/actions/annotation-actions.ts b/cvat-ui/src/actions/annotation-actions.ts index bab89b190575..5dc6a5912747 100644 --- a/cvat-ui/src/actions/annotation-actions.ts +++ b/cvat-ui/src/actions/annotation-actions.ts @@ -869,12 +869,19 @@ export function resetCanvas(): AnyAction { } export function closeJob(): ThunkAction { - return async (dispatch: ActionCreator): Promise => { + return async (dispatch: ActionCreator, getState): Promise => { + const state = getState(); + const { instance: canvasInstance } = state.annotation.canvas; const { jobInstance } = receiveAnnotationsParameters(); + if (jobInstance) { await jobInstance.close(); } + if (canvasInstance) { + canvasInstance.destroy(); + } + dispatch({ type: AnnotationActionTypes.CLOSE_JOB, }); diff --git a/cvat-ui/src/actions/import-actions.ts b/cvat-ui/src/actions/import-actions.ts index 4f54124daaa1..5f5ba82a789f 100644 --- a/cvat-ui/src/actions/import-actions.ts +++ b/cvat-ui/src/actions/import-actions.ts @@ -5,7 +5,9 @@ import { createAction, ActionUnion, ThunkAction } from 'utils/redux'; import { CombinedState } from 'reducers'; -import { getCore, Storage } from 'cvat-core-wrapper'; +import { + getCore, Storage, Job, Task, Project, +} from 'cvat-core-wrapper'; import { EventScope } from 'cvat-logger'; import { getProjectsAsync } from './projects-actions'; import { AnnotationActionTypes, fetchAnnotationsAsync } from './annotation-actions'; @@ -36,10 +38,10 @@ export const importActions = { importDataset: (instance: any, format: string) => ( createAction(ImportActionTypes.IMPORT_DATASET, { instance, format }) ), - importDatasetSuccess: (instance: any, resource: 'dataset' | 'annotation') => ( + importDatasetSuccess: (instance: Job | Task | Project, resource: 'dataset' | 'annotation') => ( createAction(ImportActionTypes.IMPORT_DATASET_SUCCESS, { instance, resource }) ), - importDatasetFailed: (instance: any, resource: 'dataset' | 'annotation', error: any) => ( + importDatasetFailed: (instance: Job | Task | Project, resource: 'dataset' | 'annotation', error: any) => ( createAction(ImportActionTypes.IMPORT_DATASET_FAILED, { instance, resource, @@ -112,22 +114,18 @@ export const importDatasetAsync = ( await instance.logger.log(EventScope.uploadAnnotations); await instance.annotations.clear(true); await instance.actions.clear(); - const history = await instance.actions.get(); // first set empty objects list // to escape some problems in canvas when shape with the same // clientID has different type (polygon, rectangle) for example - dispatch({ - type: AnnotationActionTypes.UPLOAD_JOB_ANNOTATIONS_SUCCESS, - payload: { - states: [], - history, - }, - }); + dispatch({ type: AnnotationActionTypes.UPLOAD_JOB_ANNOTATIONS_SUCCESS }); - setTimeout(() => { - dispatch(fetchAnnotationsAsync()); - }); + const relevantInstance = getState().annotation.job.instance; + if (relevantInstance && relevantInstance.id === instance.id) { + setTimeout(() => { + dispatch(fetchAnnotationsAsync()); + }); + } } } catch (error) { dispatch(importActions.importDatasetFailed(instance, resource, error)); diff --git a/cvat-ui/src/components/annotation-page/annotation-page.tsx b/cvat-ui/src/components/annotation-page/annotation-page.tsx index feda1d91c9f6..93e2c2ec4378 100644 --- a/cvat-ui/src/components/annotation-page/annotation-page.tsx +++ b/cvat-ui/src/components/annotation-page/annotation-page.tsx @@ -4,7 +4,6 @@ // SPDX-License-Identifier: MIT import React, { useEffect } from 'react'; -import { useHistory } from 'react-router'; import Layout from 'antd/lib/layout'; import Result from 'antd/lib/result'; import Spin from 'antd/lib/spin'; @@ -44,7 +43,6 @@ export default function AnnotationPageComponent(props: Props): JSX.Element { const prevJob = usePrevious(job); const prevFetching = usePrevious(fetching); - const history = useHistory(); useEffect(() => { saveLogs(); const root = window.document.getElementById('root'); @@ -54,13 +52,11 @@ export default function AnnotationPageComponent(props: Props): JSX.Element { return () => { saveLogs(); + closeJob(); + if (root) { root.style.minHeight = ''; } - - if (!history.location.pathname.includes('/jobs')) { - closeJob(); - } }; }, []); diff --git a/cvat-ui/src/reducers/annotation-reducer.ts b/cvat-ui/src/reducers/annotation-reducer.ts index c18d042c19db..cd6c41ff795c 100644 --- a/cvat-ui/src/reducers/annotation-reducer.ts +++ b/cvat-ui/src/reducers/annotation-reducer.ts @@ -779,15 +779,16 @@ export default (state = defaultState, action: AnyAction): AnnotationState => { }; } case AnnotationActionTypes.UPLOAD_JOB_ANNOTATIONS_SUCCESS: { - const { states, history } = action.payload; - return { ...state, annotations: { ...state.annotations, - history, - states, + history: { undo: [], redo: [] }, + states: [], activatedStateID: null, + activatedElementID: null, + activatedAttributeID: null, + highlightedConflict: null, collapsed: {}, }, }; @@ -1083,10 +1084,7 @@ export default (state = defaultState, action: AnyAction): AnnotationState => { } case AnnotationActionTypes.CLOSE_JOB: case AuthActionTypes.LOGOUT_SUCCESS: { - if (state.canvas.instance) { - state.canvas.instance.destroy(); - } - return { ...defaultState }; + return defaultState; } default: { return state; diff --git a/cvat-ui/src/reducers/notifications-reducer.ts b/cvat-ui/src/reducers/notifications-reducer.ts index c692cd584203..5d6d7c6d0ff0 100644 --- a/cvat-ui/src/reducers/notifications-reducer.ts +++ b/cvat-ui/src/reducers/notifications-reducer.ts @@ -5,7 +5,7 @@ import { AnyAction } from 'redux'; -import { ServerError } from 'cvat-core-wrapper'; +import { Project, ServerError, Task } from 'cvat-core-wrapper'; import { AuthActionTypes } from 'actions/auth-actions'; import { FormatsActionTypes } from 'actions/formats-actions'; import { ModelsActionTypes } from 'actions/models-actions'; @@ -567,10 +567,17 @@ export default function (state = defaultState, action: AnyAction): Notifications } case ImportActionTypes.IMPORT_DATASET_SUCCESS: { const { instance, resource } = action.payload; - const message = resource === 'annotation' ? - 'Annotations have been loaded to the ' + - `[task ${instance.taskId || instance.id}](/tasks/${instance.taskId || instance.id}) ` : - `Dataset was imported to the [project ${instance.id}](/projects/${instance.id})`; + let message = resource === 'annotation' ? + 'Annotations have been loaded to the ' : + 'Dataset was imported to the '; + if (instance instanceof Project) { + message += `[Project ${instance.id}](/projects/${instance.id})`; + } else if (instance instanceof Task) { + message += `[Task ${instance.id}](/tasks/${instance.id})`; + } else { + message += `[Job ${instance.id}](/jobs/${instance.id})`; + } + return { ...state, messages: { diff --git a/cvat-ui/src/reducers/review-reducer.ts b/cvat-ui/src/reducers/review-reducer.ts index 59ad59dd5dd0..ac0d3ecc09ad 100644 --- a/cvat-ui/src/reducers/review-reducer.ts +++ b/cvat-ui/src/reducers/review-reducer.ts @@ -197,7 +197,7 @@ export default function (state: ReviewState = defaultState, action: any): Review } case AnnotationActionTypes.CLOSE_JOB: case AuthActionTypes.LOGOUT_SUCCESS: { - return { ...defaultState }; + return defaultState; } default: return state; diff --git a/cvat-ui/src/reducers/tasks-reducer.ts b/cvat-ui/src/reducers/tasks-reducer.ts index 8daf4550b6a7..8efcde107509 100644 --- a/cvat-ui/src/reducers/tasks-reducer.ts +++ b/cvat-ui/src/reducers/tasks-reducer.ts @@ -1,5 +1,5 @@ // Copyright (C) 2020-2022 Intel Corporation -// Copyright (C) 2022-2023 CVAT.ai Corporation +// Copyright (C) 2022-2024 CVAT.ai Corporation // // SPDX-License-Identifier: MIT @@ -8,7 +8,6 @@ import { BoundariesActionTypes } from 'actions/boundaries-actions'; import { TasksActionTypes } from 'actions/tasks-actions'; import { AuthActionTypes } from 'actions/auth-actions'; -import { AnnotationActionTypes } from 'actions/annotation-actions'; import { TasksState } from '.'; const defaultState: TasksState = { @@ -136,11 +135,6 @@ export default (state: TasksState = defaultState, action: AnyAction): TasksState }, }; } - case AnnotationActionTypes.CLOSE_JOB: { - return { - ...state, - }; - } case BoundariesActionTypes.RESET_AFTER_ERROR: case AuthActionTypes.LOGOUT_SUCCESS: { return { ...defaultState }; From d045926659c2eae442ffdf81f0da1ed1e77834f4 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Tue, 7 May 2024 10:31:54 +0300 Subject: [PATCH 2/3] Added changelog --- changelog.d/20240507_103107_boris_fixed_exception.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 changelog.d/20240507_103107_boris_fixed_exception.md diff --git a/changelog.d/20240507_103107_boris_fixed_exception.md b/changelog.d/20240507_103107_boris_fixed_exception.md new file mode 100644 index 000000000000..fc9a7a3fdd68 --- /dev/null +++ b/changelog.d/20240507_103107_boris_fixed_exception.md @@ -0,0 +1,4 @@ +### Fixed + +- Cannot read property 'annotations' of null when uploading annotations into a job + () From cf9bb78899d7b2498ca758d3f90b716b8b2c89b9 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Tue, 7 May 2024 10:32:14 +0300 Subject: [PATCH 3/3] Updated version --- cvat-ui/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 418d188935c7..cddf7606aa97 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.63.9", + "version": "1.63.10", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": {