Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Click instead of hover to open dropdown menus #7431

Merged
merged 41 commits into from
Feb 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
10ce8df
Click instead of hover to open dropdown menus
bsekachev Feb 2, 2024
395a999
Annotation menu & user menu
bsekachev Feb 2, 2024
7cf4c01
Updated for all menus
bsekachev Feb 2, 2024
e3f0115
Updated tests
bsekachev Feb 2, 2024
e2eed71
Updated more dropdowns
bsekachev Feb 2, 2024
23c85fc
Updated license headers
bsekachev Feb 2, 2024
990561a
Added changelog fragment
bsekachev Feb 2, 2024
05f63e3
Little refactoring
bsekachev Feb 2, 2024
a786ba3
Reduced code duplication in tests
bsekachev Feb 2, 2024
c9b712d
Close annotation object menu on click
bsekachev Feb 2, 2024
5d50cea
added extra menu closings
bsekachev Feb 2, 2024
f1ca20d
Refactored classname
bsekachev Feb 2, 2024
7a647af
Fixed typos
bsekachev Feb 3, 2024
48dd476
Fixed command
bsekachev Feb 5, 2024
fc0ffdf
Fixed more tests
bsekachev Feb 5, 2024
40238b6
Fixed more tests
bsekachev Feb 5, 2024
76e4a13
Fixed two tests
bsekachev Feb 5, 2024
54d5a6c
Fixed test
bsekachev Feb 5, 2024
55b6e24
Merge branch 'develop' into bs/update_dropdown_triggers
bsekachev Feb 5, 2024
c56ba1a
Common component for dropdown menu
bsekachev Feb 5, 2024
97030e3
Refactoring changing color
bsekachev Feb 5, 2024
567ca33
Merge branch 'develop' into bs/update_dropdown_triggers
bsekachev Feb 5, 2024
7c341e8
Updated version
bsekachev Feb 5, 2024
ab07846
Fixed command
bsekachev Feb 6, 2024
bb4b51f
Fixed tests
bsekachev Feb 6, 2024
96ce207
Tried to stabilize test
bsekachev Feb 6, 2024
d5218e0
Tried to stabilize test
bsekachev Feb 6, 2024
74fd9d9
Unstable test
bsekachev Feb 6, 2024
671b6d1
Fixed test
bsekachev Feb 6, 2024
4c1e77a
Fixed test
bsekachev Feb 6, 2024
a30611c
Merge branch 'develop' into bs/update_dropdown_triggers
bsekachev Feb 6, 2024
94fbfbf
Updated test
bsekachev Feb 6, 2024
6c7a506
Reduced number of requests
bsekachev Feb 6, 2024
41494ff
Updated workflow
bsekachev Feb 6, 2024
c9fb312
Removed
bsekachev Feb 6, 2024
d532166
Removed
bsekachev Feb 6, 2024
a57f04d
Updated
bsekachev Feb 6, 2024
6a15229
Fixed test
bsekachev Feb 6, 2024
61d7757
Aborted extra files
bsekachev Feb 7, 2024
840c46e
Merge branch 'develop' into bs/update_dropdown_triggers
bsekachev Feb 9, 2024
304876f
Merge branch 'develop' into bs/update_dropdown_triggers
bsekachev Feb 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Changed

- Now menus in the web interface are triggered by click, not by hover as before
(<https://github.com/opencv/cvat/pull/7431>)
2 changes: 1 addition & 1 deletion cvat-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cvat-ui",
"version": "1.61.4",
"version": "1.62.0",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {
Expand Down
20 changes: 12 additions & 8 deletions cvat-ui/src/components/actions-menu/actions-menu.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import './styles.scss';
import React, { useCallback } from 'react';
import Menu from 'antd/lib/menu';
import Modal from 'antd/lib/modal';
import { LoadingOutlined } from '@ant-design/icons';
// eslint-disable-next-line import/no-extraneous-dependencies
import { MenuInfo } from 'rc-menu/lib/interface';
import { DimensionType } from 'cvat-core-wrapper';
import { DimensionType, CVATCore } from 'cvat-core-wrapper';
import Menu, { MenuInfo } from 'components/dropdown-menu';
import { usePlugins } from 'utils/hooks';
import { CombinedState } from 'reducers';

type AnnotationFormats = Awaited<ReturnType<CVATCore['server']['formats']>>;

interface Props {
taskID: number;
projectID: number | null;
taskMode: string;
bugTracker: string;
loaders: any[];
dumpers: any[];
loaders: AnnotationFormats['loaders'];
dumpers: AnnotationFormats['dumpers'];
inferenceIsActive: boolean;
taskDimension: DimensionType;
backupIsActive: boolean;
Expand Down Expand Up @@ -137,7 +137,11 @@ function ActionsMenuComponent(props: Props): JSX.Element {
);

return (
<Menu selectable={false} className='cvat-actions-menu' onClick={onClickMenuWrapper}>
<Menu
selectable={false}
className='cvat-actions-menu'
onClick={onClickMenuWrapper}
>
{ menuItems.sort((menuItem1, menuItem2) => menuItem1[1] - menuItem2[1])
.map((menuItem) => menuItem[0]) }
</Menu>
Expand Down
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -1118,7 +1118,12 @@ class CanvasWrapperComponent extends React.PureComponent<Props> {

<BrushTools />

<Dropdown trigger={['click']} placement='topCenter' overlay={<ImageSetupsContent />}>
<Dropdown
destroyPopupOnHide
trigger={['click']}
placement='topCenter'
overlay={<ImageSetupsContent />}
>
<UpOutlined className='cvat-canvas-image-setups-trigger' />
</Dropdown>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022-2023 CVAT.ai Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand All @@ -9,7 +9,6 @@ import { SmallDashOutlined } from '@ant-design/icons';
import Popover from 'antd/lib/popover';
import React, { useEffect, useRef, useState } from 'react';
import ReactDOM from 'react-dom';
import { ConnectedComponent } from 'react-redux';
import withVisibilityHandling from './handle-popover-visibility';

const extraControlsContentClassName = 'cvat-extra-controls-control-content';
Expand All @@ -19,13 +18,14 @@ const CustomPopover = withVisibilityHandling(Popover, 'extra-controls');
export function ExtraControlsControl(): JSX.Element {
const [hasChildren, setHasChildren] = useState(false);
const [initialized, setInitialized] = useState(false);
const [visible, setVisible] = useState(true);

useEffect(() => {
if (!initialized) {
setInitialized(true);
}

window.document.body.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
setVisible(false);
}, []);

onUpdateChildren = () => {
Expand All @@ -37,7 +37,8 @@ export function ExtraControlsControl(): JSX.Element {

return (
<CustomPopover
defaultVisible // we must render it at least one between using
visible={visible}
onVisibleChange={setVisible}
trigger={initialized ? 'hover' : 'click'} // trigger='hover' allows to close the popover by body click
placement='right'
overlayStyle={{ display: initialized ? '' : 'none' }}
Expand All @@ -52,7 +53,7 @@ export function ExtraControlsControl(): JSX.Element {
}

export default function ControlVisibilityObserver<P = {}>(
ControlComponent: React.FunctionComponent<P> | ConnectedComponent<any, any>,
ControlComponent: React.FunctionComponent<P>,
): React.FunctionComponent<P> {
let visibilityHeightThreshold = 0; // minimum value of height when element can be pushed to main panel

Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2022-2023 CVAT.ai Corporation
// Copyright (C) 2022-2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import React from 'react';
import Layout from 'antd/lib/layout';

import {
ActiveControl, ObjectType, Rotation, ShapeType, CombinedState,
ActiveControl, Rotation, CombinedState,
} from 'reducers';
import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react';
import { Canvas, CanvasMode } from 'cvat-canvas-wrapper';
import { LabelType } from 'cvat-core-wrapper';

import ControlVisibilityObserver, { ExtraControlsControl } from './control-visibility-observer';
import RotateControl, { Props as RotateControlProps } from './rotate-control';
Expand Down Expand Up @@ -105,14 +106,14 @@ export default function ControlsSideBarComponent(props: Props): JSX.Element {
let tagControlVisible = withUnspecifiedType;
const skeletonControlVisible = labels.some((label: Label) => label.type === 'skeleton');
labels.forEach((label: Label) => {
rectangleControlVisible = rectangleControlVisible || label.type === ShapeType.RECTANGLE;
polygonControlVisible = polygonControlVisible || label.type === ShapeType.POLYGON;
polylineControlVisible = polylineControlVisible || label.type === ShapeType.POLYLINE;
pointsControlVisible = pointsControlVisible || label.type === ShapeType.POINTS;
ellipseControlVisible = ellipseControlVisible || label.type === ShapeType.ELLIPSE;
cuboidControlVisible = cuboidControlVisible || label.type === ShapeType.CUBOID;
maskControlVisible = maskControlVisible || label.type === ShapeType.MASK;
tagControlVisible = tagControlVisible || label.type === ObjectType.TAG;
rectangleControlVisible = rectangleControlVisible || label.type === LabelType.RECTANGLE;
polygonControlVisible = polygonControlVisible || label.type === LabelType.POLYGON;
polylineControlVisible = polylineControlVisible || label.type === LabelType.POLYLINE;
pointsControlVisible = pointsControlVisible || label.type === LabelType.POINTS;
ellipseControlVisible = ellipseControlVisible || label.type === LabelType.ELLIPSE;
cuboidControlVisible = cuboidControlVisible || label.type === LabelType.CUBOID;
maskControlVisible = maskControlVisible || label.type === LabelType.MASK;
tagControlVisible = tagControlVisible || label.type === LabelType.TAG;
});

const preventDefault = (event: KeyboardEvent | undefined): void => {
Expand Down
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -150,13 +150,11 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
</Row>
) : null}
<Row justify='space-around'>
<Col span={12}>
<Col span={24}>
<CVATTooltip title={`Press ${repeatShapeShortcut} to draw again`}>
<Button className={`cvat-draw-${shapeType}-shape-button`} onClick={onDrawShape}>Shape</Button>
</CVATTooltip>
</Col>
{shapeType !== ShapeType.MASK && (
<Col span={12}>
{shapeType !== ShapeType.MASK && (
<CVATTooltip title={`Press ${repeatShapeShortcut} to draw again`}>
<Button
className={`cvat-draw-${shapeType}-track-button`}
Expand All @@ -165,8 +163,8 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
Track
</Button>
</CVATTooltip>
</Col>
)}
)}
</Col>
</Row>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import React, { useState } from 'react';
import React from 'react';
import Popover, { PopoverProps } from 'antd/lib/popover';

interface OwnProps {
Expand All @@ -12,7 +13,6 @@ interface OwnProps {

export default function withVisibilityHandling(WrappedComponent: typeof Popover, popoverType: string) {
return function (props: OwnProps & PopoverProps): JSX.Element {
const [visible, setVisible] = useState<boolean>(false);
const { overlayClassName, onVisibleChange, ...rest } = props;
const overlayClassNames = typeof overlayClassName === 'string' ? overlayClassName.split(/\s+/) : [];
const popoverClassName = `cvat-${popoverType}-popover`;
Expand All @@ -27,7 +27,7 @@ export default function withVisibilityHandling(WrappedComponent: typeof Popover,
animationDuration: '0s',
animationDelay: '0s',
}}
trigger={visible ? ['click'] : ['click', 'hover']}
trigger={['click']}
overlayClassName={overlayClassNames.join(' ').trim()}
onVisibleChange={(_visible: boolean) => {
if (_visible) {
Expand All @@ -38,7 +38,6 @@ export default function withVisibilityHandling(WrappedComponent: typeof Popover,
(element as HTMLElement).style.opacity = '';
}
}
setVisible(_visible);
if (onVisibleChange) onVisibleChange(_visible);
}}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

Expand Down Expand Up @@ -42,7 +43,6 @@ function RotateControl(props: Props): JSX.Element {
</CVATTooltip>
</>
)}
trigger='hover'
>
<Icon className='cvat-rotate-canvas-control' component={RotateIcon} />
</CustomPopover>
Expand Down
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -1100,6 +1100,7 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
</Col>
<Col span={2} className='cvat-interactors-tips-icon-container'>
<Dropdown
destroyPopupOnHide
overlay={(
<ToolsTooltips
name={activeInteractor?.name}
Expand Down
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -13,6 +13,7 @@ import { ObjectType, ShapeType, ColorBy } from 'reducers';
import CVATTooltip from 'components/common/cvat-tooltip';
import LabelSelector from 'components/label-selector/label-selector';
import ItemMenu from './object-item-menu';
import ColorPicker from './color-picker';

interface Props {
jobInstance: any;
Expand Down Expand Up @@ -87,21 +88,8 @@ function ItemTopComponent(props: Props): JSX.Element {
jobInstance,
} = props;

const [menuVisible, setMenuVisible] = useState(false);
const [colorPickerVisible, setColorPickerVisible] = useState(false);

const changeMenuVisible = (visible: boolean): void => {
if (!visible && colorPickerVisible) return;
setMenuVisible(visible);
};

const changeColorPickerVisible = (visible: boolean): void => {
if (!visible) {
setMenuVisible(false);
}
setColorPickerVisible(visible);
};

return (
<Row align='middle'>
<Col span={10}>
Expand Down Expand Up @@ -129,12 +117,24 @@ function ItemTopComponent(props: Props): JSX.Element {
</CVATTooltip>
</Col>
{ !isGroundTruth && (
<Col span={2}>
colorPickerVisible ? (
<ColorPicker
visible
value={color}
onVisibleChange={setColorPickerVisible}
onChange={(_color: string) => {
changeColor(_color);
}}
>
<Col span={2}>
<MoreOutlined />
</Col>
</ColorPicker>
) : (
<Dropdown
visible={menuVisible}
onVisibleChange={changeMenuVisible}
destroyPopupOnHide
placement='bottomLeft'
trigger={menuVisible ? ['click'] : ['click', 'hover']}
trigger={['click']}
overlay={ItemMenu({
jobInstance,
readonly,
Expand Down Expand Up @@ -162,14 +162,16 @@ function ItemTopComponent(props: Props): JSX.Element {
toBackground,
toForeground,
resetCuboidPerspective,
changeColorPickerVisible,
setColorPickerVisible,
edit,
slice,
})}
>
<MoreOutlined />
<Col span={2}>
<MoreOutlined />
</Col>
</Dropdown>
</Col>
)
)}
</Row>
);
Expand Down
Loading
Loading