diff --git a/CHANGELOG.md b/CHANGELOG.md index e6b333bcc73..68e1d138685 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 () +- Non-informative lock icon () +- Sidebar in AAM has no hide/show button () +- Task/Job buttons has no "Open in new tab" option () +- Delete point context menu option has no shortcut hint () ### Security - diff --git a/cvat-canvas/src/scss/canvas.scss b/cvat-canvas/src/scss/canvas.scss index 152c91d13ad..b7d6c56d12c 100644 --- a/cvat-canvas/src/scss/canvas.scss +++ b/cvat-canvas/src/scss/canvas.scss @@ -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; } diff --git a/cvat-canvas/src/typescript/canvasView.ts b/cvat-canvas/src/typescript/canvasView.ts index 63acbefa6c8..71f6b05d900 100644 --- a/cvat-canvas/src/typescript/canvasView.ts +++ b/cvat-canvas/src/typescript/canvasView.ts @@ -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( diff --git a/cvat-canvas/src/typescript/svg.patch.ts b/cvat-canvas/src/typescript/svg.patch.ts index b16019dd7b7..d17356c35af 100644 --- a/cvat-canvas/src/typescript/svg.patch.ts +++ b/cvat-canvas/src/typescript/svg.patch.ts @@ -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}, diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index a799df3272d..3e2c48f40b3 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.0.1", + "version": "1.0.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 9a038b6496d..f9b49018c56 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -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": { diff --git a/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/attribute-annotation-sidebar.tsx b/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/attribute-annotation-sidebar.tsx index 9cf839c1925..1c24f961f16 100644 --- a/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/attribute-annotation-sidebar.tsx +++ b/cvat-ui/src/components/annotation-page/attribute-annotation-workspace/attribute-annotation-sidebar/attribute-annotation-sidebar.tsx @@ -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 ( + {/* eslint-disable-next-line */} + setSidebarCollapsed(!sidebarCollapsed)} + > + {sidebarCollapsed ? + : } + - + diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-point-context-menu.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-point-context-menu.tsx index 122e832a0ac..bd534747e77 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/canvas-point-context-menu.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/canvas-point-context-menu.tsx @@ -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(
- + + +
, window.document.body, ); diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx index 2a43e042ff5..1a5b54cbc38 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/object-item.tsx @@ -338,7 +338,7 @@ function ItemButtonsComponent(props: ItemButtonsComponentProps): JSX.Element { { locked - ? + ? : } @@ -388,7 +388,7 @@ function ItemButtonsComponent(props: ItemButtonsComponentProps): JSX.Element { { locked - ? + ? : } @@ -405,7 +405,7 @@ function ItemButtonsComponent(props: ItemButtonsComponentProps): JSX.Element { { locked - ? + ? : } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-list-header.tsx b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-list-header.tsx index 07337fc7d2e..2aebd92cb0b 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-list-header.tsx +++ b/cvat-ui/src/components/annotation-page/standard-workspace/objects-side-bar/objects-list-header.tsx @@ -97,7 +97,7 @@ function ObjectListHeader(props: Props): JSX.Element { { statesLocked - ? + ? : } diff --git a/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss b/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss index 96c105880f1..83474bad308 100644 --- a/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss +++ b/cvat-ui/src/components/annotation-page/standard-workspace/styles.scss @@ -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; } diff --git a/cvat-ui/src/components/annotation-page/top-bar/annotation-menu.tsx b/cvat-ui/src/components/annotation-page/top-bar/annotation-menu.tsx index 7039abff7fc..51a460ea378 100644 --- a/cvat-ui/src/components/annotation-page/top-bar/annotation-menu.tsx +++ b/cvat-ui/src/components/annotation-page/top-bar/annotation-menu.tsx @@ -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 - Open the task + e.preventDefault()}> + Open the task + { installedReID && } diff --git a/cvat-ui/src/components/task-page/job-list.tsx b/cvat-ui/src/components/task-page/job-list.tsx index 195c3046215..76d0a48d928 100644 --- a/cvat-ui/src/components/task-page/job-list.tsx +++ b/cvat-ui/src/components/task-page/job-list.tsx @@ -46,9 +46,11 @@ function JobListComponent(props: Props & RouteComponentProps): JSX.Element {
diff --git a/cvat-ui/src/components/tasks-page/task-item.tsx b/cvat-ui/src/components/tasks-page/task-item.tsx index aea0c0ec427..36f1e04ecbf 100644 --- a/cvat-ui/src/components/tasks-page/task-item.tsx +++ b/cvat-ui/src/components/tasks-page/task-item.tsx @@ -184,7 +184,11 @@ class TaskItemComponent extends React.PureComponent history.push(`/tasks/${id}`)} + href={`/tasks/${id}`} + onClick={(e: React.MouseEvent): void => { + e.preventDefault(); + history.push(`/tasks/${id}`) + }} > Open diff --git a/cvat-ui/src/containers/annotation-page/top-bar/annotation-menu.tsx b/cvat-ui/src/containers/annotation-page/top-bar/annotation-menu.tsx index 20648a2b023..b6633885c1b 100644 --- a/cvat-ui/src/containers/annotation-page/top-bar/annotation-menu.tsx +++ b/cvat-ui/src/containers/annotation-page/top-bar/annotation-menu.tsx @@ -157,6 +157,7 @@ function AnnotationMenuContainer(props: Props): JSX.Element { exportActivities={exportActivities} installedReID={installedReID} onClickMenu={onClickMenu} + taskID={jobInstance.task.id} /> ); }