Fixed: cannot read property 'label' of undefined (#2311)

* Fixed: cannot read property 'label' of undefined

* Updated UI package version & changelog

* Fixed tests
main
Boris Sekachev 5 years ago committed by GitHub
parent 975d7261d7
commit bcc8bba39e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -63,6 +63,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- A problem in exporting of tracks, where tracks could be truncated (<https://github.com/openvinotoolkit/cvat/issues/2129>) - A problem in exporting of tracks, where tracks could be truncated (<https://github.com/openvinotoolkit/cvat/issues/2129>)
- Fixed CVAT startup process if the user has `umask 077` in .bashrc file (<https://github.com/openvinotoolkit/cvat/pull/2293>) - Fixed CVAT startup process if the user has `umask 077` in .bashrc file (<https://github.com/openvinotoolkit/cvat/pull/2293>)
- Exception: Cannot read property "each" of undefined after drawing a single point (<https://github.com/openvinotoolkit/cvat/pull/2307>) - Exception: Cannot read property "each" of undefined after drawing a single point (<https://github.com/openvinotoolkit/cvat/pull/2307>)
- Cannot read property 'label' of undefined (Fixed?) (<https://github.com/openvinotoolkit/cvat/pull/2311>)
### Security ### Security

@ -1,6 +1,6 @@
{ {
"name": "cvat-ui", "name": "cvat-ui",
"version": "1.9.12", "version": "1.9.13",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

@ -1,6 +1,6 @@
{ {
"name": "cvat-ui", "name": "cvat-ui",
"version": "1.9.12", "version": "1.9.13",
"description": "CVAT single-page application", "description": "CVAT single-page application",
"main": "src/index.tsx", "main": "src/index.tsx",
"scripts": { "scripts": {

@ -9,18 +9,14 @@ import ObjectItemContainer from 'containers/annotation-page/standard-workspace/o
interface Props { interface Props {
activatedStateID: number | null; activatedStateID: number | null;
objectStates: any[];
visible: boolean; visible: boolean;
left: number; left: number;
top: number; top: number;
} }
export default function CanvasContextMenu(props: Props): JSX.Element | null { export default function CanvasContextMenu(props: Props): JSX.Element | null {
const { const { activatedStateID, objectStates, visible, left, top } = props;
activatedStateID,
visible,
left,
top,
} = props;
if (!visible || activatedStateID === null) { if (!visible || activatedStateID === null) {
return null; return null;
@ -31,6 +27,7 @@ export default function CanvasContextMenu(props: Props): JSX.Element | null {
<ObjectItemContainer <ObjectItemContainer
key={activatedStateID} key={activatedStateID}
clientID={activatedStateID} clientID={activatedStateID}
objectStates={objectStates}
initialCollapsed initialCollapsed
/> />
</div>, </div>,

@ -15,6 +15,7 @@ interface Props {
statesCollapsedAll: boolean; statesCollapsedAll: boolean;
statesOrdering: StatesOrdering; statesOrdering: StatesOrdering;
sortedStatesID: number[]; sortedStatesID: number[];
objectStates: any[];
switchLockAllShortcut: string; switchLockAllShortcut: string;
switchHiddenAllShortcut: string; switchHiddenAllShortcut: string;
changeStatesOrdering(value: StatesOrdering): void; changeStatesOrdering(value: StatesOrdering): void;
@ -34,6 +35,7 @@ function ObjectListComponent(props: Props): JSX.Element {
statesCollapsedAll, statesCollapsedAll,
statesOrdering, statesOrdering,
sortedStatesID, sortedStatesID,
objectStates,
switchLockAllShortcut, switchLockAllShortcut,
switchHiddenAllShortcut, switchHiddenAllShortcut,
changeStatesOrdering, changeStatesOrdering,
@ -63,13 +65,16 @@ function ObjectListComponent(props: Props): JSX.Element {
showAllStates={showAllStates} showAllStates={showAllStates}
/> />
<div className='cvat-objects-sidebar-states-list'> <div className='cvat-objects-sidebar-states-list'>
{ sortedStatesID.map((id: number): JSX.Element => ( {sortedStatesID.map(
<ObjectItemContainer (id: number): JSX.Element => (
key={id} <ObjectItemContainer
clientID={id} objectStates={objectStates}
initialCollapsed={statesCollapsedAll} key={id}
/> clientID={id}
))} initialCollapsed={statesCollapsedAll}
/>
),
)}
</div> </div>
</div> </div>
); );

@ -11,6 +11,7 @@ import CanvasContextMenuComponent from 'components/annotation-page/standard-work
interface StateToProps { interface StateToProps {
activatedStateID: number | null; activatedStateID: number | null;
objectStates: any[];
visible: boolean; visible: boolean;
top: number; top: number;
left: number; left: number;
@ -21,17 +22,9 @@ interface StateToProps {
function mapStateToProps(state: CombinedState): StateToProps { function mapStateToProps(state: CombinedState): StateToProps {
const { const {
annotation: { annotation: {
annotations: { annotations: { activatedStateID, collapsed, states: objectStates },
activatedStateID,
collapsed,
},
canvas: { canvas: {
contextMenu: { contextMenu: { visible, top, left, type },
visible,
top,
left,
type,
},
}, },
}, },
} = state; } = state;
@ -39,6 +32,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
return { return {
activatedStateID, activatedStateID,
collapsed: activatedStateID !== null ? collapsed[activatedStateID] : undefined, collapsed: activatedStateID !== null ? collapsed[activatedStateID] : undefined,
objectStates,
visible, visible,
left, left,
top, top,
@ -76,8 +70,7 @@ class CanvasContextMenuContainer extends React.PureComponent<Props, State> {
} }
static getDerivedStateFromProps(props: Props, state: State): State | null { static getDerivedStateFromProps(props: Props, state: State): State | null {
if (props.left === state.latestLeft if (props.left === state.latestLeft && props.top === state.latestTop) {
&& props.top === state.latestTop) {
return null; return null;
} }
@ -100,9 +93,13 @@ class CanvasContextMenuContainer extends React.PureComponent<Props, State> {
const [element] = window.document.getElementsByClassName('cvat-canvas-context-menu'); const [element] = window.document.getElementsByClassName('cvat-canvas-context-menu');
if (collapsed !== prevProps.collapsed && element) { if (collapsed !== prevProps.collapsed && element) {
element.addEventListener('transitionend', () => { element.addEventListener(
this.updatePositionIfOutOfScreen(); 'transitionend',
}, { once: true }); () => {
this.updatePositionIfOutOfScreen();
},
{ once: true },
);
} else if (element) { } else if (element) {
this.updatePositionIfOutOfScreen(); this.updatePositionIfOutOfScreen();
} }
@ -145,15 +142,9 @@ class CanvasContextMenuContainer extends React.PureComponent<Props, State> {
}; };
private updatePositionIfOutOfScreen(): void { private updatePositionIfOutOfScreen(): void {
const { const { top, left } = this.state;
top,
left,
} = this.state;
const { const { innerWidth, innerHeight } = window;
innerWidth,
innerHeight,
} = window;
const [element] = window.document.getElementsByClassName('cvat-canvas-context-menu'); const [element] = window.document.getElementsByClassName('cvat-canvas-context-menu');
if (element) { if (element) {
@ -170,24 +161,17 @@ class CanvasContextMenuContainer extends React.PureComponent<Props, State> {
} }
public render(): JSX.Element { public render(): JSX.Element {
const { const { left, top } = this.state;
left, const { visible, activatedStateID, objectStates, type } = this.props;
top,
} = this.state;
const {
visible,
activatedStateID,
type,
} = this.props;
return ( return (
<> <>
{ type === ContextMenuType.CANVAS_SHAPE && ( {type === ContextMenuType.CANVAS_SHAPE && (
<CanvasContextMenuComponent <CanvasContextMenuComponent
left={left} left={left}
top={top} top={top}
visible={visible} visible={visible}
objectStates={objectStates}
activatedStateID={activatedStateID} activatedStateID={activatedStateID}
/> />
)} )}
@ -196,6 +180,4 @@ class CanvasContextMenuContainer extends React.PureComponent<Props, State> {
} }
} }
export default connect( export default connect(mapStateToProps)(CanvasContextMenuContainer);
mapStateToProps,
)(CanvasContextMenuContainer);

@ -7,12 +7,7 @@ import copy from 'copy-to-clipboard';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { LogType } from 'cvat-logger'; import { LogType } from 'cvat-logger';
import { import { ActiveControl, CombinedState, ColorBy, ShapeType } from 'reducers/interfaces';
ActiveControl,
CombinedState,
ColorBy,
ShapeType,
} from 'reducers/interfaces';
import { import {
collapseObjectItems, collapseObjectItems,
updateAnnotationsAsync, updateAnnotationsAsync,
@ -31,6 +26,7 @@ import { shift } from 'utils/math';
interface OwnProps { interface OwnProps {
clientID: number; clientID: number;
objectStates: any[];
initialCollapsed: boolean; initialCollapsed: boolean;
} }
@ -66,46 +62,30 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
const { const {
annotation: { annotation: {
annotations: { annotations: {
states,
collapsed: statesCollapsed, collapsed: statesCollapsed,
activatedStateID, activatedStateID,
zLayer: { zLayer: { min: minZLayer, max: maxZLayer },
min: minZLayer,
max: maxZLayer,
},
},
job: {
attributes: jobAttributes,
instance: jobInstance,
labels,
}, },
job: { attributes: jobAttributes, instance: jobInstance, labels },
player: { player: {
frame: { frame: { number: frameNumber },
number: frameNumber,
},
},
canvas: {
ready,
activeControl,
}, },
canvas: { ready, activeControl },
aiToolsRef, aiToolsRef,
}, },
settings: { settings: {
shapes: { shapes: { colorBy },
colorBy,
},
},
shortcuts: {
normalizedKeyMap,
}, },
shortcuts: { normalizedKeyMap },
} = state; } = state;
const { objectStates: states, initialCollapsed, clientID } = own;
const stateIDs = states.map((_state: any): number => _state.clientID); const stateIDs = states.map((_state: any): number => _state.clientID);
const index = stateIDs.indexOf(own.clientID); const index = stateIDs.indexOf(clientID);
try { try {
const collapsedState = typeof (statesCollapsed[own.clientID]) === 'undefined' const collapsedState =
? own.initialCollapsed : statesCollapsed[own.clientID]; typeof statesCollapsed[clientID] === 'undefined' ? initialCollapsed : statesCollapsed[clientID];
return { return {
objectState: states[index], objectState: states[index],
@ -117,7 +97,7 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
colorBy, colorBy,
jobInstance, jobInstance,
frameNumber, frameNumber,
activated: activatedStateID === own.clientID, activated: activatedStateID === clientID,
minZLayer, minZLayer,
maxZLayer, maxZLayer,
normalizedKeyMap, normalizedKeyMap,
@ -133,7 +113,9 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
clientID: own.clientID, clientID: own.clientID,
stateIDs, stateIDs,
}; };
throw new Error(`${exception.toString()} in mapStateToProps of ObjectItemContainer. Data are ${JSON.stringify(dataObject)}`); throw new Error(
`${exception.toString()} in mapStateToProps of ObjectItemContainer. Data are ${JSON.stringify(dataObject)}`,
);
} }
} }
@ -180,25 +162,15 @@ class ObjectItemContainer extends React.PureComponent<Props> {
}; };
private remove = (): void => { private remove = (): void => {
const { const { objectState, removeObject, jobInstance } = this.props;
objectState,
removeObject,
jobInstance,
} = this.props;
removeObject(jobInstance, objectState); removeObject(jobInstance, objectState);
}; };
private createURL = (): void => { private createURL = (): void => {
const { const { objectState, frameNumber } = this.props;
objectState,
frameNumber,
} = this.props;
const { const { origin, pathname } = window.location;
origin,
pathname,
} = window.location;
const search = `frame=${frameNumber}&type=${objectState.objectType}&serverID=${objectState.serverID}`; const search = `frame=${frameNumber}&type=${objectState.objectType}&serverID=${objectState.serverID}`;
const url = `${origin}${pathname}?${search}`; const url = `${origin}${pathname}?${search}`;
@ -219,12 +191,12 @@ class ObjectItemContainer extends React.PureComponent<Props> {
} }
return acc; return acc;
}, [], },
[],
); );
if (objectState.shapeType === ShapeType.POLYGON) { if (objectState.shapeType === ShapeType.POLYGON) {
objectState.points = reducedPoints.slice(0, 1) objectState.points = reducedPoints.slice(0, 1).concat(reducedPoints.reverse().slice(0, -1)).flat();
.concat(reducedPoints.reverse().slice(0, -1)).flat();
updateState(objectState); updateState(objectState);
} else if (objectState.shapeType === ShapeType.POLYLINE) { } else if (objectState.shapeType === ShapeType.POLYLINE) {
objectState.points = reducedPoints.reverse().flat(); objectState.points = reducedPoints.reverse().flat();
@ -233,32 +205,21 @@ class ObjectItemContainer extends React.PureComponent<Props> {
}; };
private toBackground = (): void => { private toBackground = (): void => {
const { const { objectState, minZLayer } = this.props;
objectState,
minZLayer,
} = this.props;
objectState.zOrder = minZLayer - 1; objectState.zOrder = minZLayer - 1;
this.commit(); this.commit();
}; };
private toForeground = (): void => { private toForeground = (): void => {
const { const { objectState, maxZLayer } = this.props;
objectState,
maxZLayer,
} = this.props;
objectState.zOrder = maxZLayer + 1; objectState.zOrder = maxZLayer + 1;
this.commit(); this.commit();
}; };
private activate = (): void => { private activate = (): void => {
const { const { activateObject, objectState, ready, activeControl } = this.props;
activateObject,
objectState,
ready,
activeControl,
} = this.props;
if (ready && activeControl === ActiveControl.CURSOR) { if (ready && activeControl === ActiveControl.CURSOR) {
activateObject(objectState.clientID); activateObject(objectState.clientID);
@ -266,11 +227,7 @@ class ObjectItemContainer extends React.PureComponent<Props> {
}; };
private collapse = (): void => { private collapse = (): void => {
const { const { collapseOrExpand, objectState, collapsed } = this.props;
collapseOrExpand,
objectState,
collapsed,
} = this.props;
collapseOrExpand([objectState], !collapsed); collapseOrExpand([objectState], !collapsed);
}; };
@ -283,11 +240,7 @@ class ObjectItemContainer extends React.PureComponent<Props> {
}; };
private changeColor = (color: string): void => { private changeColor = (color: string): void => {
const { const { objectState, colorBy, changeGroupColor } = this.props;
objectState,
colorBy,
changeGroupColor,
} = this.props;
if (colorBy === ColorBy.INSTANCE) { if (colorBy === ColorBy.INSTANCE) {
objectState.color = color; objectState.color = color;
@ -298,10 +251,7 @@ class ObjectItemContainer extends React.PureComponent<Props> {
}; };
private changeLabel = (labelID: string): void => { private changeLabel = (labelID: string): void => {
const { const { objectState, labels } = this.props;
objectState,
labels,
} = this.props;
const [label] = labels.filter((_label: any): boolean => _label.id === +labelID); const [label] = labels.filter((_label: any): boolean => _label.id === +labelID);
objectState.label = label; objectState.label = label;
@ -330,8 +280,7 @@ class ObjectItemContainer extends React.PureComponent<Props> {
this.resetCuboidPerspective(false); this.resetCuboidPerspective(false);
objectState.points = shift(objectState.points, objectState.points = shift(objectState.points, cuboidOrientationIsLeft(objectState.points) ? 4 : -4);
cuboidOrientationIsLeft(objectState.points) ? 4 : -4);
this.commit(); this.commit();
}; };
@ -369,24 +318,13 @@ class ObjectItemContainer extends React.PureComponent<Props> {
}; };
private commit(): void { private commit(): void {
const { const { objectState, updateState } = this.props;
objectState,
updateState,
} = this.props;
updateState(objectState); updateState(objectState);
} }
public render(): JSX.Element { public render(): JSX.Element {
const { const { objectState, collapsed, labels, attributes, activated, colorBy, normalizedKeyMap } = this.props;
objectState,
collapsed,
labels,
attributes,
activated,
colorBy,
normalizedKeyMap,
} = this.props;
let stateColor = ''; let stateColor = '';
if (colorBy === ColorBy.INSTANCE) { if (colorBy === ColorBy.INSTANCE) {

@ -17,12 +17,7 @@ import {
changeGroupColorAsync, changeGroupColorAsync,
} from 'actions/annotation-actions'; } from 'actions/annotation-actions';
import { Canvas } from 'cvat-canvas-wrapper'; import { Canvas } from 'cvat-canvas-wrapper';
import { import { CombinedState, StatesOrdering, ObjectType, ColorBy } from 'reducers/interfaces';
CombinedState,
StatesOrdering,
ObjectType,
ColorBy,
} from 'reducers/interfaces';
interface StateToProps { interface StateToProps {
jobInstance: any; jobInstance: any;
@ -65,34 +60,20 @@ function mapStateToProps(state: CombinedState): StateToProps {
collapsed, collapsed,
collapsedAll, collapsedAll,
activatedStateID, activatedStateID,
zLayer: { zLayer: { min: minZLayer, max: maxZLayer },
min: minZLayer,
max: maxZLayer,
},
},
job: {
instance: jobInstance,
}, },
job: { instance: jobInstance },
player: { player: {
frame: { frame: { number: frameNumber },
number: frameNumber,
},
},
canvas: {
instance: canvasInstance,
}, },
canvas: { instance: canvasInstance },
tabContentHeight: listHeight, tabContentHeight: listHeight,
colors, colors,
}, },
settings: { settings: {
shapes: { shapes: { colorBy },
colorBy,
},
},
shortcuts: {
keyMap,
normalizedKeyMap,
}, },
shortcuts: { keyMap, normalizedKeyMap },
} = state; } = state;
let statesHidden = true; let statesHidden = true;
@ -232,10 +213,7 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
}; };
private lockAllStates(locked: boolean): void { private lockAllStates(locked: boolean): void {
const { const { objectStates, updateAnnotations } = this.props;
objectStates,
updateAnnotations,
} = this.props;
for (const objectState of objectStates) { for (const objectState of objectStates) {
objectState.lock = locked; objectState.lock = locked;
} }
@ -244,10 +222,7 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
} }
private hideAllStates(hidden: boolean): void { private hideAllStates(hidden: boolean): void {
const { const { objectStates, updateAnnotations } = this.props;
objectStates,
updateAnnotations,
} = this.props;
for (const objectState of objectStates) { for (const objectState of objectStates) {
objectState.hidden = hidden; objectState.hidden = hidden;
} }
@ -256,10 +231,7 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
} }
private collapseAllStates(collapsed: boolean): void { private collapseAllStates(collapsed: boolean): void {
const { const { objectStates, collapseStates } = this.props;
objectStates,
collapseStates,
} = this.props;
collapseStates(objectStates, collapsed); collapseStates(objectStates, collapsed);
} }
@ -269,7 +241,6 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
statesHidden, statesHidden,
statesLocked, statesLocked,
activatedStateID, activatedStateID,
objectStates,
jobInstance, jobInstance,
updateAnnotations, updateAnnotations,
changeGroupColor, changeGroupColor,
@ -285,10 +256,7 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
colors, colors,
colorBy, colorBy,
} = this.props; } = this.props;
const { const { objectStates, sortedStatesID, statesOrdering } = this.state;
sortedStatesID,
statesOrdering,
} = this.state;
const subKeyMap = { const subKeyMap = {
SWITCH_ALL_LOCK: keyMap.SWITCH_ALL_LOCK, SWITCH_ALL_LOCK: keyMap.SWITCH_ALL_LOCK,
@ -316,10 +284,9 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
const activatedStated = (): any | null => { const activatedStated = (): any | null => {
if (activatedStateID !== null) { if (activatedStateID !== null) {
const [state] = objectStates const [state] = objectStates.filter(
.filter((objectState: any): boolean => ( (objectState: any): boolean => objectState.clientID === activatedStateID,
objectState.clientID === activatedStateID );
));
return state || null; return state || null;
} }
@ -434,8 +401,7 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
preventDefault(event); preventDefault(event);
const state = activatedStated(); const state = activatedStated();
if (state && state.objectType === ObjectType.TRACK) { if (state && state.objectType === ObjectType.TRACK) {
const frame = typeof (state.keyframes.next) === 'number' const frame = typeof state.keyframes.next === 'number' ? state.keyframes.next : null;
? state.keyframes.next : null;
if (frame !== null && canvasInstance.isAbleToChangeFrame()) { if (frame !== null && canvasInstance.isAbleToChangeFrame()) {
changeFrame(frame); changeFrame(frame);
} }
@ -445,8 +411,7 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
preventDefault(event); preventDefault(event);
const state = activatedStated(); const state = activatedStated();
if (state && state.objectType === ObjectType.TRACK) { if (state && state.objectType === ObjectType.TRACK) {
const frame = typeof (state.keyframes.prev) === 'number' const frame = typeof state.keyframes.prev === 'number' ? state.keyframes.prev : null;
? state.keyframes.prev : null;
if (frame !== null && canvasInstance.isAbleToChangeFrame()) { if (frame !== null && canvasInstance.isAbleToChangeFrame()) {
changeFrame(frame); changeFrame(frame);
} }
@ -461,6 +426,7 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
{...this.props} {...this.props}
statesOrdering={statesOrdering} statesOrdering={statesOrdering}
sortedStatesID={sortedStatesID} sortedStatesID={sortedStatesID}
objectStates={objectStates}
switchHiddenAllShortcut={normalizedKeyMap.SWITCH_ALL_HIDDEN} switchHiddenAllShortcut={normalizedKeyMap.SWITCH_ALL_HIDDEN}
switchLockAllShortcut={normalizedKeyMap.SWITCH_ALL_LOCK} switchLockAllShortcut={normalizedKeyMap.SWITCH_ALL_LOCK}
changeStatesOrdering={this.onChangeStatesOrdering} changeStatesOrdering={this.onChangeStatesOrdering}
@ -476,7 +442,4 @@ class ObjectsListContainer extends React.PureComponent<Props, State> {
} }
} }
export default connect( export default connect(mapStateToProps, mapDispatchToProps)(ObjectsListContainer);
mapStateToProps,
mapDispatchToProps,
)(ObjectsListContainer);

Loading…
Cancel
Save