React UI: batch of fixes (#1525)

main
Dmitry Kalinin 6 years ago committed by GitHub
parent 3caae98b5b
commit 2e8117561c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -33,6 +33,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Exporting frame stepped task (https://github.com/opencv/cvat/issues/1294, https://github.com/opencv/cvat/issues/1334)
- Fixed broken command line interface for `cvat` export format in Datumaro (https://github.com/opencv/cvat/issues/1494)
- Updated Rest API document, Swagger document serving instruction issue (https://github.com/opencv/cvat/issues/1495)
- Fixed cuboid occluded view (<https://github.com/opencv/cvat/pull/1500>)
- Non-informative lock icon (<https://github.com/opencv/cvat/pull/1434>)
- Sidebar in AAM has no hide/show button (<https://github.com/opencv/cvat/pull/1420>)
- Task/Job buttons has no "Open in new tab" option (<https://github.com/opencv/cvat/pull/1419>)
- Delete point context menu option has no shortcut hint (<https://github.com/opencv/cvat/pull/1416>)
### Security
-

@ -103,6 +103,10 @@ polyline.cvat_canvas_shape_splitting {
stroke-dasharray: 5;
}
.cvat_canvas_shape .svg_select_points, .cvat_canvas_shape .cvat_canvas_cuboid_projections {
stroke-dasharray: none;
}
.cvat_canvas_autoborder_point {
opacity: 0.55;
}

@ -427,6 +427,9 @@ export class CanvasViewImpl implements CanvasView, Listener {
private selectize(value: boolean, shape: SVG.Element): void {
const self = this;
const { offset } = this.controller.geometry;
const translate = (points: number[]): number[] => points
.map((coord: number): number => coord - offset);
function dblClickHandler(e: MouseEvent): void {
const pointID = Array.prototype.indexOf
@ -437,10 +440,22 @@ export class CanvasViewImpl implements CanvasView, Listener {
.filter((_state: any): boolean => (
_state.clientID === self.activeElement.clientID
));
if (['cuboid', 'rectangle'].includes(state.shapeType)) {
if (state.shapeType === 'rectangle') {
e.preventDefault();
return;
}
if (state.shapeType === 'cuboid') {
if (e.shiftKey) {
const points = translate(pointsToArray((e.target as any)
.parentElement.parentElement.instance.attr('points')));
self.onEditDone(
state,
points,
)
e.preventDefault();
return;
}
}
if (e.ctrlKey) {
const { points } = state;
self.onEditDone(

@ -263,10 +263,10 @@ function getTopDown(edgeIndex: EdgeIndex): number[] {
this.rbProj = this.line(this.updateProjectionLine(this.cuboidModel.rb.getEquation(),
this.cuboidModel.rb.points[1], this.cuboidModel.vpr));
this.ftProj.stroke({ color: '#C0C0C0' });
this.fbProj.stroke({ color: '#C0C0C0' });
this.rtProj.stroke({ color: '#C0C0C0' });
this.rbProj.stroke({ color: '#C0C0C0' });
this.ftProj.stroke({ color: '#C0C0C0' }).addClass('cvat_canvas_cuboid_projections');
this.fbProj.stroke({ color: '#C0C0C0' }).addClass('cvat_canvas_cuboid_projections');
this.rtProj.stroke({ color: '#C0C0C0' }).addClass('cvat_canvas_cuboid_projections');
this.rbProj.stroke({ color: '#C0C0C0' }).addClass('cvat_canvas_cuboid_projections');
},
setupEdges() {
@ -281,7 +281,7 @@ function getTopDown(edgeIndex: EdgeIndex): number[] {
this.rightBotEdge = this.line(this.cuboidModel.rb.points);
},
setupGrabPoints(circleType) {
setupGrabPoints(circleType: Function | string) {
const viewModel = this.cuboidModel;
const circle = typeof circleType === 'function' ? circleType : this.circle;
@ -372,7 +372,7 @@ function getTopDown(edgeIndex: EdgeIndex): number[] {
}
if (value === false) {
this.getGrabPoints().forEach((point) => {point && point.remove()});
this.getGrabPoints().forEach((point: SVG.Element) => {point && point.remove()});
} else {
this.setupGrabPoints(this.face.remember('_selectHandler').drawPoint.bind(
{nested: this, options: this.face.remember('_selectHandler').options}
@ -380,21 +380,29 @@ function getTopDown(edgeIndex: EdgeIndex): number[] {
// setup proper classes for selection points for proper cursor
Array.from(this.face.remember('_selectHandler').nested.node.children)
.forEach((point: SVG.Circle, i: number) => {
.forEach((point: SVG.LinkedHTMLElement, i: number) => {
point.classList.add(`svg_select_points_${['lt', 'lb', 'rb', 'rt'][i]}`)
});
if (this.cuboidModel.orientation === Orientation.LEFT) {
Array.from(this.dorsalRightEdge.remember('_selectHandler').nested.node.children)
.forEach((point: SVG.Circle, i: number) => {
.forEach((point: SVG.LinkedHTMLElement, i: number) => {
point.classList.add(`svg_select_points_${['t', 'b'][i]}`);
point.ondblclick = this.resetPerspective.bind(this);
point.ondblclick = (e: MouseEvent) => {
if (e.shiftKey) {
this.resetPerspective()
}
};
});
} else {
Array.from(this.dorsalLeftEdge.remember('_selectHandler').nested.node.children)
.forEach((point: SVG.Circle, i: number) => {
.forEach((point: SVG.LinkedHTMLElement, i: number) => {
point.classList.add(`svg_select_points_${['t', 'b'][i]}`);
point.ondblclick = this.resetPerspective.bind(this);
point.ondblclick = (e: MouseEvent) => {
if (e.shiftKey) {
this.resetPerspective()
}
};
});
}
@ -584,7 +592,7 @@ function getTopDown(edgeIndex: EdgeIndex): number[] {
setupDorsalEdge.call(this, this.dorsalLeftEdge, this.cuboidModel.orientation);
}
function horizontalEdgeControl(updatingFace, midX, midY) {
function horizontalEdgeControl(updatingFace: any, midX: number, midY: number) {
const leftPoints = this.updatedEdge(
this.cuboidModel.fl.points[0],
{x: midX, y: midY},

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

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

@ -12,6 +12,7 @@ import { SelectValue } from 'antd/lib/select';
import { CheckboxChangeEvent } from 'antd/lib/checkbox';
import { Row, Col } from 'antd/lib/grid';
import Text from 'antd/lib/typography/Text';
import Icon from 'antd/lib/icon';
import { LogType } from 'cvat-logger';
import {
@ -106,6 +107,8 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
}, {}),
);
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
const [activeObjectState] = activatedStateID === null
? [null] : states.filter((objectState: any): boolean => (
objectState.clientID === activatedStateID
@ -175,6 +178,7 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
reverseArrow: true,
collapsible: true,
trigger: null,
collapsed: sidebarCollapsed,
};
const subKeyMap = {
@ -218,8 +222,18 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
if (activeObjectState) {
return (
<Layout.Sider {...siderProps}>
{/* eslint-disable-next-line */}
<span
className={`cvat-objects-sidebar-sider
ant-layout-sider-zero-width-trigger
ant-layout-sider-zero-width-trigger-left`}
onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
>
{sidebarCollapsed ? <Icon type='menu-fold' title='Show' />
: <Icon type='menu-unfold' title='Hide' />}
</span>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges />
<Row>
<Row className='cvat-objects-sidebar-filter-input'>
<Col>
<AnnotationsFiltersInput />
</Col>

@ -5,6 +5,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import Button from 'antd/lib/button';
import Tooltip from 'antd/lib/tooltip';
interface Props {
activatedStateID: number | null;
@ -29,9 +30,11 @@ export default function CanvasPointContextMenu(props: Props): JSX.Element | null
return ReactDOM.createPortal(
<div className='cvat-canvas-point-context-menu' style={{ top, left }}>
<Button type='link' icon='delete' onClick={onPointDelete}>
Delete point
</Button>
<Tooltip title='Delete point [Ctrl + dblclick]'>
<Button type='link' icon='delete' onClick={onPointDelete}>
Delete point
</Button>
</Tooltip>
</div>,
window.document.body,
);

@ -338,7 +338,7 @@ function ItemButtonsComponent(props: ItemButtonsComponentProps): JSX.Element {
<Col>
<Tooltip title={`Switch lock property ${switchLockShortcut}`}>
{ locked
? <Icon type='lock' onClick={unlock} />
? <Icon type='lock' onClick={unlock} theme='filled'/>
: <Icon type='unlock' onClick={lock} />}
</Tooltip>
</Col>
@ -388,7 +388,7 @@ function ItemButtonsComponent(props: ItemButtonsComponentProps): JSX.Element {
<Col>
<Tooltip title={`Switch lock property ${switchLockShortcut}`}>
{ locked
? <Icon type='lock' onClick={unlock} />
? <Icon type='lock' onClick={unlock} theme='filled' />
: <Icon type='unlock' onClick={lock} />}
</Tooltip>
</Col>
@ -405,7 +405,7 @@ function ItemButtonsComponent(props: ItemButtonsComponentProps): JSX.Element {
<Col>
<Tooltip title={`Switch lock property ${switchLockShortcut}`}>
{ locked
? <Icon type='lock' onClick={unlock} />
? <Icon type='lock' onClick={unlock} theme='filled'/>
: <Icon type='unlock' onClick={lock} />}
</Tooltip>
</Col>

@ -97,7 +97,7 @@ function ObjectListHeader(props: Props): JSX.Element {
<Col span={2}>
<Tooltip title={`Switch lock property for all ${switchLockAllShortcut}`}>
{ statesLocked
? <Icon type='lock' onClick={unlockAllStates} />
? <Icon type='lock' onClick={unlockAllStates} theme='filled' />
: <Icon type='unlock' onClick={lockAllStates} />}
</Tooltip>
</Col>

@ -12,12 +12,18 @@
background-color: $background-color-1;
}
.cvat-objects-sidebar-filter-input {
width: calc(100% - 35px);
}
.cvat-objects-sidebar-sider {
top: 0px;
right: 0px;
left: auto;
background-color: $background-color-2;
border-left: 1px solid $border-color-1;
border-bottom: 1px solid $border-color-1;
border-radius: 4px 0 0 4px;
z-index: 2;
}

@ -19,6 +19,7 @@ interface Props {
dumpActivities: string[] | null;
exportActivities: string[] | null;
installedReID: boolean;
taskID: number;
onClickMenu(params: ClickParam, file?: File): void;
}
@ -40,6 +41,7 @@ export default function AnnotationMenuComponent(props: Props): JSX.Element {
dumpActivities,
exportActivities,
installedReID,
taskID,
} = props;
let latestParams: ClickParam | null = null;
@ -119,7 +121,9 @@ export default function AnnotationMenuComponent(props: Props): JSX.Element {
Remove annotations
</Menu.Item>
<Menu.Item key={Actions.OPEN_TASK}>
Open the task
<a href={`/tasks/${taskID}`} onClick={(e: React.MouseEvent) => e.preventDefault()}>
Open the task
</a>
</Menu.Item>
{ installedReID && <ReIDPlugin /> }
</Menu>

@ -46,9 +46,11 @@ function JobListComponent(props: Props & RouteComponentProps): JSX.Element {
<div>
<Button
type='link'
onClick={(): void => {
onClick={(e: React.MouseEvent): void => {
e.preventDefault();
push(`/tasks/${taskId}/jobs/${id}`);
}}
href={`/tasks/${taskId}/jobs/${id}`}
>
{`Job #${id}`}
</Button>

@ -184,7 +184,11 @@ class TaskItemComponent extends React.PureComponent<TaskItemProps & RouteCompone
type='primary'
size='large'
ghost
onClick={(): void => history.push(`/tasks/${id}`)}
href={`/tasks/${id}`}
onClick={(e: React.MouseEvent): void => {
e.preventDefault();
history.push(`/tasks/${id}`)
}}
>
Open
</Button>

@ -157,6 +157,7 @@ function AnnotationMenuContainer(props: Props): JSX.Element {
exportActivities={exportActivities}
installedReID={installedReID}
onClickMenu={onClickMenu}
taskID={jobInstance.task.id}
/>
);
}

Loading…
Cancel
Save