CVAT UI: batch of fixes (#2084)

* fixed object item border color

* Fixed default collapsed prop in object item

* Added color picker for shape outline

* Added CHANGELOG, increased npm version

* Fixed object details collapsing

* Fixed default collapsed
main
Dmitry Kalinin 6 years ago committed by GitHub
parent 510191f64b
commit 0e37d70b1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Ability to configure email verification for new users (<https://github.com/opencv/cvat/pull/1929>) - Ability to configure email verification for new users (<https://github.com/opencv/cvat/pull/1929>)
- Link to django admin page from UI (<https://github.com/opencv/cvat/pull/2068>) - Link to django admin page from UI (<https://github.com/opencv/cvat/pull/2068>)
- Notification message when users use wrong browser (<https://github.com/opencv/cvat/pull/2070>) - Notification message when users use wrong browser (<https://github.com/opencv/cvat/pull/2070>)
- Annotation in process outline color wheel (<https://github.com/opencv/cvat/pull/2084>)
### Changed ### Changed
- Shape coordinates are rounded to 2 digits in dumped annotations (<https://github.com/opencv/cvat/pull/1970>) - Shape coordinates are rounded to 2 digits in dumped annotations (<https://github.com/opencv/cvat/pull/1970>)
@ -44,6 +45,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed a case in which exported masks could have wrong color order (<https://github.com/opencv/cvat/issues/2032>) - Fixed a case in which exported masks could have wrong color order (<https://github.com/opencv/cvat/issues/2032>)
- Fixed error with creating task with labels with the same name (<https://github.com/opencv/cvat/pull/2031>) - Fixed error with creating task with labels with the same name (<https://github.com/opencv/cvat/pull/2031>)
- Django RQ dashboard view (<https://github.com/opencv/cvat/pull/2069>) - Django RQ dashboard view (<https://github.com/opencv/cvat/pull/2069>)
- Object's details menu settings (<https://github.com/opencv/cvat/pull/2084>)
-
## [1.1.0-beta] - 2020-08-03 ## [1.1.0-beta] - 2020-08-03
### Added ### Added

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

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

@ -94,8 +94,8 @@ export const registerAsync = (
dispatch(authActions.register()); dispatch(authActions.register());
try { try {
const user = await cvat.server.register(username, firstName, lastName, email, password1, password2, const user = await cvat.server.register(username, firstName, lastName, email, password1,
confirmations); password2, confirmations);
dispatch(authActions.registerSuccess(user)); dispatch(authActions.registerSuccess(user));
} catch (error) { } catch (error) {

@ -17,7 +17,7 @@ export enum SettingsActionTypes {
CHANGE_SHAPES_OPACITY = 'CHANGE_SHAPES_OPACITY', CHANGE_SHAPES_OPACITY = 'CHANGE_SHAPES_OPACITY',
CHANGE_SELECTED_SHAPES_OPACITY = 'CHANGE_SELECTED_SHAPES_OPACITY', CHANGE_SELECTED_SHAPES_OPACITY = 'CHANGE_SELECTED_SHAPES_OPACITY',
CHANGE_SHAPES_COLOR_BY = 'CHANGE_SHAPES_COLOR_BY', CHANGE_SHAPES_COLOR_BY = 'CHANGE_SHAPES_COLOR_BY',
CHANGE_SHAPES_BLACK_BORDERS = 'CHANGE_SHAPES_BLACK_BORDERS', CHANGE_SHAPES_OUTLINED_BORDERS = 'CHANGE_SHAPES_OUTLINED_BORDERS',
CHANGE_SHAPES_SHOW_PROJECTIONS = 'CHANGE_SHAPES_SHOW_PROJECTIONS', CHANGE_SHAPES_SHOW_PROJECTIONS = 'CHANGE_SHAPES_SHOW_PROJECTIONS',
CHANGE_SHOW_UNLABELED_REGIONS = 'CHANGE_SHOW_UNLABELED_REGIONS', CHANGE_SHOW_UNLABELED_REGIONS = 'CHANGE_SHOW_UNLABELED_REGIONS',
CHANGE_FRAME_STEP = 'CHANGE_FRAME_STEP', CHANGE_FRAME_STEP = 'CHANGE_FRAME_STEP',
@ -63,11 +63,12 @@ export function changeShapesColorBy(colorBy: ColorBy): AnyAction {
}; };
} }
export function changeShapesBlackBorders(blackBorders: boolean): AnyAction { export function changeShapesOutlinedBorders(outlined: boolean, color: string): AnyAction {
return { return {
type: SettingsActionTypes.CHANGE_SHAPES_BLACK_BORDERS, type: SettingsActionTypes.CHANGE_SHAPES_OUTLINED_BORDERS,
payload: { payload: {
blackBorders, outlined,
color,
}, },
}; };
} }

@ -22,7 +22,7 @@ $info-icon-color: #0074d9;
$objects-bar-tabs-color: #bebebe; $objects-bar-tabs-color: #bebebe;
$objects-bar-icons-color: #242424; // #6e6e6e $objects-bar-icons-color: #242424; // #6e6e6e
$active-label-background-color: #d8ecff; $active-label-background-color: #d8ecff;
$object-item-border-color: #000; $object-item-border-color: rgba(0, 0, 0, 0.7);
$slider-color: #1890ff; $slider-color: #1890ff;
$monospaced-fonts-stack: Consolas, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace; $monospaced-fonts-stack: Consolas, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace;

@ -11,6 +11,8 @@ import Slider, { SliderValue } from 'antd/lib/slider';
import Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox'; import Checkbox, { CheckboxChangeEvent } from 'antd/lib/checkbox';
import Collapse from 'antd/lib/collapse'; import Collapse from 'antd/lib/collapse';
import ColorPicker from 'components/annotation-page/standard-workspace/objects-side-bar/color-picker';
import { ColorizeIcon } from 'icons';
import { ColorBy, CombinedState } from 'reducers/interfaces'; import { ColorBy, CombinedState } from 'reducers/interfaces';
import { import {
collapseAppearance as collapseAppearanceAction, collapseAppearance as collapseAppearanceAction,
@ -20,17 +22,19 @@ import {
changeShapesColorBy as changeShapesColorByAction, changeShapesColorBy as changeShapesColorByAction,
changeShapesOpacity as changeShapesOpacityAction, changeShapesOpacity as changeShapesOpacityAction,
changeSelectedShapesOpacity as changeSelectedShapesOpacityAction, changeSelectedShapesOpacity as changeSelectedShapesOpacityAction,
changeShapesBlackBorders as changeShapesBlackBordersAction, changeShapesOutlinedBorders as changeShapesOutlinedBordersAction,
changeShowBitmap as changeShowBitmapAction, changeShowBitmap as changeShowBitmapAction,
changeShowProjections as changeShowProjectionsAction, changeShowProjections as changeShowProjectionsAction,
} from 'actions/settings-actions'; } from 'actions/settings-actions';
import Button from 'antd/lib/button';
interface StateToProps { interface StateToProps {
appearanceCollapsed: boolean; appearanceCollapsed: boolean;
colorBy: ColorBy; colorBy: ColorBy;
opacity: number; opacity: number;
selectedOpacity: number; selectedOpacity: number;
blackBorders: boolean; outlined: boolean;
outlineColor: string;
showBitmap: boolean; showBitmap: boolean;
showProjections: boolean; showProjections: boolean;
} }
@ -40,7 +44,7 @@ interface DispatchToProps {
changeShapesColorBy(event: RadioChangeEvent): void; changeShapesColorBy(event: RadioChangeEvent): void;
changeShapesOpacity(event: SliderValue): void; changeShapesOpacity(event: SliderValue): void;
changeSelectedShapesOpacity(event: SliderValue): void; changeSelectedShapesOpacity(event: SliderValue): void;
changeShapesBlackBorders(event: CheckboxChangeEvent): void; changeShapesOutlinedBorders(outlined: boolean, color: string): void;
changeShowBitmap(event: CheckboxChangeEvent): void; changeShowBitmap(event: CheckboxChangeEvent): void;
changeShowProjections(event: CheckboxChangeEvent): void; changeShowProjections(event: CheckboxChangeEvent): void;
} }
@ -72,7 +76,8 @@ function mapStateToProps(state: CombinedState): StateToProps {
colorBy, colorBy,
opacity, opacity,
selectedOpacity, selectedOpacity,
blackBorders, outlined,
outlineColor,
showBitmap, showBitmap,
showProjections, showProjections,
}, },
@ -84,7 +89,8 @@ function mapStateToProps(state: CombinedState): StateToProps {
colorBy, colorBy,
opacity, opacity,
selectedOpacity, selectedOpacity,
blackBorders, outlined,
outlineColor,
showBitmap, showBitmap,
showProjections, showProjections,
}; };
@ -119,8 +125,8 @@ function mapDispatchToProps(dispatch: Dispatch<AnyAction>): DispatchToProps {
changeSelectedShapesOpacity(value: SliderValue): void { changeSelectedShapesOpacity(value: SliderValue): void {
dispatch(changeSelectedShapesOpacityAction(value as number)); dispatch(changeSelectedShapesOpacityAction(value as number));
}, },
changeShapesBlackBorders(event: CheckboxChangeEvent): void { changeShapesOutlinedBorders(outlined: boolean, color: string): void {
dispatch(changeShapesBlackBordersAction(event.target.checked)); dispatch(changeShapesOutlinedBordersAction(outlined, color));
}, },
changeShowBitmap(event: CheckboxChangeEvent): void { changeShowBitmap(event: CheckboxChangeEvent): void {
dispatch(changeShowBitmapAction(event.target.checked)); dispatch(changeShowBitmapAction(event.target.checked));
@ -139,14 +145,15 @@ function AppearanceBlock(props: Props): JSX.Element {
colorBy, colorBy,
opacity, opacity,
selectedOpacity, selectedOpacity,
blackBorders, outlined,
outlineColor,
showBitmap, showBitmap,
showProjections, showProjections,
collapseAppearance, collapseAppearance,
changeShapesColorBy, changeShapesColorBy,
changeShapesOpacity, changeShapesOpacity,
changeSelectedShapesOpacity, changeSelectedShapesOpacity,
changeShapesBlackBorders, changeShapesOutlinedBorders,
changeShowBitmap, changeShowBitmap,
changeShowProjections, changeShowProjections,
} = props; } = props;
@ -185,10 +192,22 @@ function AppearanceBlock(props: Props): JSX.Element {
max={100} max={100}
/> />
<Checkbox <Checkbox
onChange={changeShapesBlackBorders} onChange={(event: CheckboxChangeEvent) => {
checked={blackBorders} changeShapesOutlinedBorders(event.target.checked, outlineColor);
}}
checked={outlined}
> >
Black borders Outlined borders
<ColorPicker
onChange={(color) => changeShapesOutlinedBorders(outlined, color)}
value={outlineColor}
placement='top'
resetVisible={false}
>
<Button type='link' shape='circle'>
<ColorizeIcon />
</Button>
</ColorPicker>
</Checkbox> </Checkbox>
<Checkbox <Checkbox
onChange={changeShowBitmap} onChange={changeShowBitmap}

@ -28,7 +28,11 @@ export default function CanvasContextMenu(props: Props): JSX.Element | null {
return ReactDOM.createPortal( return ReactDOM.createPortal(
<div className='cvat-canvas-context-menu' style={{ top, left }}> <div className='cvat-canvas-context-menu' style={{ top, left }}>
<ObjectItemContainer key={activatedStateID} clientID={activatedStateID} /> <ObjectItemContainer
key={activatedStateID}
clientID={activatedStateID}
initialCollapsed
/>
</div>, </div>,
window.document.body, window.document.body,
); );

@ -42,7 +42,8 @@ interface Props {
opacity: number; opacity: number;
colorBy: ColorBy; colorBy: ColorBy;
selectedOpacity: number; selectedOpacity: number;
blackBorders: boolean; outlined: boolean;
outlineColor: string;
showBitmap: boolean; showBitmap: boolean;
showProjections: boolean; showProjections: boolean;
grid: boolean; grid: boolean;
@ -125,7 +126,8 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
opacity, opacity,
colorBy, colorBy,
selectedOpacity, selectedOpacity,
blackBorders, outlined,
outlineColor,
showBitmap, showBitmap,
frameData, frameData,
frameAngle, frameAngle,
@ -230,7 +232,8 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
}, { once: true }); }, { once: true });
} }
if (prevProps.opacity !== opacity || prevProps.blackBorders !== blackBorders if (prevProps.opacity !== opacity || prevProps.outlined !== outlined
|| prevProps.outlineColor !== outlineColor
|| prevProps.selectedOpacity !== selectedOpacity || prevProps.colorBy !== colorBy || prevProps.selectedOpacity !== selectedOpacity || prevProps.colorBy !== colorBy
) { ) {
this.updateShapesView(); this.updateShapesView();
@ -602,7 +605,8 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
annotations, annotations,
opacity, opacity,
colorBy, colorBy,
blackBorders, outlined,
outlineColor,
} = this.props; } = this.props;
for (const state of annotations) { for (const state of annotations) {
@ -625,7 +629,7 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
} }
(shapeView as any).instance.fill({ color: shapeColor, opacity: opacity / 100 }); (shapeView as any).instance.fill({ color: shapeColor, opacity: opacity / 100 });
(shapeView as any).instance.stroke({ color: blackBorders ? 'black' : shapeColor }); (shapeView as any).instance.stroke({ color: outlined ? outlineColor : shapeColor });
} }
} }
} }

@ -12,7 +12,7 @@ interface Props {
listHeight: number; listHeight: number;
statesHidden: boolean; statesHidden: boolean;
statesLocked: boolean; statesLocked: boolean;
statesCollapsed: boolean; statesCollapsedAll: boolean;
statesOrdering: StatesOrdering; statesOrdering: StatesOrdering;
sortedStatesID: number[]; sortedStatesID: number[];
switchLockAllShortcut: string; switchLockAllShortcut: string;
@ -31,7 +31,7 @@ function ObjectListComponent(props: Props): JSX.Element {
listHeight, listHeight,
statesHidden, statesHidden,
statesLocked, statesLocked,
statesCollapsed, statesCollapsedAll,
statesOrdering, statesOrdering,
sortedStatesID, sortedStatesID,
switchLockAllShortcut, switchLockAllShortcut,
@ -50,7 +50,7 @@ function ObjectListComponent(props: Props): JSX.Element {
<ObjectListHeader <ObjectListHeader
statesHidden={statesHidden} statesHidden={statesHidden}
statesLocked={statesLocked} statesLocked={statesLocked}
statesCollapsed={statesCollapsed} statesCollapsed={statesCollapsedAll}
statesOrdering={statesOrdering} statesOrdering={statesOrdering}
switchLockAllShortcut={switchLockAllShortcut} switchLockAllShortcut={switchLockAllShortcut}
switchHiddenAllShortcut={switchHiddenAllShortcut} switchHiddenAllShortcut={switchHiddenAllShortcut}
@ -64,7 +64,11 @@ function ObjectListComponent(props: Props): JSX.Element {
/> />
<div className='cvat-objects-sidebar-states-list'> <div className='cvat-objects-sidebar-states-list'>
{ sortedStatesID.map((id: number): JSX.Element => ( { sortedStatesID.map((id: number): JSX.Element => (
<ObjectItemContainer key={id} clientID={id} /> <ObjectItemContainer
key={id}
clientID={id}
initialCollapsed={statesCollapsedAll}
/>
))} ))}
</div> </div>
</div> </div>

@ -64,7 +64,8 @@ interface StateToProps {
opacity: number; opacity: number;
colorBy: ColorBy; colorBy: ColorBy;
selectedOpacity: number; selectedOpacity: number;
blackBorders: boolean; outlined: boolean;
outlineColor: string;
showBitmap: boolean; showBitmap: boolean;
showProjections: boolean; showProjections: boolean;
grid: boolean; grid: boolean;
@ -179,7 +180,8 @@ function mapStateToProps(state: CombinedState): StateToProps {
opacity, opacity,
colorBy, colorBy,
selectedOpacity, selectedOpacity,
blackBorders, outlined,
outlineColor,
showBitmap, showBitmap,
showProjections, showProjections,
}, },
@ -204,7 +206,8 @@ function mapStateToProps(state: CombinedState): StateToProps {
opacity, opacity,
colorBy, colorBy,
selectedOpacity, selectedOpacity,
blackBorders, outlined,
outlineColor,
showBitmap, showBitmap,
showProjections, showProjections,
grid, grid,

@ -30,6 +30,7 @@ import { shift } from 'utils/math';
interface OwnProps { interface OwnProps {
clientID: number; clientID: number;
initialCollapsed: boolean;
} }
interface StateToProps { interface StateToProps {
@ -101,7 +102,7 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
.indexOf(own.clientID); .indexOf(own.clientID);
const collapsedState = typeof (statesCollapsed[own.clientID]) === 'undefined' const collapsedState = typeof (statesCollapsed[own.clientID]) === 'undefined'
? true : statesCollapsed[own.clientID]; ? own.initialCollapsed : statesCollapsed[own.clientID];
return { return {
objectState: states[index], objectState: states[index],

@ -30,7 +30,8 @@ interface StateToProps {
listHeight: number; listHeight: number;
statesHidden: boolean; statesHidden: boolean;
statesLocked: boolean; statesLocked: boolean;
statesCollapsed: boolean; statesCollapsedAll: boolean;
collapsedStates: Record<number, boolean>;
objectStates: any[]; objectStates: any[];
annotationsFilters: string[]; annotationsFilters: string[];
colors: string[]; colors: string[];
@ -62,6 +63,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
filters: annotationsFilters, filters: annotationsFilters,
filtersHistory: annotationsFiltersHistory, filtersHistory: annotationsFiltersHistory,
collapsed, collapsed,
collapsedAll,
activatedStateID, activatedStateID,
zLayer: { zLayer: {
min: minZLayer, min: minZLayer,
@ -95,25 +97,23 @@ function mapStateToProps(state: CombinedState): StateToProps {
let statesHidden = true; let statesHidden = true;
let statesLocked = true; let statesLocked = true;
let statesCollapsed = true;
objectStates.forEach((objectState: any) => { objectStates.forEach((objectState: any) => {
const { clientID, lock } = objectState; const { lock } = objectState;
if (!lock) { if (!lock) {
if (objectState.objectType !== ObjectType.TAG) { if (objectState.objectType !== ObjectType.TAG) {
statesHidden = statesHidden && objectState.hidden; statesHidden = statesHidden && objectState.hidden;
} }
statesLocked = statesLocked && objectState.lock; statesLocked = statesLocked && objectState.lock;
} }
const stateCollapsed = clientID in collapsed ? collapsed[clientID] : true;
statesCollapsed = statesCollapsed && stateCollapsed;
}); });
return { return {
listHeight, listHeight,
statesHidden, statesHidden,
statesLocked, statesLocked,
statesCollapsed, statesCollapsedAll: collapsedAll,
collapsedStates: collapsed,
objectStates, objectStates,
frameNumber, frameNumber,
jobInstance, jobInstance,

@ -67,6 +67,7 @@ const defaultState: AnnotationState = {
statuses: [], statuses: [],
}, },
collapsed: {}, collapsed: {},
collapsedAll: true,
states: [], states: [],
filters: [], filters: [],
filtersHistory: JSON.parse( filtersHistory: JSON.parse(
@ -352,6 +353,7 @@ export default (state = defaultState, action: AnyAction): AnnotationState => {
} = action.payload; } = action.payload;
const updatedCollapsedStates = { ...state.annotations.collapsed }; const updatedCollapsedStates = { ...state.annotations.collapsed };
const totalStatesCount = state.annotations.states.length;
for (const objectState of states) { for (const objectState of states) {
updatedCollapsedStates[objectState.clientID] = collapsed; updatedCollapsedStates[objectState.clientID] = collapsed;
} }
@ -361,6 +363,8 @@ export default (state = defaultState, action: AnyAction): AnnotationState => {
annotations: { annotations: {
...state.annotations, ...state.annotations,
collapsed: updatedCollapsedStates, collapsed: updatedCollapsedStates,
collapsedAll: states.length === totalStatesCount
? collapsed : state.annotations.collapsedAll,
}, },
}; };
} }

@ -361,6 +361,7 @@ export interface AnnotationState {
activatedStateID: number | null; activatedStateID: number | null;
activatedAttributeID: number | null; activatedAttributeID: number | null;
collapsed: Record<number, boolean>; collapsed: Record<number, boolean>;
collapsedAll: boolean;
states: any[]; states: any[];
filters: string[]; filters: string[];
filtersHistory: string[]; filtersHistory: string[];
@ -452,7 +453,8 @@ export interface ShapesSettingsState {
colorBy: ColorBy; colorBy: ColorBy;
opacity: number; opacity: number;
selectedOpacity: number; selectedOpacity: number;
blackBorders: boolean; outlined: boolean;
outlineColor: string;
showBitmap: boolean; showBitmap: boolean;
showProjections: boolean; showProjections: boolean;
} }

@ -21,7 +21,8 @@ const defaultState: SettingsState = {
colorBy: ColorBy.LABEL, colorBy: ColorBy.LABEL,
opacity: 3, opacity: 3,
selectedOpacity: 30, selectedOpacity: 30,
blackBorders: false, outlined: false,
outlineColor: '#000000',
showBitmap: false, showBitmap: false,
showProjections: false, showProjections: false,
}, },
@ -124,12 +125,13 @@ export default (state = defaultState, action: AnyAction): SettingsState => {
}, },
}; };
} }
case SettingsActionTypes.CHANGE_SHAPES_BLACK_BORDERS: { case SettingsActionTypes.CHANGE_SHAPES_OUTLINED_BORDERS: {
return { return {
...state, ...state,
shapes: { shapes: {
...state.shapes, ...state.shapes,
blackBorders: action.payload.blackBorders, outlined: action.payload.outlined,
outlineColor: action.payload.color,
}, },
}; };
} }

Loading…
Cancel
Save