Minor fixes

main
Boris Sekachev 5 years ago
parent a60fd76f0d
commit 6883ee3155

@ -12964,7 +12964,6 @@
"requires": { "requires": {
"axios": "^0.21.0", "axios": "^0.21.0",
"browser-or-node": "^1.2.1", "browser-or-node": "^1.2.1",
"cvat-data": "file:../cvat-data",
"detect-browser": "^5.2.0", "detect-browser": "^5.2.0",
"error-stack-parser": "^2.0.2", "error-stack-parser": "^2.0.2",
"form-data": "^2.5.0", "form-data": "^2.5.0",

@ -8,7 +8,6 @@ import Menu from 'antd/lib/menu';
import Modal from 'antd/lib/modal'; import Modal from 'antd/lib/modal';
// eslint-disable-next-line import/no-extraneous-dependencies // eslint-disable-next-line import/no-extraneous-dependencies
import { MenuInfo } from 'rc-menu/lib/interface'; import { MenuInfo } from 'rc-menu/lib/interface';
import DumpSubmenu from './dump-submenu'; import DumpSubmenu from './dump-submenu';
import LoadSubmenu from './load-submenu'; import LoadSubmenu from './load-submenu';
import ExportSubmenu from './export-submenu'; import ExportSubmenu from './export-submenu';

@ -17,7 +17,9 @@ interface Props {
} }
export default function LoadSubmenu(props: Props): JSX.Element { export default function LoadSubmenu(props: Props): JSX.Element {
const { menuKey, loaders, loadActivity, onFileUpload } = props; const {
menuKey, loaders, loadActivity, onFileUpload,
} = props;
return ( return (
<Menu.SubMenu key={menuKey} title='Upload annotations'> <Menu.SubMenu key={menuKey} title='Upload annotations'>

@ -20,7 +20,7 @@
.cvat-menu-load-submenu-item, .cvat-menu-load-submenu-item,
.cvat-menu-dump-submenu-item, .cvat-menu-dump-submenu-item,
.cvat-menu-export-submenu-item { .cvat-menu-export-submenu-item {
> i { > span[role='img'] {
color: $info-icon-color; color: $info-icon-color;
} }

@ -52,7 +52,7 @@ interface DispatchToProps {
export function computeHeight(): number { export function computeHeight(): number {
const [sidebar] = window.document.getElementsByClassName('cvat-objects-sidebar'); const [sidebar] = window.document.getElementsByClassName('cvat-objects-sidebar');
const [appearance] = window.document.getElementsByClassName('cvat-objects-appearance-collapse'); const [appearance] = window.document.getElementsByClassName('cvat-objects-appearance-collapse');
const [tabs] = Array.from(window.document.querySelectorAll('.cvat-objects-sidebar-tabs > .ant-tabs-card-bar')); const [tabs] = Array.from(window.document.querySelectorAll('.cvat-objects-sidebar-tabs > .ant-tabs-nav'));
if (sidebar && appearance && tabs) { if (sidebar && appearance && tabs) {
const maxHeight = sidebar ? sidebar.clientHeight : 0; const maxHeight = sidebar ? sidebar.clientHeight : 0;

@ -291,15 +291,11 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
ant-layout-sider-zero-width-trigger-left`} ant-layout-sider-zero-width-trigger-left`}
onClick={collapse} onClick={collapse}
> >
{sidebarCollapsed ? ( {sidebarCollapsed ? <MenuFoldOutlined title='Show' /> : <MenuUnfoldOutlined title='Hide' />}
<MenuFoldOutlined title='Show' />
) : (
<MenuUnfoldOutlined title='Hide' />
)}
</span> </span>
<GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges /> <GlobalHotKeys keyMap={subKeyMap} handlers={handlers} allowChanges />
<Row className='cvat-objects-sidebar-filter-input'> <Row>
<Col> <Col span={24}>
<AnnotationsFiltersInput /> <AnnotationsFiltersInput />
</Col> </Col>
</Row> </Row>
@ -323,6 +319,7 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
}} }}
/> />
<ObjectButtonsContainer <ObjectButtonsContainer
readonly={false}
clientID={activeObjectState.clientID} clientID={activeObjectState.clientID}
outsideDisabled outsideDisabled
hiddenDisabled hiddenDisabled
@ -376,8 +373,8 @@ function AttributeAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.
> >
{sidebarCollapsed ? <MenuFoldOutlined title='Show' /> : <MenuUnfoldOutlined title='Hide' />} {sidebarCollapsed ? <MenuFoldOutlined title='Show' /> : <MenuUnfoldOutlined title='Hide' />}
</span> </span>
<Row className='cvat-objects-sidebar-filter-input'> <Row>
<Col> <Col span={24}>
<AnnotationsFiltersInput /> <AnnotationsFiltersInput />
</Col> </Col>
</Row> </Row>

@ -22,7 +22,9 @@ interface InputElementParameters {
} }
function renderInputElement(parameters: InputElementParameters): JSX.Element { function renderInputElement(parameters: InputElementParameters): JSX.Element {
const { inputType, attrID, clientID, values, currentValue, onChange } = parameters; const {
inputType, attrID, clientID, values, currentValue, onChange,
} = parameters;
const renderCheckbox = (): JSX.Element => ( const renderCheckbox = (): JSX.Element => (
<> <>
@ -246,7 +248,9 @@ interface Props {
} }
function AttributeEditor(props: Props): JSX.Element { function AttributeEditor(props: Props): JSX.Element {
const { attribute, currentValue, onChange, clientID } = props; const {
attribute, currentValue, onChange, clientID,
} = props;
const { inputType, values, id: attrID } = attribute; const { inputType, values, id: attrID } = attribute;
return ( return (

@ -17,7 +17,9 @@ interface Props {
} }
function AttributeSwitcher(props: Props): JSX.Element { function AttributeSwitcher(props: Props): JSX.Element {
const { currentAttribute, currentIndex, attributesCount, nextAttribute, normalizedKeyMap } = props; const {
currentAttribute, currentIndex, attributesCount, nextAttribute, normalizedKeyMap,
} = props;
const title = `${currentAttribute} [${currentIndex + 1}/${attributesCount}]`; const title = `${currentAttribute} [${currentIndex + 1}/${attributesCount}]`;
return ( return (

@ -19,7 +19,9 @@ interface Props {
} }
function ObjectSwitcher(props: Props): JSX.Element { function ObjectSwitcher(props: Props): JSX.Element {
const { currentLabel, clientID, objectsCount, currentIndex, nextObject, normalizedKeyMap } = props; const {
currentLabel, clientID, objectsCount, currentIndex, nextObject, normalizedKeyMap,
} = props;
const title = `${currentLabel} ${clientID} [${currentIndex + 1}/${objectsCount}]`; const title = `${currentLabel} ${clientID} [${currentIndex + 1}/${objectsCount}]`;
return ( return (

@ -27,7 +27,7 @@
overflow: hidden; overflow: hidden;
} }
> button > i { > button > span[role='img'] {
color: $objects-bar-icons-color; color: $objects-bar-icons-color;
} }
} }

@ -43,12 +43,12 @@ export default function RequestReviewModal(): JSX.Element | null {
onOk={submitAnnotations} onOk={submitAnnotations}
okText='Submit' okText='Submit'
> >
<Row type='flex' justify='start'> <Row justify='start'>
<Col> <Col>
<Title level={4}>Assign a user who is responsible for review</Title> <Title level={4}>Assign a user who is responsible for review</Title>
</Col> </Col>
</Row> </Row>
<Row align='middle' type='flex' justify='start'> <Row align='middle' justify='start'>
<Col> <Col>
<Text type='secondary'>Reviewer: </Text> <Text type='secondary'>Reviewer: </Text>
</Col> </Col>
@ -56,7 +56,7 @@ export default function RequestReviewModal(): JSX.Element | null {
<UserSelector value={reviewer} onSelect={setReviewer} /> <UserSelector value={reviewer} onSelect={setReviewer} />
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='start'> <Row justify='start'>
<Text type='secondary'>You might not be able to change the job after this action. Continue?</Text> <Text type='secondary'>You might not be able to change the job after this action. Continue?</Text>
</Row> </Row>
</Modal> </Modal>

@ -5,47 +5,36 @@
import React, { ReactPortal } from 'react'; import React, { ReactPortal } from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import Form, { FormComponentProps } from '@ant-design/compatible/lib/form/Form'; import Form from 'antd/lib/form';
import Input from 'antd/lib/input'; import Input from 'antd/lib/input';
import Button from 'antd/lib/button'; import Button from 'antd/lib/button';
import { Row, Col } from 'antd/lib/grid'; import { Row, Col } from 'antd/lib/grid';
import { reviewActions, finishIssueAsync } from 'actions/review-actions'; import { reviewActions, finishIssueAsync } from 'actions/review-actions';
import { Store } from 'antd/lib/form/interface';
type FormProps = { interface FormProps {
top: number; top: number;
left: number; left: number;
submit(message: string): void; submit(message: string): void;
cancel(): void; cancel(): void;
} & FormComponentProps; }
function MessageForm(props: FormProps): JSX.Element { function MessageForm(props: FormProps): JSX.Element {
const { const {
form: { getFieldDecorator }, top, left, submit, cancel,
form,
top,
left,
submit,
cancel,
} = props; } = props;
function handleSubmit(e: React.FormEvent): void { function handleSubmit(values: Store): void {
e.preventDefault(); submit(values.issue_description);
form.validateFields((error, values): void => {
if (!error) {
submit(values.issue_description);
}
});
} }
return ( return (
<Form className='cvat-create-issue-dialog' style={{ top, left }} onSubmit={handleSubmit}> <Form className='cvat-create-issue-dialog' style={{ top, left }} onFinish={handleSubmit}>
<Form.Item> <Form.Item name='issue_description' rules={[{ required: true, message: 'Please, fill out the field' }]}>
{getFieldDecorator('issue_description', { <Input autoComplete='off' placeholder='Please, describe the issue' />
rules: [{ required: true, message: 'Please, fill out the field' }],
})(<Input autoComplete='off' placeholder='Please, describe the issue' />)}
</Form.Item> </Form.Item>
<Row type='flex' justify='space-between'> <Row justify='space-between'>
<Col> <Col>
<Button onClick={cancel} type='ghost'> <Button onClick={cancel} type='ghost'>
Cancel Cancel
@ -61,8 +50,6 @@ function MessageForm(props: FormProps): JSX.Element {
); );
} }
const WrappedMessageForm = Form.create<FormProps>()(MessageForm);
interface Props { interface Props {
top: number; top: number;
left: number; left: number;
@ -73,7 +60,7 @@ export default function CreateIssueDialog(props: Props): ReactPortal {
const { top, left } = props; const { top, left } = props;
return ReactDOM.createPortal( return ReactDOM.createPortal(
<WrappedMessageForm <MessageForm
top={top} top={top}
left={left} left={left}
submit={(message: string) => { submit={(message: string) => {

@ -88,7 +88,7 @@ export default function IssueDialog(props: Props): JSX.Element {
return ReactDOM.createPortal( return ReactDOM.createPortal(
<div style={{ top, left }} ref={ref} className='cvat-issue-dialog'> <div style={{ top, left }} ref={ref} className='cvat-issue-dialog'>
<Row className='cvat-issue-dialog-header' type='flex' justify='space-between'> <Row className='cvat-issue-dialog-header' justify='space-between'>
<Col> <Col>
<Title level={4}>{id >= 0 ? `Issue #${id}` : 'Issue'}</Title> <Title level={4}>{id >= 0 ? `Issue #${id}` : 'Issue'}</Title>
</Col> </Col>
@ -98,10 +98,10 @@ export default function IssueDialog(props: Props): JSX.Element {
</Tooltip> </Tooltip>
</Col> </Col>
</Row> </Row>
<Row className='cvat-issue-dialog-chat' type='flex' justify='start'> <Row className='cvat-issue-dialog-chat' justify='start'>
<Col style={{ display: 'block' }}>{lines}</Col> <Col style={{ display: 'block' }}>{lines}</Col>
</Row> </Row>
<Row className='cvat-issue-dialog-input' type='flex' justify='start'> <Row className='cvat-issue-dialog-input' justify='start'>
<Col span={24}> <Col span={24}>
<Input <Input
placeholder='Print a comment here..' placeholder='Print a comment here..'
@ -118,7 +118,7 @@ export default function IssueDialog(props: Props): JSX.Element {
/> />
</Col> </Col>
</Row> </Row>
<Row className='cvat-issue-dialog-footer' type='flex' justify='end'> <Row className='cvat-issue-dialog-footer' justify='end'>
<Col> <Col>
{currentText.length ? ( {currentText.length ? (
<Button <Button

@ -86,12 +86,12 @@ export default function SubmitReviewModal(): JSX.Element | null {
okText='Submit' okText='Submit'
width={650} width={650}
> >
<Row type='flex' justify='start'> <Row justify='start'>
<Col> <Col>
<Title level={4}>Submitting your review</Title> <Title level={4}>Submitting your review</Title>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='start'> <Row justify='start'>
<Col span={12}> <Col span={12}>
<Description title='Review summary' layout='horizontal' column={1} size='small' bordered> <Description title='Review summary' layout='horizontal' column={1} size='small' bordered>
<Description.Item label='Estimated quality: '>{estimatedQuality}</Description.Item> <Description.Item label='Estimated quality: '>{estimatedQuality}</Description.Item>
@ -119,7 +119,7 @@ export default function SubmitReviewModal(): JSX.Element | null {
<RadioButton value={ReviewStatus.REJECTED}>Reject</RadioButton> <RadioButton value={ReviewStatus.REJECTED}>Reject</RadioButton>
</Radio.Group> </Radio.Group>
{reviewStatus === ReviewStatus.REVIEW_FURTHER && ( {reviewStatus === ReviewStatus.REVIEW_FURTHER && (
<Row align='middle' type='flex' justify='start'> <Row align='middle' justify='start'>
<Col> <Col>
<Text type='secondary'>Reviewer: </Text> <Text type='secondary'>Reviewer: </Text>
</Col> </Col>
@ -128,7 +128,7 @@ export default function SubmitReviewModal(): JSX.Element | null {
</Col> </Col>
</Row> </Row>
)} )}
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col> <Col>
<Rate <Rate
value={Math.round(estimatedQuality)} value={Math.round(estimatedQuality)}

@ -52,17 +52,17 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
return ( return (
<div className='cvat-draw-shape-popover-content'> <div className='cvat-draw-shape-popover-content'>
<Row type='flex' justify='start'> <Row justify='start'>
<Col> <Col>
<Text className='cvat-text-color' strong>{`Draw new ${shapeType}`}</Text> <Text className='cvat-text-color' strong>{`Draw new ${shapeType}`}</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='start'> <Row justify='start'>
<Col> <Col>
<Text className='cvat-text-color'>Label</Text> <Text className='cvat-text-color'>Label</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center'> <Row justify='center'>
<Col span={24}> <Col span={24}>
<LabelSelector <LabelSelector
style={{ width: '100%' }} style={{ width: '100%' }}
@ -79,7 +79,7 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
<Text className='cvat-text-color'> Drawing method </Text> <Text className='cvat-text-color'> Drawing method </Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='space-around'> <Row justify='space-around'>
<Col> <Col>
<Radio.Group <Radio.Group
style={{ display: 'flex' }} style={{ display: 'flex' }}
@ -104,7 +104,7 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
<Text className='cvat-text-color'> Drawing method </Text> <Text className='cvat-text-color'> Drawing method </Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='space-around'> <Row justify='space-around'>
<Col> <Col>
<Radio.Group <Radio.Group
style={{ display: 'flex' }} style={{ display: 'flex' }}
@ -123,7 +123,7 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
</> </>
)} )}
{shapeType !== ShapeType.RECTANGLE && shapeType !== ShapeType.CUBOID && ( {shapeType !== ShapeType.RECTANGLE && shapeType !== ShapeType.CUBOID && (
<Row type='flex' justify='space-around' align='middle'> <Row justify='space-around' align='middle'>
<Col span={14}> <Col span={14}>
<Text className='cvat-text-color'> Number of points: </Text> <Text className='cvat-text-color'> Number of points: </Text>
</Col> </Col>
@ -144,7 +144,7 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
</Col> </Col>
</Row> </Row>
)} )}
<Row type='flex' justify='space-around'> <Row justify='space-around'>
<Col span={12}> <Col span={12}>
<Tooltip title={`Press ${repeatShapeShortcut} to draw again`} mouseLeaveDelay={0}> <Tooltip title={`Press ${repeatShapeShortcut} to draw again`} mouseLeaveDelay={0}>
<Button onClick={onDrawShape}>Shape</Button> <Button onClick={onDrawShape}>Shape</Button>

@ -24,19 +24,19 @@ function SetupTagPopover(props: Props): JSX.Element {
return ( return (
<div className='cvat-draw-shape-popover-content'> <div className='cvat-draw-shape-popover-content'>
<Row type='flex' justify='start'> <Row justify='start'>
<Col> <Col>
<Text className='cvat-text-color' strong> <Text className='cvat-text-color' strong>
Setup tag Setup tag
</Text> </Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='start'> <Row justify='start'>
<Col> <Col>
<Text className='cvat-text-color'>Label</Text> <Text className='cvat-text-color'>Label</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center'> <Row justify='center'>
<Col span={24}> <Col span={24}>
<LabelSelector <LabelSelector
style={{ width: '100%' }} style={{ width: '100%' }}
@ -46,7 +46,7 @@ function SetupTagPopover(props: Props): JSX.Element {
/> />
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='space-around'> <Row justify='space-around'>
<Col span={24}> <Col span={24}>
<Tooltip title={`Press ${repeatShapeShortcut} to add a tag again`} mouseLeaveDelay={0}> <Tooltip title={`Press ${repeatShapeShortcut} to add a tag again`} mouseLeaveDelay={0}>
<Button onClick={() => onSetup(selectedLabelID)}>Tag</Button> <Button onClick={() => onSetup(selectedLabelID)}>Tag</Button>

@ -18,23 +18,27 @@ interface Props {
} }
function SplitControl(props: Props): JSX.Element { function SplitControl(props: Props): JSX.Element {
const { switchSplitShortcut, activeControl, canvasInstance, splitTrack } = props; const {
switchSplitShortcut, activeControl, canvasInstance, splitTrack,
} = props;
const dynamicIconProps = const dynamicIconProps =
activeControl === ActiveControl.SPLIT ? { activeControl === ActiveControl.SPLIT ?
className: 'cvat-split-track-control cvat-active-canvas-control', {
onClick: (): void => { className: 'cvat-split-track-control cvat-active-canvas-control',
canvasInstance.split({ enabled: false }); onClick: (): void => {
splitTrack(false); canvasInstance.split({ enabled: false });
}, splitTrack(false);
} : { },
className: 'cvat-split-track-control', } :
onClick: (): void => { {
canvasInstance.cancel(); className: 'cvat-split-track-control',
canvasInstance.split({ enabled: true }); onClick: (): void => {
splitTrack(true); canvasInstance.cancel();
}, canvasInstance.split({ enabled: true });
}; splitTrack(true);
},
};
return ( return (
<Tooltip title={`Split a track ${switchSplitShortcut}`} placement='right' mouseLeaveDelay={0}> <Tooltip title={`Split a track ${switchSplitShortcut}`} placement='right' mouseLeaveDelay={0}>

@ -375,17 +375,17 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
} }
}; };
private setActiveInteractor = (key: string): void => { private setActiveInteractor = (value: string): void => {
const { interactors } = this.props; const { interactors } = this.props;
this.setState({ this.setState({
activeInteractor: interactors.filter((interactor: Model) => interactor.id === key)[0], activeInteractor: interactors.filter((interactor: Model) => interactor.id === value)[0],
}); });
}; };
private setActiveTracker = (key: string): void => { private setActiveTracker = (value: string): void => {
const { trackers } = this.props; const { trackers } = this.props;
this.setState({ this.setState({
activeTracker: trackers.filter((tracker: Model) => tracker.id === key)[0], activeTracker: trackers.filter((tracker: Model) => tracker.id === value)[0],
}); });
}; };
@ -457,12 +457,12 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
const { activeLabelID } = this.state; const { activeLabelID } = this.state;
return ( return (
<> <>
<Row type='flex' justify='start'> <Row justify='start'>
<Col> <Col>
<Text className='cvat-text-color'>Label</Text> <Text className='cvat-text-color'>Label</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center'> <Row justify='center'>
<Col span={24}> <Col span={24}>
<LabelSelector <LabelSelector
style={{ width: '100%' }} style={{ width: '100%' }}
@ -486,7 +486,7 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
if (!trackers.length) { if (!trackers.length) {
return ( return (
<Row type='flex' justify='center' align='middle' style={{ marginTop: '5px' }}> <Row justify='center' align='middle' style={{ marginTop: '5px' }}>
<Col> <Col>
<Text type='warning' className='cvat-text-color'> <Text type='warning' className='cvat-text-color'>
No available trackers found No available trackers found
@ -498,12 +498,12 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
return ( return (
<> <>
<Row type='flex' justify='start'> <Row justify='start'>
<Col> <Col>
<Text className='cvat-text-color'>Tracker</Text> <Text className='cvat-text-color'>Tracker</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' align='middle' justify='center'> <Row align='middle' justify='center'>
<Col span={24}> <Col span={24}>
<Select <Select
style={{ width: '100%' }} style={{ width: '100%' }}
@ -512,7 +512,7 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
> >
{trackers.map( {trackers.map(
(tracker: Model): JSX.Element => ( (tracker: Model): JSX.Element => (
<Select.Option title={tracker.description} key={tracker.id}> <Select.Option value={tracker.id} title={tracker.description} key={tracker.id}>
{tracker.name} {tracker.name}
</Select.Option> </Select.Option>
), ),
@ -520,7 +520,7 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
</Select> </Select>
</Col> </Col>
</Row> </Row>
<Row type='flex' align='middle' justify='start' style={{ marginTop: '5px' }}> <Row align='middle' justify='start' style={{ marginTop: '5px' }}>
<Col> <Col>
<Text>Tracking frames</Text> <Text>Tracking frames</Text>
</Col> </Col>
@ -541,7 +541,7 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
/> />
</Col> </Col>
</Row> </Row>
<Row type='flex' align='middle' justify='end'> <Row align='middle' justify='end'>
<Col> <Col>
<Button <Button
type='primary' type='primary'
@ -578,7 +578,7 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
if (!interactors.length) { if (!interactors.length) {
return ( return (
<Row type='flex' justify='center' align='middle' style={{ marginTop: '5px' }}> <Row justify='center' align='middle' style={{ marginTop: '5px' }}>
<Col> <Col>
<Text type='warning' className='cvat-text-color'> <Text type='warning' className='cvat-text-color'>
No available interactors found No available interactors found
@ -590,12 +590,12 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
return ( return (
<> <>
<Row type='flex' justify='start'> <Row justify='start'>
<Col> <Col>
<Text className='cvat-text-color'>Interactor</Text> <Text className='cvat-text-color'>Interactor</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' align='middle' justify='center'> <Row align='middle' justify='center'>
<Col span={24}> <Col span={24}>
<Select <Select
style={{ width: '100%' }} style={{ width: '100%' }}
@ -604,7 +604,11 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
> >
{interactors.map( {interactors.map(
(interactor: Model): JSX.Element => ( (interactor: Model): JSX.Element => (
<Select.Option title={interactor.description} key={interactor.id}> <Select.Option
value={interactor.id}
title={interactor.description}
key={interactor.id}
>
{interactor.name} {interactor.name}
</Select.Option> </Select.Option>
), ),
@ -612,7 +616,7 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
</Select> </Select>
</Col> </Col>
</Row> </Row>
<Row type='flex' align='middle' justify='end'> <Row align='middle' justify='end'>
<Col> <Col>
<Button <Button
type='primary' type='primary'
@ -651,7 +655,7 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
if (!detectors.length) { if (!detectors.length) {
return ( return (
<Row type='flex' justify='center' align='middle' style={{ marginTop: '5px' }}> <Row justify='center' align='middle' style={{ marginTop: '5px' }}>
<Col> <Col>
<Text type='warning' className='cvat-text-color'> <Text type='warning' className='cvat-text-color'>
No available detectors found No available detectors found
@ -679,17 +683,18 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
}); });
const states = result.map( const states = result.map(
(data: any): any => new core.classes.ObjectState({ (data: any): any =>
shapeType: data.type, new core.classes.ObjectState({
label: task.labels.filter((label: any): boolean => label.name === data.label)[0], shapeType: data.type,
points: data.points, label: task.labels.filter((label: any): boolean => label.name === data.label)[0],
objectType: ObjectType.SHAPE, points: data.points,
frame, objectType: ObjectType.SHAPE,
occluded: false, frame,
source: 'auto', occluded: false,
attributes: {}, source: 'auto',
zOrder: curZOrder, attributes: {},
}), zOrder: curZOrder,
}),
); );
await jobInstance.annotations.put(states); await jobInstance.annotations.put(states);
@ -710,7 +715,7 @@ export class ToolsControlComponent extends React.PureComponent<Props, State> {
private renderPopoverContent(): JSX.Element { private renderPopoverContent(): JSX.Element {
return ( return (
<div className='cvat-tools-control-popover-content'> <div className='cvat-tools-control-popover-content'>
<Row type='flex' justify='start'> <Row justify='start'>
<Col> <Col>
<Text className='cvat-text-color' strong> <Text className='cvat-text-color' strong>
AI Tools AI Tools

@ -103,7 +103,7 @@ function ColorPicker(props: Props, ref: React.Ref<any>): JSX.Element {
</> </>
)} )}
title={( title={(
<Row type='flex' justify='space-between' align='middle'> <Row justify='space-between' align='middle'>
<Col span={12}> <Col span={12}>
<Text strong>Select color</Text> <Text strong>Select color</Text>
</Col> </Col>

@ -6,9 +6,8 @@ import React from 'react';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import { CombinedState } from 'reducers/interfaces'; import { CombinedState } from 'reducers/interfaces';
import { import {
LeftOutlined, RightOutlined, EyeInvisibleOutlined, EyeOutlined, LeftOutlined, RightOutlined, EyeInvisibleFilled, EyeOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { IconBaseProps } from '@ant-design/icons/lib/components/Icon';
import Tooltip from 'antd/lib/tooltip'; import Tooltip from 'antd/lib/tooltip';
import Alert from 'antd/lib/alert'; import Alert from 'antd/lib/alert';
import { Row, Col } from 'antd/lib/grid'; import { Row, Col } from 'antd/lib/grid';
@ -27,7 +26,7 @@ export default function LabelsListComponent(): JSX.Element {
const combinedIssues = activeReview ? issues.concat(activeReview.issues) : issues; const combinedIssues = activeReview ? issues.concat(activeReview.issues) : issues;
const frames = combinedIssues.map((issue: any): number => issue.frame).sort((a: number, b: number) => +a - +b); const frames = combinedIssues.map((issue: any): number => issue.frame).sort((a: number, b: number) => +a - +b);
const nearestLeft = frames.filter((_frame: number): boolean => _frame < frame).reverse()[0]; const nearestLeft = frames.filter((_frame: number): boolean => _frame < frame).reverse()[0];
const dinamicLeftProps: IconBaseProps = Number.isInteger(nearestLeft) ? const dinamicLeftProps: any = Number.isInteger(nearestLeft) ?
{ {
onClick: () => dispatch(changeFrameAsync(nearestLeft)), onClick: () => dispatch(changeFrameAsync(nearestLeft)),
} : } :
@ -39,7 +38,7 @@ export default function LabelsListComponent(): JSX.Element {
}; };
const nearestRight = frames.filter((_frame: number): boolean => _frame > frame)[0]; const nearestRight = frames.filter((_frame: number): boolean => _frame > frame)[0];
const dinamicRightProps: IconBaseProps = Number.isInteger(nearestRight) ? const dinamicRightProps: any = Number.isInteger(nearestRight) ?
{ {
onClick: () => dispatch(changeFrameAsync(nearestRight)), onClick: () => dispatch(changeFrameAsync(nearestRight)),
} : } :
@ -53,7 +52,7 @@ export default function LabelsListComponent(): JSX.Element {
return ( return (
<div style={{ height: tabContentHeight }}> <div style={{ height: tabContentHeight }}>
<div className='cvat-objects-sidebar-issues-list-header'> <div className='cvat-objects-sidebar-issues-list-header'>
<Row type='flex' justify='start' align='middle'> <Row justify='start' align='middle'>
<Col> <Col>
<Tooltip title='Find the previous frame with issues'> <Tooltip title='Find the previous frame with issues'>
<LeftOutlined {...dinamicLeftProps} /> <LeftOutlined {...dinamicLeftProps} />
@ -66,8 +65,8 @@ export default function LabelsListComponent(): JSX.Element {
</Col> </Col>
<Col offset={3}> <Col offset={3}>
<Tooltip title='Show/hide all the issues'> <Tooltip title='Show/hide all the issues'>
{ issuesHidden ? ( {issuesHidden ? (
<EyeInvisibleOutlined <EyeInvisibleFilled
onClick={() => dispatch(reviewActions.switchIssuesHiddenFlag(false))} onClick={() => dispatch(reviewActions.switchIssuesHiddenFlag(false))}
/> />
) : ( ) : (

@ -7,7 +7,7 @@ import { Row, Col } from 'antd/lib/grid';
import Button from 'antd/lib/button'; import Button from 'antd/lib/button';
import Text from 'antd/lib/typography/Text'; import Text from 'antd/lib/typography/Text';
import { import {
LockOutlined, UnlockOutlined, EyeInvisibleOutlined, EyeOutlined, LockFilled, UnlockOutlined, EyeInvisibleFilled, EyeOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
interface Props { interface Props {
@ -48,14 +48,15 @@ function LabelItemComponent(props: Props): JSX.Element {
return ( return (
<Row <Row
type='flex'
align='middle' align='middle'
justify='space-around' justify='space-around'
className='cvat-objects-sidebar-label-item' className='cvat-objects-sidebar-label-item'
style={{ display: visible ? 'flex' : 'none' }} style={{ display: visible ? 'flex' : 'none' }}
> >
<Col span={4}> <Col span={4}>
<Button style={{ background: labelColor }} className='cvat-label-item-color-button' /> <Button style={{ background: labelColor }} className='cvat-label-item-color-button'>
{' '}
</Button>
</Col> </Col>
<Col span={14}> <Col span={14}>
<Text strong className='cvat-text'> <Text strong className='cvat-text'>
@ -64,14 +65,14 @@ function LabelItemComponent(props: Props): JSX.Element {
</Col> </Col>
<Col span={3}> <Col span={3}>
{statesLocked ? ( {statesLocked ? (
<LockOutlined {...classes.lock.enabled} onClick={unlockStates} /> <LockFilled {...classes.lock.enabled} onClick={unlockStates} />
) : ( ) : (
<UnlockOutlined {...classes.lock.disabled} onClick={lockStates} /> <UnlockOutlined {...classes.lock.disabled} onClick={lockStates} />
)} )}
</Col> </Col>
<Col span={3}> <Col span={3}>
{statesHidden ? ( {statesHidden ? (
<EyeInvisibleOutlined {...classes.hidden.enabled} onClick={showStates} /> <EyeInvisibleFilled {...classes.hidden.enabled} onClick={showStates} />
) : ( ) : (
<EyeOutlined {...classes.hidden.disabled} onClick={hideStates} /> <EyeOutlined {...classes.hidden.disabled} onClick={hideStates} />
)} )}

@ -94,7 +94,7 @@ function ItemTopComponent(props: Props): JSX.Element {
}; };
return ( return (
<Row type='flex' align='middle'> <Row align='middle'>
<Col span={10}> <Col span={10}>
<Text style={{ fontSize: 12 }}>{clientID}</Text> <Text style={{ fontSize: 12 }}>{clientID}</Text>
<br /> <br />
@ -104,7 +104,13 @@ function ItemTopComponent(props: Props): JSX.Element {
</Col> </Col>
<Col span={12}> <Col span={12}>
<Tooltip title='Change current label' mouseLeaveDelay={0}> <Tooltip title='Change current label' mouseLeaveDelay={0}>
<LabelSelector disabled={readonly} size='small' labels={labels} value={labelID} onChange={changeLabel} /> <LabelSelector
disabled={readonly}
size='small'
labels={labels}
value={labelID}
onChange={changeLabel}
/>
</Tooltip> </Tooltip>
</Col> </Col>
<Col span={2}> <Col span={2}>

@ -4,7 +4,19 @@
import React from 'react'; import React from 'react';
import { Row, Col } from 'antd/lib/grid'; import { Row, Col } from 'antd/lib/grid';
import Icon from '@ant-design/icons'; import Icon, {
UnlockOutlined,
LockFilled,
TeamOutlined,
UserOutlined,
PushpinFilled,
PushpinOutlined,
EyeInvisibleFilled,
StarFilled,
SelectOutlined,
StarOutlined,
EyeOutlined,
} from '@ant-design/icons';
import Tooltip from 'antd/lib/tooltip'; import Tooltip from 'antd/lib/tooltip';
import { ObjectType, ShapeType } from 'reducers/interfaces'; import { ObjectType, ShapeType } from 'reducers/interfaces';
@ -130,9 +142,9 @@ function SwitchLock(props: Props): JSX.Element {
return ( return (
<Tooltip title={`Switch lock property ${switchLockShortcut}`} mouseLeaveDelay={0}> <Tooltip title={`Switch lock property ${switchLockShortcut}`} mouseLeaveDelay={0}>
{locked ? ( {locked ? (
<Icon {...classes.lock.enabled} type='lock' theme='filled' onClick={unlock} /> <LockFilled {...classes.lock.enabled} onClick={unlock} />
) : ( ) : (
<Icon {...classes.lock.disabled} type='unlock' onClick={lock} /> <UnlockOutlined {...classes.lock.disabled} onClick={lock} />
)} )}
</Tooltip> </Tooltip>
); );
@ -145,9 +157,9 @@ function SwitchOccluded(props: Props): JSX.Element {
return ( return (
<Tooltip title={`Switch occluded property ${switchOccludedShortcut}`} mouseLeaveDelay={0}> <Tooltip title={`Switch occluded property ${switchOccludedShortcut}`} mouseLeaveDelay={0}>
{occluded ? ( {occluded ? (
<Icon {...classes.occluded.enabled} type='team' onClick={unsetOccluded} /> <TeamOutlined {...classes.occluded.enabled} onClick={unsetOccluded} />
) : ( ) : (
<Icon {...classes.occluded.disabled} type='user' onClick={setOccluded} /> <UserOutlined {...classes.occluded.disabled} onClick={setOccluded} />
)} )}
</Tooltip> </Tooltip>
); );
@ -158,9 +170,9 @@ function SwitchPinned(props: Props): JSX.Element {
return ( return (
<Tooltip title='Switch pinned property' mouseLeaveDelay={0}> <Tooltip title='Switch pinned property' mouseLeaveDelay={0}>
{pinned ? ( {pinned ? (
<Icon {...classes.pinned.enabled} type='pushpin' theme='filled' onClick={unpin} /> <PushpinFilled {...classes.pinned.enabled} onClick={unpin} />
) : ( ) : (
<Icon {...classes.pinned.disabled} type='pushpin' onClick={pin} /> <PushpinOutlined {...classes.pinned.disabled} onClick={pin} />
)} )}
</Tooltip> </Tooltip>
); );
@ -174,15 +186,9 @@ function SwitchHidden(props: Props): JSX.Element {
return ( return (
<Tooltip title={`Switch hidden property ${switchHiddenShortcut}`} mouseLeaveDelay={0}> <Tooltip title={`Switch hidden property ${switchHiddenShortcut}`} mouseLeaveDelay={0}>
{hidden ? ( {hidden ? (
<Icon <EyeInvisibleFilled {...classes.hidden.enabled} onClick={show} style={hiddenStyle} />
{...classes.hidden.enabled}
type='eye-invisible'
theme='filled'
onClick={show}
style={hiddenStyle}
/>
) : ( ) : (
<Icon {...classes.hidden.disabled} type='eye' onClick={hide} style={hiddenStyle} /> <EyeOutlined {...classes.hidden.disabled} onClick={hide} style={hiddenStyle} />
)} )}
</Tooltip> </Tooltip>
); );
@ -203,7 +209,7 @@ function SwitchOutside(props: Props): JSX.Element {
style={outsideStyle} style={outsideStyle}
/> />
) : ( ) : (
<Icon {...classes.outside.disabled} type='select' onClick={setOutside} style={outsideStyle} /> <SelectOutlined {...classes.outside.disabled} onClick={setOutside} style={outsideStyle} />
)} )}
</Tooltip> </Tooltip>
); );
@ -217,15 +223,9 @@ function SwitchKeyframe(props: Props): JSX.Element {
return ( return (
<Tooltip title={`Switch keyframe property ${switchKeyFrameShortcut}`} mouseLeaveDelay={0}> <Tooltip title={`Switch keyframe property ${switchKeyFrameShortcut}`} mouseLeaveDelay={0}>
{keyframe ? ( {keyframe ? (
<Icon <StarFilled {...classes.keyframe.enabled} onClick={unsetKeyframe} style={keyframeStyle} />
{...classes.keyframe.enabled}
type='star'
theme='filled'
onClick={unsetKeyframe}
style={keyframeStyle}
/>
) : ( ) : (
<Icon {...classes.keyframe.disabled} type='star' onClick={setKeyframe} style={keyframeStyle} /> <StarOutlined {...classes.keyframe.disabled} onClick={setKeyframe} style={keyframeStyle} />
)} )}
</Tooltip> </Tooltip>
); );
@ -236,9 +236,9 @@ function ItemButtonsComponent(props: Props): JSX.Element {
if (objectType === ObjectType.TRACK) { if (objectType === ObjectType.TRACK) {
return ( return (
<Row type='flex' align='middle' justify='space-around'> <Row align='middle' justify='space-around'>
<Col span={20} style={{ textAlign: 'center' }}> <Col span={20} style={{ textAlign: 'center' }}>
<Row type='flex' justify='space-around'> <Row justify='space-around'>
<Col> <Col>
<NavigateFirstKeyframe {...props} /> <NavigateFirstKeyframe {...props} />
</Col> </Col>
@ -253,7 +253,7 @@ function ItemButtonsComponent(props: Props): JSX.Element {
</Col> </Col>
</Row> </Row>
{!readonly && ( {!readonly && (
<Row type='flex' justify='space-around'> <Row justify='space-around'>
<Col> <Col>
<SwitchOutside {...props} /> <SwitchOutside {...props} />
</Col> </Col>
@ -287,9 +287,9 @@ function ItemButtonsComponent(props: Props): JSX.Element {
if (objectType === ObjectType.TAG) { if (objectType === ObjectType.TAG) {
return ( return (
<Row type='flex' align='middle' justify='space-around'> <Row align='middle' justify='space-around'>
<Col span={20} style={{ textAlign: 'center' }}> <Col span={20} style={{ textAlign: 'center' }}>
<Row type='flex' justify='space-around'> <Row justify='space-around'>
<Col> <Col>
<SwitchLock {...props} /> <SwitchLock {...props} />
</Col> </Col>
@ -300,9 +300,9 @@ function ItemButtonsComponent(props: Props): JSX.Element {
} }
return ( return (
<Row type='flex' align='middle' justify='space-around'> <Row align='middle' justify='space-around'>
<Col span={20} style={{ textAlign: 'center' }}> <Col span={20} style={{ textAlign: 'center' }}>
<Row type='flex' justify='space-around'> <Row justify='space-around'>
<Col> <Col>
<SwitchLock {...props} /> <SwitchLock {...props} />
</Col> </Col>

@ -55,7 +55,6 @@ function ItemAttributesComponent(props: Props): JSX.Element {
(attribute: any): JSX.Element => ( (attribute: any): JSX.Element => (
<Row <Row
key={attribute.id} key={attribute.id}
type='flex'
align='middle' align='middle'
justify='start' justify='start'
className='cvat-object-item-attribute-wrapper' className='cvat-object-item-attribute-wrapper'

@ -5,8 +5,12 @@
import React from 'react'; import React from 'react';
import { Row, Col } from 'antd/lib/grid'; import { Row, Col } from 'antd/lib/grid';
import { import {
LockOutlined, UnlockOutlined, EyeInvisibleOutlined, LockFilled,
EyeOutlined, CaretDownOutlined, CaretUpFilled, UnlockOutlined,
EyeInvisibleFilled,
EyeOutlined,
CaretDownOutlined,
CaretUpFilled,
} from '@ant-design/icons'; } from '@ant-design/icons';
import Tooltip from 'antd/lib/tooltip'; import Tooltip from 'antd/lib/tooltip';
@ -14,7 +18,6 @@ import AnnotationsFiltersInput from 'components/annotation-page/annotations-filt
import StatesOrderingSelector from 'components/annotation-page/standard-workspace/objects-side-bar/states-ordering-selector'; import StatesOrderingSelector from 'components/annotation-page/standard-workspace/objects-side-bar/states-ordering-selector';
import { StatesOrdering } from 'reducers/interfaces'; import { StatesOrdering } from 'reducers/interfaces';
interface Props { interface Props {
readonly: boolean; readonly: boolean;
statesHidden: boolean; statesHidden: boolean;
@ -39,11 +42,7 @@ function LockAllSwitcher(props: Props): JSX.Element {
return ( return (
<Col span={2}> <Col span={2}>
<Tooltip title={`Switch lock property for all ${switchLockAllShortcut}`} mouseLeaveDelay={0}> <Tooltip title={`Switch lock property for all ${switchLockAllShortcut}`} mouseLeaveDelay={0}>
{statesLocked ? ( {statesLocked ? <LockFilled onClick={unlockAllStates} /> : <UnlockOutlined onClick={lockAllStates} />}
<LockOutlined type='lock' onClick={unlockAllStates} />
) : (
<UnlockOutlined type='unlock' onClick={lockAllStates} />
)}
</Tooltip> </Tooltip>
</Col> </Col>
); );
@ -57,7 +56,7 @@ function HideAllSwitcher(props: Props): JSX.Element {
<Col span={2}> <Col span={2}>
<Tooltip title={`Switch hidden property for all ${switchHiddenAllShortcut}`} mouseLeaveDelay={0}> <Tooltip title={`Switch hidden property for all ${switchHiddenAllShortcut}`} mouseLeaveDelay={0}>
{statesHidden ? ( {statesHidden ? (
<EyeInvisibleOutlined onClick={showAllStates} /> <EyeInvisibleFilled onClick={showAllStates} />
) : ( ) : (
<EyeOutlined onClick={hideAllStates} /> <EyeOutlined onClick={hideAllStates} />
)} )}
@ -87,11 +86,11 @@ function ObjectListHeader(props: Props): JSX.Element {
return ( return (
<div className='cvat-objects-sidebar-states-header'> <div className='cvat-objects-sidebar-states-header'>
<Row> <Row>
<Col> <Col span={24}>
<AnnotationsFiltersInput /> <AnnotationsFiltersInput />
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='space-between' align='middle'> <Row justify='space-between' align='middle'>
{!readonly && ( {!readonly && (
<> <>
<LockAllSwitcher {...props} /> <LockAllSwitcher {...props} />

@ -19,6 +19,10 @@
background: $header-color; background: $header-color;
border-radius: 0; border-radius: 0;
height: 25px; height: 25px;
.ant-collapse-arrow {
top: $grid-unit-size;
}
} }
> .ant-collapse-content { > .ant-collapse-content {
@ -48,7 +52,11 @@
box-sizing: border-box; box-sizing: border-box;
border: none; border: none;
.ant-tabs-card-bar { .ant-tabs-nav {
&::before {
content: none;
}
border: none; border: none;
margin-bottom: 0; margin-bottom: 0;
padding-top: 25px; padding-top: 25px;
@ -75,7 +83,7 @@
box-sizing: border-box; box-sizing: border-box;
> div > div { > div > div {
> i { > span[role='img'] {
font-size: 16px; font-size: 16px;
color: $objects-bar-icons-color; color: $objects-bar-icons-color;
@ -133,7 +141,7 @@
text-align: center; text-align: center;
margin: 0 2px; margin: 0 2px;
> i { > span[role='img'] {
@extend .cvat-object-sidebar-icon; @extend .cvat-object-sidebar-icon;
} }
@ -182,7 +190,7 @@
line-height: 12px; line-height: 12px;
} }
> div:nth-child(3) > i { > div:nth-child(3) > span {
@extend .cvat-object-sidebar-icon; @extend .cvat-object-sidebar-icon;
font-size: 25px; font-size: 25px;
@ -198,7 +206,7 @@
margin-top: 5px; margin-top: 5px;
} }
i { span[role='img'] {
@extend .cvat-object-sidebar-icon; @extend .cvat-object-sidebar-icon;
} }
} }
@ -216,6 +224,10 @@
background: inherit; background: inherit;
padding-top: 2px; padding-top: 2px;
padding-bottom: 2px; padding-bottom: 2px;
.ant-collapse-arrow {
top: $grid-unit-size;
}
} }
> .ant-collapse-content { > .ant-collapse-content {
@ -281,10 +293,10 @@
.cvat-objects-sidebar-label-item { .cvat-objects-sidebar-label-item {
height: 2.5em; height: 2.5em;
border-bottom: 1px solid $border-color-2; border-bottom: 1px solid $border-color-1;
padding: 5px; padding: 5px;
i { span {
@extend .cvat-object-sidebar-icon; @extend .cvat-object-sidebar-icon;
} }

@ -8,10 +8,6 @@
height: 100%; height: 100%;
} }
.cvat-objects-sidebar-filter-input {
width: calc(100% - 35px);
}
.cvat-objects-sidebar-sider { .cvat-objects-sidebar-sider {
top: 0; top: 0;
right: 0; right: 0;
@ -34,26 +30,38 @@
.cvat-canvas-controls-sidebar { .cvat-canvas-controls-sidebar {
background-color: $background-color-2; background-color: $background-color-2;
border-right: 1px solid $border-color-1; border-right: 1px solid $border-color-1;
}
> div { .cvat-cursor-control,
> i { .cvat-move-control,
border-radius: 3.3px; .cvat-rotate-canvas-control,
transform: scale(0.65); .cvat-fit-control,
padding: 2px; .cvat-resize-control,
.cvat-draw-rectangle-control,
&:hover { .cvat-draw-polygon-control,
background: $header-color; .cvat-draw-polyline-control,
transform: scale(0.75); .cvat-draw-points-control,
} .cvat-draw-cuboid-control,
.cvat-setup-tag-control,
.cvat-merge-control,
.cvat-group-control,
.cvat-split-track-control,
.cvat-issue-control {
border-radius: 3.3px;
transform: scale(0.65);
padding: 2px;
&:active { &:hover {
transform: scale(0.65); background: $header-color;
} transform: scale(0.75);
}
> svg { &:active {
transform: scale(0.8); transform: scale(0.65);
} }
}
> svg {
transform: scale(0.8);
} }
} }
@ -76,13 +84,15 @@
} }
} }
.cvat-rotate-canvas-controls > .ant-popover-content > .ant-popover-inner > div > .ant-popover-inner-content { .cvat-rotate-canvas-controls {
padding: 0; .ant-popover-inner-content {
padding: 0;
}
} }
.cvat-draw-shape-popover, .cvat-draw-shape-popover,
.cvat-tools-control-popover { .cvat-tools-control-popover {
> .ant-popover-content > .ant-popover-inner > div > .ant-popover-inner-content { .ant-popover-inner-content {
padding: 0; padding: 0;
} }
} }

@ -6,6 +6,7 @@
.cvat-annotation-page.ant-layout { .cvat-annotation-page.ant-layout {
height: 100%; height: 100%;
overflow: hidden;
} }
.ant-layout-header.cvat-annotation-header { .ant-layout-header.cvat-annotation-header {
@ -37,21 +38,21 @@
align-items: center; align-items: center;
margin: 0 3px; margin: 0 3px;
> span { > span:not([role='img']) {
margin-left: 0; margin-left: 0;
font-size: 10px; font-size: 10px;
} }
> i { > span[role='img'] {
transform: scale(0.8); transform: scale(0.8);
padding: 3px; padding: 3px;
} }
&:hover > i { &:hover > span[role='img'] {
transform: scale(0.85); transform: scale(0.85);
} }
&:active > i { &:active > span[role='img'] {
transform: scale(0.8); transform: scale(0.8);
} }
@ -80,7 +81,7 @@
height: 100%; height: 100%;
margin-right: 10px; margin-right: 10px;
> i { > span {
font-size: 25px; font-size: 25px;
margin: 0 7px; margin: 0 7px;
color: $player-buttons-color; color: $player-buttons-color;
@ -96,18 +97,17 @@
} }
.cvat-player-controls { .cvat-player-controls {
position: relative;
height: 100%; height: 100%;
line-height: 27px; line-height: 27px;
> div { > div {
position: relative;
height: 50%; height: 50%;
} }
} }
.cvat-player-slider { .cvat-player-slider {
width: 350px; width: 350px;
margin: 0;
> .ant-slider-rail { > .ant-slider-rail {
background-color: $player-slider-color; background-color: $player-slider-color;
@ -266,7 +266,7 @@
} }
} }
> i { > span[role='img'] {
opacity: 0.7; opacity: 0.7;
color: $objects-bar-icons-color; color: $objects-bar-icons-color;

@ -12,7 +12,7 @@
background: $background-color-2; background: $background-color-2;
padding: 5px; padding: 5px;
> div > .ant-row-flex > .ant-col > .ant-tag { > div > .ant-row > .ant-col > .ant-tag {
margin: 4px; margin: 4px;
} }
} }

@ -98,7 +98,6 @@ const ShortcutsSelect = (props: Props): JSX.Element => {
onChange={(value: string) => { onChange={(value: string) => {
onChangeShortcutLabel(value, Number.parseInt(id, 10)); onChangeShortcutLabel(value, Number.parseInt(id, 10));
}} }}
size='default'
style={{ width: 200 }} style={{ width: 200 }}
className='cvat-tag-annotation-label-select' className='cvat-tag-annotation-label-select'
> >

@ -207,19 +207,15 @@ function TagAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.Elemen
ant-layout-sider-zero-width-trigger-left`} ant-layout-sider-zero-width-trigger-left`}
onClick={() => setSidebarCollapsed(!sidebarCollapsed)} onClick={() => setSidebarCollapsed(!sidebarCollapsed)}
> >
{sidebarCollapsed ? ( {sidebarCollapsed ? <MenuFoldOutlined title='Show' /> : <MenuUnfoldOutlined title='Hide' />}
<MenuFoldOutlined title='Show' />
) : (
<MenuUnfoldOutlined title='Hide' />
)}
</span> </span>
<Row type='flex' justify='start' className='cvat-tag-annotation-sidebar-label-select'> <Row justify='start' className='cvat-tag-annotation-sidebar-label-select'>
<Col> <Col>
<Text strong>Tag label</Text> <Text strong>Tag label</Text>
<LabelSelector labels={labels} value={selectedLabelID} onChange={onChangeLabel} /> <LabelSelector labels={labels} value={selectedLabelID} onChange={onChangeLabel} />
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='space-around' className='cvat-tag-annotation-sidebar-buttons'> <Row justify='space-around' className='cvat-tag-annotation-sidebar-buttons'>
<Col span={8}> <Col span={8}>
<Button onClick={() => onAddTag(selectedLabelID)}>Add tag</Button> <Button onClick={() => onAddTag(selectedLabelID)}>Add tag</Button>
</Col> </Col>
@ -227,7 +223,7 @@ function TagAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.Elemen
<Button onClick={onChangeFrame}>Skip frame</Button> <Button onClick={onChangeFrame}>Skip frame</Button>
</Col> </Col>
</Row> </Row>
<Row type='flex' className='cvat-tag-annotation-sidebar-checkbox-skip-frame'> <Row className='cvat-tag-annotation-sidebar-checkbox-skip-frame'>
<Col> <Col>
<Checkbox <Checkbox
checked={skipFrame} checked={skipFrame}
@ -239,7 +235,7 @@ function TagAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.Elemen
</Checkbox> </Checkbox>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='start' className='cvat-tag-annotation-sidebar-frame-tags'> <Row justify='start' className='cvat-tag-annotation-sidebar-frame-tags'>
<Col> <Col>
<Text strong>Frame tags:&nbsp;</Text> <Text strong>Frame tags:&nbsp;</Text>
{frameTags.map((tag: any) => ( {frameTags.map((tag: any) => (
@ -262,7 +258,7 @@ function TagAnnotationSidebar(props: StateToProps & DispatchToProps): JSX.Elemen
<ShortcutsSelect onAddTag={onAddTag} /> <ShortcutsSelect onAddTag={onAddTag} />
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center' className='cvat-tag-annotation-sidebar-shortcut-help'> <Row justify='center' className='cvat-tag-annotation-sidebar-shortcut-help'>
<Col> <Col>
<Text> <Text>
Use&nbsp; Use&nbsp;

@ -5,7 +5,7 @@
import React from 'react'; import React from 'react';
import { Col } from 'antd/lib/grid'; import { Col } from 'antd/lib/grid';
import Icon from '@ant-design/icons' import Icon from '@ant-design/icons';
import Tooltip from 'antd/lib/tooltip'; import Tooltip from 'antd/lib/tooltip';
import Popover from 'antd/lib/popover'; import Popover from 'antd/lib/popover';

@ -50,7 +50,7 @@ function PlayerNavigation(props: Props): JSX.Element {
return ( return (
<> <>
<Col className='cvat-player-controls'> <Col className='cvat-player-controls'>
<Row type='flex'> <Row align='bottom'>
<Col> <Col>
<Slider <Slider
className='cvat-player-slider' className='cvat-player-slider'
@ -61,7 +61,7 @@ function PlayerNavigation(props: Props): JSX.Element {
/> />
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center'> <Row justify='center'>
<Col className='cvat-player-filename-wrapper'> <Col className='cvat-player-filename-wrapper'>
<Tooltip title={frameFilename} mouseLeaveDelay={0}> <Tooltip title={frameFilename} mouseLeaveDelay={0}>
<Text type='secondary'>{frameFilename}</Text> <Text type='secondary'>{frameFilename}</Text>
@ -82,7 +82,7 @@ function PlayerNavigation(props: Props): JSX.Element {
type='number' type='number'
value={frameInputValue} value={frameInputValue}
onChange={(value: number | undefined | string) => { onChange={(value: number | undefined | string) => {
if (typeof (value) !== 'undefined') { if (typeof value !== 'undefined') {
setFrameInputValue(Math.floor(clamp(+value, startFrame, stopFrame))); setFrameInputValue(Math.floor(clamp(+value, startFrame, stopFrame)));
} }
}} }}

@ -133,12 +133,12 @@ export default function StatisticsModalComponent(props: Props): JSX.Element {
return ( return (
<Modal {...baseProps}> <Modal {...baseProps}>
<div className='cvat-job-info-modal-window'> <div className='cvat-job-info-modal-window'>
<Row type='flex' justify='start'> <Row justify='start'>
<Col> <Col>
<Text className='cvat-text'>Overview</Text> <Text className='cvat-text'>Overview</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='start'> <Row justify='start'>
<Col span={4}> <Col span={4}>
<Text strong className='cvat-text'> <Text strong className='cvat-text'>
Assignee Assignee
@ -171,7 +171,7 @@ export default function StatisticsModalComponent(props: Props): JSX.Element {
</Col> </Col>
</Row> </Row>
{!!bugTracker && ( {!!bugTracker && (
<Row type='flex' justify='start' className='cvat-job-info-bug-tracker'> <Row justify='start' className='cvat-job-info-bug-tracker'>
<Col> <Col>
<Text strong className='cvat-text'> <Text strong className='cvat-text'>
Bug tracker Bug tracker
@ -180,7 +180,7 @@ export default function StatisticsModalComponent(props: Props): JSX.Element {
</Col> </Col>
</Row> </Row>
)} )}
<Row type='flex' justify='space-around' className='cvat-job-info-statistics'> <Row justify='space-around' className='cvat-job-info-statistics'>
<Col span={24}> <Col span={24}>
<Text className='cvat-text'>Annotations statistics</Text> <Text className='cvat-text'>Annotations statistics</Text>
<Table scroll={{ y: 400 }} bordered pagination={false} columns={columns} dataSource={rows} /> <Table scroll={{ y: 400 }} bordered pagination={false} columns={columns} dataSource={rows} />

@ -99,7 +99,7 @@ export default function AnnotationTopBarComponent(props: Props): JSX.Element {
} = props; } = props;
return ( return (
<Row type='flex' justify='space-between'> <Row justify='space-between'>
<LeftGroup <LeftGroup
saving={saving} saving={saving}
savingStatuses={savingStatuses} savingStatuses={savingStatuses}
@ -113,7 +113,7 @@ export default function AnnotationTopBarComponent(props: Props): JSX.Element {
onRedoClick={onRedoClick} onRedoClick={onRedoClick}
/> />
<Col className='cvat-annotation-header-player-group'> <Col className='cvat-annotation-header-player-group'>
<Row type='flex' align='middle'> <Row align='middle'>
<PlayerButtons <PlayerButtons
playing={playing} playing={playing}
playPauseShortcut={playPauseShortcut} playPauseShortcut={playPauseShortcut}

@ -116,7 +116,7 @@ export default function CreateProjectContent(): JSX.Element {
}; };
return ( return (
<Row type='flex' justify='start' align='middle' className='cvat-create-project-content'> <Row justify='start' align='middle' className='cvat-create-project-content'>
<Col span={24}> <Col span={24}>
<NameConfigurationForm formRef={nameFormRef} /> <NameConfigurationForm formRef={nameFormRef} />
</Col> </Col>

@ -11,7 +11,7 @@ import CreateProjectContent from './create-project-content';
export default function CreateProjectPageComponent(): JSX.Element { export default function CreateProjectPageComponent(): JSX.Element {
return ( return (
<Row type='flex' justify='center' align='top' className='cvat-create-task-form-wrapper'> <Row justify='center' align='top' className='cvat-create-task-form-wrapper'>
<Col md={20} lg={16} xl={14} xxl={9}> <Col md={20} lg={16} xl={14} xxl={9}>
<Text className='cvat-title'>Create a new project</Text> <Text className='cvat-title'>Create a new project</Text>
<CreateProjectContent /> <CreateProjectContent />

@ -69,8 +69,9 @@ function validateRepository(_: RuleObject, value: string): Promise<[void, void]>
return Promise.resolve(); return Promise.resolve();
} }
const isInteger = ({ min, max }: { min?: number, max?: number }) => ( const isInteger = ({ min, max }: { min?: number; max?: number }) => (
_: RuleObject, value?: number | string, _: RuleObject,
value?: number | string,
): Promise<void> => { ): Promise<void> => {
if (typeof value === 'undefined' || value === '') { if (typeof value === 'undefined' || value === '') {
return Promise.resolve(); return Promise.resolve();
@ -134,17 +135,20 @@ class AdvancedConfigurationForm extends React.PureComponent<Props> {
const { onSubmit } = this.props; const { onSubmit } = this.props;
if (this.formRef.current) { if (this.formRef.current) {
this.formRef.current.resetFields(); this.formRef.current.resetFields();
return this.formRef.current.validateFields().then((values: Store): Promise<void> => { return this.formRef.current.validateFields().then(
const frameFilter = values.frameStep ? `step=${values.frameStep}` : undefined; (values: Store): Promise<void> => {
const entries = Object.entries(values) const frameFilter = values.frameStep ? `step=${values.frameStep}` : undefined;
.filter((entry: [string, unknown]): boolean => entry[0] !== frameFilter); const entries = Object.entries(values).filter(
(entry: [string, unknown]): boolean => entry[0] !== frameFilter,
onSubmit({ );
...Object.fromEntries(entries) as any as AdvancedConfiguration,
frameFilter, onSubmit({
}); ...((Object.fromEntries(entries) as any) as AdvancedConfiguration),
return Promise.resolve(); frameFilter,
}); });
return Promise.resolve();
},
);
} }
return Promise.reject(new Error('Form ref is empty')); return Promise.reject(new Error('Form ref is empty'));
@ -185,13 +189,7 @@ class AdvancedConfigurationForm extends React.PureComponent<Props> {
{ validator: isInteger({ min: 5, max: 100 }) }, { validator: isInteger({ min: 5, max: 100 }) },
]} ]}
> >
<Input <Input size='large' type='number' min={5} max={100} suffix={<PercentageOutlined />} />
size='large'
type='number'
min={5}
max={100}
suffix={<PercentageOutlined />}
/>
</Form.Item> </Form.Item>
</Tooltip> </Tooltip>
); );
@ -215,11 +213,7 @@ class AdvancedConfigurationForm extends React.PureComponent<Props> {
private renderSegmentSize(): JSX.Element { private renderSegmentSize(): JSX.Element {
return ( return (
<Tooltip title='Defines a number of frames in a segment' mouseLeaveDelay={0}> <Tooltip title='Defines a number of frames in a segment' mouseLeaveDelay={0}>
<Form.Item <Form.Item label='Segment size' name='segmentSize' rules={[{ validator: isInteger({ min: 1 }) }]}>
label='Segment size'
name='segmentSize'
rules={[{ validator: isInteger({ min: 1 }) }]}
>
<Input size='large' type='number' min={1} /> <Input size='large' type='number' min={1} />
</Form.Item> </Form.Item>
</Tooltip> </Tooltip>
@ -228,11 +222,7 @@ class AdvancedConfigurationForm extends React.PureComponent<Props> {
private renderStartFrame(): JSX.Element { private renderStartFrame(): JSX.Element {
return ( return (
<Form.Item <Form.Item label='Start frame' name='startFrame' rules={[{ validator: isInteger({ min: 0 }) }]}>
label='Start frame'
name='startFrame'
rules={[{ validator: isInteger({ min: 0 }) }]}
>
<Input size='large' type='number' min={0} step={1} /> <Input size='large' type='number' min={0} step={1} />
</Form.Item> </Form.Item>
); );
@ -253,11 +243,7 @@ class AdvancedConfigurationForm extends React.PureComponent<Props> {
private renderFrameStep(): JSX.Element { private renderFrameStep(): JSX.Element {
return ( return (
<Form.Item <Form.Item label='Frame step' name='frameStep' rules={[{ validator: isInteger({ min: 1 }) }]}>
label='Frame step'
name='frameStep'
rules={[{ validator: isInteger({ min: 1 }) }]}
>
<Input size='large' type='number' min={1} step={1} /> <Input size='large' type='number' min={1} step={1} />
</Form.Item> </Form.Item>
); );
@ -286,10 +272,7 @@ class AdvancedConfigurationForm extends React.PureComponent<Props> {
extra='Attach a repository to store annotations there' extra='Attach a repository to store annotations there'
rules={[{ validator: validateRepository }]} rules={[{ validator: validateRepository }]}
> >
<Input <Input size='large' placeholder='e.g. https//github.com/user/repos [annotation/<anno_file_name>.zip]' />
size='large'
placeholder='e.g. https//github.com/user/repos [annotation/<anno_file_name>.zip]'
/>
</Form.Item> </Form.Item>
); );
} }
@ -337,11 +320,7 @@ class AdvancedConfigurationForm extends React.PureComponent<Props> {
private renderCreateTaskMethod(): JSX.Element { private renderCreateTaskMethod(): JSX.Element {
return ( return (
<Form.Item <Form.Item help='Using cache to store data.' name='useCache' valuePropName='checked'>
help='Using cache to store data.'
name='useCache'
valuePropName='checked'
>
<Checkbox> <Checkbox>
<Text className='cvat-text-color'>Use cache</Text> <Text className='cvat-text-color'>Use cache</Text>
</Checkbox> </Checkbox>
@ -370,11 +349,7 @@ class AdvancedConfigurationForm extends React.PureComponent<Props> {
)} )}
mouseLeaveDelay={0} mouseLeaveDelay={0}
> >
<Form.Item <Form.Item label='Chunk size' name='dataChunkSize' rules={[{ validator: isInteger({ min: 1 }) }]}>
label='Chunk size'
name='dataChunkSize'
rules={[{ validator: isInteger({ min: 1 }) }]}
>
<Input size='large' type='number' /> <Input size='large' type='number' />
</Form.Item> </Form.Item>
</Tooltip> </Tooltip>
@ -387,9 +362,7 @@ class AdvancedConfigurationForm extends React.PureComponent<Props> {
<Form initialValues={initialValues} ref={this.formRef} layout='vertical'> <Form initialValues={initialValues} ref={this.formRef} layout='vertical'>
{activeFileManagerTab === 'share' ? ( {activeFileManagerTab === 'share' ? (
<Row> <Row>
<Col> <Col>{this.renderCopyDataChechbox()}</Col>
{ this.renderCopyDataChechbox() }
</Col>
</Row> </Row>
) : null} ) : null}
<Row> <Row>
@ -398,7 +371,7 @@ class AdvancedConfigurationForm extends React.PureComponent<Props> {
<Row> <Row>
<Col>{this.renderCreateTaskMethod()}</Col> <Col>{this.renderCreateTaskMethod()}</Col>
</Row> </Row>
<Row type='flex' justify='start'> <Row justify='start'>
<Col span={7}>{this.renderImageQuality()}</Col> <Col span={7}>{this.renderImageQuality()}</Col>
<Col span={7} offset={1}> <Col span={7} offset={1}>
{this.renderOverlap()} {this.renderOverlap()}
@ -408,7 +381,7 @@ class AdvancedConfigurationForm extends React.PureComponent<Props> {
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='start'> <Row justify='start'>
<Col span={7}>{this.renderStartFrame()}</Col> <Col span={7}>{this.renderStartFrame()}</Col>
<Col span={7} offset={1}> <Col span={7} offset={1}>
{this.renderStopFrame()} {this.renderStopFrame()}
@ -418,7 +391,7 @@ class AdvancedConfigurationForm extends React.PureComponent<Props> {
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='start'> <Row justify='start'>
<Col span={7}>{this.renderChunkSize()}</Col> <Col span={7}>{this.renderChunkSize()}</Col>
</Row> </Row>

@ -69,7 +69,7 @@ export default function CreateTaskPage(props: Props): JSX.Element {
}, [error]); }, [error]);
return ( return (
<Row type='flex' justify='center' align='top' className='cvat-create-task-form-wrapper'> <Row justify='center' align='top' className='cvat-create-task-form-wrapper'>
<Col md={20} lg={16} xl={14} xxl={9}> <Col md={20} lg={16} xl={14} xxl={9}>
<Text className='cvat-title'>Create a new task</Text> <Text className='cvat-title'>Create a new task</Text>
<CreateTaskContent <CreateTaskContent

@ -109,7 +109,7 @@ export default function Feedback(): JSX.Element {
visible={visible} visible={visible}
> >
<Button <Button
style={{ color: '#ff4d4f' }} style={visible ? { color: '#ff4d4f' } : {}}
className='cvat-feedback-button' className='cvat-feedback-button'
type='link' type='link'
onClick={(): void => { onClick={(): void => {

@ -9,7 +9,7 @@
padding: 0; padding: 0;
height: auto; height: auto;
> i { > span[role='img'] {
font-size: 40px; font-size: 40px;
} }
} }

@ -3,14 +3,16 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import './styles.scss'; import './styles.scss';
import React from 'react'; import React, { ReactText } from 'react';
import Tabs from 'antd/lib/tabs'; import Tabs from 'antd/lib/tabs';
import Input from 'antd/lib/input'; import Input from 'antd/lib/input';
import Text from 'antd/lib/typography/Text'; import Text from 'antd/lib/typography/Text';
import Paragraph from 'antd/lib/typography/Paragraph'; import Paragraph from 'antd/lib/typography/Paragraph';
import Upload, { RcFile } from 'antd/lib/upload'; import Upload, { RcFile } from 'antd/lib/upload';
import Empty from 'antd/lib/empty'; import Empty from 'antd/lib/empty';
import Tree, { AntTreeNode, TreeNodeNormal } from 'antd/lib/tree/Tree'; import Tree, { TreeNodeNormal } from 'antd/lib/tree/Tree';
// eslint-disable-next-line import/no-extraneous-dependencies
import { EventDataNode } from 'rc-tree/lib/interface';
import { InboxOutlined } from '@ant-design/icons'; import { InboxOutlined } from '@ant-design/icons';
import consts from 'consts'; import consts from 'consts';
@ -124,17 +126,18 @@ export default class FileManager extends React.PureComponent<Props, State> {
private renderShareSelector(): JSX.Element { private renderShareSelector(): JSX.Element {
function renderTreeNodes(data: TreeNodeNormal[]): JSX.Element[] { function renderTreeNodes(data: TreeNodeNormal[]): JSX.Element[] {
// sort alphabetically // sort alphabetically
data.sort((a: TreeNodeNormal, b: TreeNodeNormal): number => a.key.localeCompare(b.key)); data.sort((a: TreeNodeNormal, b: TreeNodeNormal): number =>
a.key.toLocaleString().localeCompare(b.key.toLocaleString()));
return data.map((item: TreeNodeNormal) => { return data.map((item: TreeNodeNormal) => {
if (item.children) { if (item.children) {
return ( return (
<Tree.TreeNode title={item.title} key={item.key} dataRef={item} isLeaf={item.isLeaf}> <Tree.TreeNode title={item.title} key={item.key} data={item} isLeaf={item.isLeaf}>
{renderTreeNodes(item.children)} {renderTreeNodes(item.children)}
</Tree.TreeNode> </Tree.TreeNode>
); );
} }
return <Tree.TreeNode key={item.key} {...item} dataRef={item} />; return <Tree.TreeNode {...item} key={item.key} data={item} />;
}); });
} }
@ -153,21 +156,22 @@ export default class FileManager extends React.PureComponent<Props, State> {
checkStrictly={false} checkStrictly={false}
expandedKeys={expandedKeys} expandedKeys={expandedKeys}
checkedKeys={files.share} checkedKeys={files.share}
loadData={(node: AntTreeNode): Promise<void> => this.loadData(node.props.dataRef.key)} loadData={(event: EventDataNode): Promise<void> => this.loadData(event.key.toLocaleString())}
onExpand={(newExpandedKeys: string[]): void => { onExpand={(newExpandedKeys: ReactText[]): void => {
this.setState({ this.setState({
expandedKeys: newExpandedKeys, expandedKeys: newExpandedKeys.map((text: ReactText): string => text.toLocaleString()),
}); });
}} }}
onCheck={( onCheck={(
checkedKeys: checkedKeys:
| string[] | ReactText[]
| { | {
checked: string[]; checked: ReactText[];
halfChecked: string[]; halfChecked: ReactText[];
}, },
): void => { ): void => {
const keys = checkedKeys as string[]; const keys = (checkedKeys as ReactText[]).map((text: ReactText): string =>
text.toLocaleString());
this.setState({ this.setState({
files: { files: {
...files, ...files,

@ -100,7 +100,9 @@ class GlobalErrorBoundary extends React.PureComponent<Props, State> {
} }
public render(): React.ReactNode { public render(): React.ReactNode {
const { restore, job, serverVersion, coreVersion, canvasVersion, uiVersion } = this.props; const {
restore, job, serverVersion, coreVersion, canvasVersion, uiVersion,
} = this.props;
const { hasError, error } = this.state; const { hasError, error } = this.state;
@ -152,7 +154,8 @@ class GlobalErrorBoundary extends React.PureComponent<Props, State> {
}} }}
> >
{' '} {' '}
Copy{' '} Copy
{' '}
</a> </a>
</Tooltip> </Tooltip>
the error message to clipboard the error message to clipboard

@ -8,9 +8,15 @@ import { connect } from 'react-redux';
import { useHistory } from 'react-router'; import { useHistory } from 'react-router';
import { Row, Col } from 'antd/lib/grid'; import { Row, Col } from 'antd/lib/grid';
import Icon, { import Icon, {
ContactsOutlined, SettingOutlined, InfoCircleOutlined, EditOutlined, SettingOutlined,
LoadingOutlined, LogoutOutlined, GithubOutlined, InfoCircleOutlined,
QuestionCircleOutlined, CaretDownOutlined, EditOutlined,
LoadingOutlined,
LogoutOutlined,
GithubOutlined,
QuestionCircleOutlined,
CaretDownOutlined,
ControlOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import Layout from 'antd/lib/layout'; import Layout from 'antd/lib/layout';
import Button from 'antd/lib/button'; import Button from 'antd/lib/button';
@ -169,7 +175,7 @@ function HeaderContainer(props: Props): JSX.Element {
<Text strong>UI version:</Text> <Text strong>UI version:</Text>
<Text type='secondary'>{` ${tool.ui.version}`}</Text> <Text type='secondary'>{` ${tool.ui.version}`}</Text>
</p> </p>
<Row type='flex' justify='space-around'> <Row justify='space-around'>
<Col> <Col>
<a href={CHANGELOG_URL} target='_blank' rel='noopener noreferrer'> <a href={CHANGELOG_URL} target='_blank' rel='noopener noreferrer'>
What&apos;s new? What&apos;s new?
@ -212,7 +218,7 @@ function HeaderContainer(props: Props): JSX.Element {
window.open(`${tool.server.host}/admin`, '_blank'); window.open(`${tool.server.host}/admin`, '_blank');
}} }}
> >
<ContactsOutlined /> <ControlOutlined />
Admin page Admin page
</Menu.Item> </Menu.Item>
)} )}

@ -82,7 +82,7 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
return ( return (
<div className='cvat-player-settings'> <div className='cvat-player-settings'>
<Row type='flex' align='bottom' className='cvat-player-settings-step'> <Row align='bottom' className='cvat-player-settings-step'>
<Col> <Col>
<Text className='cvat-text-color'> Player step </Text> <Text className='cvat-text-color'> Player step </Text>
<InputNumber <InputNumber
@ -105,7 +105,7 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
</Text> </Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' align='middle' className='cvat-player-settings-speed'> <Row align='middle' className='cvat-player-settings-speed'>
<Col> <Col>
<Text className='cvat-text-color'> Player speed </Text> <Text className='cvat-text-color'> Player speed </Text>
<Select <Select
@ -135,7 +135,7 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
</Select> </Select>
</Col> </Col>
</Row> </Row>
<Row type='flex' className='cvat-player-settings-canvas-background'> <Row className='cvat-player-settings-canvas-background'>
<Col> <Col>
<Popover <Popover
content={( content={(
@ -152,7 +152,7 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
</Popover> </Popover>
</Col> </Col>
</Row> </Row>
<Row type='flex'> <Row>
<Col> <Col>
<Checkbox <Checkbox
className='cvat-text-color cvat-player-settings-grid' className='cvat-text-color cvat-player-settings-grid'
@ -165,7 +165,7 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
</Checkbox> </Checkbox>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='space-between'> <Row justify='space-between'>
<Col span={8} className='cvat-player-settings-grid-size'> <Col span={8} className='cvat-player-settings-grid-size'>
<Text className='cvat-text-color'> Grid size </Text> <Text className='cvat-text-color'> Grid size </Text>
<InputNumber <InputNumber
@ -223,10 +223,10 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
<Text className='cvat-text-color'>{`${gridOpacity} %`}</Text> <Text className='cvat-text-color'>{`${gridOpacity} %`}</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='start'> <Row justify='start'>
<Col> <Col span={7}>
<Row className='cvat-player-settings-reset-zoom'> <Row className='cvat-player-settings-reset-zoom'>
<Col className='cvat-player-settings-reset-zoom-checkbox'> <Col span={24} className='cvat-player-settings-reset-zoom-checkbox'>
<Checkbox <Checkbox
className='cvat-text-color' className='cvat-text-color'
checked={resetZoom} checked={resetZoom}
@ -237,14 +237,14 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
Reset zoom Reset zoom
</Checkbox> </Checkbox>
</Col> </Col>
<Col> <Col span={24}>
<Text type='secondary'> Fit image after changing frame </Text> <Text type='secondary'> Fit image after changing frame </Text>
</Col> </Col>
</Row> </Row>
</Col> </Col>
<Col offset={5}> <Col span={7} offset={5}>
<Row className='cvat-player-settings-rotate-all'> <Row className='cvat-player-settings-rotate-all'>
<Col className='cvat-player-settings-rotate-all-checkbox'> <Col span={24} className='cvat-player-settings-rotate-all-checkbox'>
<Checkbox <Checkbox
className='cvat-text-color' className='cvat-text-color'
checked={rotateAll} checked={rotateAll}
@ -255,7 +255,7 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
Rotate all images Rotate all images
</Checkbox> </Checkbox>
</Col> </Col>
<Col> <Col span={24}>
<Text type='secondary'> Rotate all images simultaneously </Text> <Text type='secondary'> Rotate all images simultaneously </Text>
</Col> </Col>
</Row> </Row>
@ -264,8 +264,10 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
<Row> <Row>
<Col span={12}> <Col span={12}>
<Row className='cvat-player-settings-brightness'> <Row className='cvat-player-settings-brightness'>
<Col className='cvat-text-color'>Brightness</Col> <Col span={24} className='cvat-text-color'>
<Col> Brightness
</Col>
<Col span={24}>
<Slider <Slider
min={50} min={50}
max={200} max={200}
@ -277,8 +279,10 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
</Col> </Col>
</Row> </Row>
<Row className='cvat-player-settings-contrast'> <Row className='cvat-player-settings-contrast'>
<Col className='cvat-text-color'>Contrast</Col> <Col span={24} className='cvat-text-color'>
<Col> Contrast
</Col>
<Col span={24}>
<Slider <Slider
min={50} min={50}
max={200} max={200}
@ -290,8 +294,10 @@ export default function PlayerSettingsComponent(props: Props): JSX.Element {
</Col> </Col>
</Row> </Row>
<Row className='cvat-player-settings-saturation'> <Row className='cvat-player-settings-saturation'>
<Col className='cvat-text-color'>Saturation</Col> <Col span={24} className='cvat-text-color'>
<Col> Saturation
</Col>
<Col span={24}>
<Slider <Slider
min={0} min={0}
max={300} max={300}

@ -55,6 +55,10 @@
justify-items: start; justify-items: start;
} }
.cvat-player-settings-grid-size-input {
height: fit-content;
}
.cvat-player-settings-grid-color { .cvat-player-settings-grid-color {
> .ant-select { > .ant-select {
width: 150px; width: 150px;
@ -75,7 +79,7 @@
} }
} }
.cvat-player-settings-step > div > span > i { .cvat-player-settings-step > div > span > span[role='img'] {
margin: 0 5px; margin: 0 5px;
font-size: 10px; font-size: 10px;
} }

@ -49,7 +49,7 @@ export default function WorkspaceSettingsComponent(props: Props): JSX.Element {
return ( return (
<div className='cvat-workspace-settings'> <div className='cvat-workspace-settings'>
<Row type='flex'> <Row>
<Col> <Col>
<Checkbox <Checkbox
className='cvat-text-color cvat-workspace-settings-auto-save' className='cvat-text-color cvat-workspace-settings-auto-save'
@ -62,7 +62,7 @@ export default function WorkspaceSettingsComponent(props: Props): JSX.Element {
</Checkbox> </Checkbox>
</Col> </Col>
</Row> </Row>
<Row type='flex'> <Row>
<Col className='cvat-workspace-settings-auto-save-interval'> <Col className='cvat-workspace-settings-auto-save-interval'>
<Text type='secondary'> Auto save every </Text> <Text type='secondary'> Auto save every </Text>
<InputNumber <InputNumber
@ -82,7 +82,7 @@ export default function WorkspaceSettingsComponent(props: Props): JSX.Element {
</Col> </Col>
</Row> </Row>
<Row className='cvat-workspace-settings-show-interpolated'> <Row className='cvat-workspace-settings-show-interpolated'>
<Col> <Col span={24}>
<Checkbox <Checkbox
className='cvat-text-color' className='cvat-text-color'
checked={showAllInterpolationTracks} checked={showAllInterpolationTracks}
@ -93,12 +93,12 @@ export default function WorkspaceSettingsComponent(props: Props): JSX.Element {
Show all interpolation tracks Show all interpolation tracks
</Checkbox> </Checkbox>
</Col> </Col>
<Col> <Col span={24}>
<Text type='secondary'> Show hidden interpolated objects in the side panel </Text> <Text type='secondary'> Show hidden interpolated objects in the side panel </Text>
</Col> </Col>
</Row> </Row>
<Row className='cvat-workspace-settings-show-text-always'> <Row className='cvat-workspace-settings-show-text-always'>
<Col> <Col span={24}>
<Checkbox <Checkbox
className='cvat-text-color' className='cvat-text-color'
checked={showObjectsTextAlways} checked={showObjectsTextAlways}
@ -109,7 +109,7 @@ export default function WorkspaceSettingsComponent(props: Props): JSX.Element {
Always show object details Always show object details
</Checkbox> </Checkbox>
</Col> </Col>
<Col> <Col span={24}>
<Text type='secondary'> <Text type='secondary'>
{' '} {' '}
Show text for an object on the canvas not only when the object is activated Show text for an object on the canvas not only when the object is activated
@ -118,7 +118,7 @@ export default function WorkspaceSettingsComponent(props: Props): JSX.Element {
</Col> </Col>
</Row> </Row>
<Row className='cvat-workspace-settings-autoborders'> <Row className='cvat-workspace-settings-autoborders'>
<Col> <Col span={24}>
<Checkbox <Checkbox
className='cvat-text-color' className='cvat-text-color'
checked={automaticBordering} checked={automaticBordering}
@ -129,7 +129,7 @@ export default function WorkspaceSettingsComponent(props: Props): JSX.Element {
Automatic bordering Automatic bordering
</Checkbox> </Checkbox>
</Col> </Col>
<Col> <Col span={24}>
<Text type='secondary'> <Text type='secondary'>
{' '} {' '}
Enable automatic bordering for polygons and polylines during drawing/editing Enable automatic bordering for polygons and polylines during drawing/editing

@ -10,7 +10,9 @@ import Tooltip from 'antd/lib/tooltip';
import Form, { FormInstance, RuleObject } from 'antd/lib/form'; import Form, { FormInstance, RuleObject } from 'antd/lib/form';
import { Store } from 'antd/lib/form/interface'; import { Store } from 'antd/lib/form/interface';
import { Label, Attribute, validateParsedLabel, idGenerator } from './common'; import {
Label, Attribute, validateParsedLabel, idGenerator,
} from './common';
function validateLabels(_: RuleObject, value: string): Promise<void> { function validateLabels(_: RuleObject, value: string): Promise<void> {
try { try {
@ -80,14 +82,10 @@ export default class RawViewer extends React.PureComponent<Props> {
const textLabels = JSON.stringify(convertedLabels, null, 2); const textLabels = JSON.stringify(convertedLabels, null, 2);
return ( return (
<Form layout='vertical' onFinish={this.handleSubmit} ref={this.formRef}> <Form layout='vertical' onFinish={this.handleSubmit} ref={this.formRef}>
<Form.Item <Form.Item name='labels' initialValue={textLabels} rules={[{ validator: validateLabels }]}>
name='labels'
initialValue={textLabels}
rules={[{ validator: validateLabels }]}
>
<Input.TextArea rows={5} className='cvat-raw-labels-viewer' /> <Input.TextArea rows={5} className='cvat-raw-labels-viewer' />
</Form.Item> </Form.Item>
<Row type='flex' justify='start' align='middle'> <Row justify='start' align='middle'>
<Col> <Col>
<Tooltip title='Save labels and return' mouseLeaveDelay={0}> <Tooltip title='Save labels and return' mouseLeaveDelay={0}>
<Button style={{ width: '150px' }} type='primary' htmlType='submit'> <Button style={{ width: '150px' }} type='primary' htmlType='submit'>

@ -51,7 +51,7 @@ textarea.ant-input.cvat-raw-labels-viewer {
margin-left: 5px; margin-left: 5px;
color: white; color: white;
> i:hover { > span[role='img']:hover {
filter: invert(1); filter: invert(1);
} }
} }
@ -84,7 +84,7 @@ textarea.ant-input.cvat-raw-labels-viewer {
display: contents; display: contents;
} }
.cvat-delete-attribute-button:hover > i { .cvat-delete-attribute-button:hover > span[role='img'] {
color: $danger-icon-color; color: $danger-icon-color;
} }

@ -31,7 +31,7 @@ function LoginPageComponent(props: LoginPageComponentProps & RouteComponentProps
return ( return (
<> <>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col {...sizes}> <Col {...sizes}>
<Title level={2}> Login </Title> <Title level={2}> Login </Title>
<LoginForm <LoginForm
@ -40,7 +40,7 @@ function LoginPageComponent(props: LoginPageComponentProps & RouteComponentProps
onLogin(loginData.username, loginData.password); onLogin(loginData.username, loginData.password);
}} }}
/> />
<Row type='flex' justify='start' align='top'> <Row justify='start' align='top'>
<Col> <Col>
<Text strong> <Text strong>
New to CVAT? Create New to CVAT? Create
@ -49,7 +49,7 @@ function LoginPageComponent(props: LoginPageComponentProps & RouteComponentProps
</Col> </Col>
</Row> </Row>
{renderResetPassword && ( {renderResetPassword && (
<Row type='flex' justify='start' align='top'> <Row justify='start' align='top'>
<Col> <Col>
<Text strong> <Text strong>
<Link to='/auth/password/reset'>Forgot your password?</Link> <Link to='/auth/password/reset'>Forgot your password?</Link>

@ -111,7 +111,9 @@ function DetectorRunner(props: Props): JSX.Element {
> >
{labels.map( {labels.map(
(label: string): JSX.Element => ( (label: string): JSX.Element => (
<Select.Option value={label} key={label}>{label}</Select.Option> <Select.Option value={label} key={label}>
{label}
</Select.Option>
), ),
)} )}
</Select> </Select>
@ -121,7 +123,7 @@ function DetectorRunner(props: Props): JSX.Element {
return ( return (
<div className='cvat-run-model-content'> <div className='cvat-run-model-content'>
<Row type='flex' align='middle'> <Row align='middle'>
<Col span={4}>Model:</Col> <Col span={4}>Model:</Col>
<Col span={20}> <Col span={20}>
<Select <Select
@ -143,7 +145,9 @@ function DetectorRunner(props: Props): JSX.Element {
> >
{models.map( {models.map(
(_model: Model): JSX.Element => ( (_model: Model): JSX.Element => (
<Select.Option value={_model.id} key={_model.id}>{_model.name}</Select.Option> <Select.Option value={_model.id} key={_model.id}>
{_model.name}
</Select.Option>
), ),
)} )}
</Select> </Select>
@ -155,7 +159,7 @@ function DetectorRunner(props: Props): JSX.Element {
const label = task.labels.filter((_label: any): boolean => _label.name === mapping[modelLabel])[0]; const label = task.labels.filter((_label: any): boolean => _label.name === mapping[modelLabel])[0];
const color = label ? label.color : consts.NEW_LABEL_COLOR; const color = label ? label.color : consts.NEW_LABEL_COLOR;
return ( return (
<Row key={modelLabel} type='flex' justify='start' align='middle'> <Row key={modelLabel} justify='start' align='middle'>
<Col span={10}> <Col span={10}>
<Tag color={color}>{modelLabel}</Tag> <Tag color={color}>{modelLabel}</Tag>
</Col> </Col>
@ -179,22 +183,14 @@ function DetectorRunner(props: Props): JSX.Element {
})} })}
{isDetector && !!taskLabels.length && !!modelLabels.length && ( {isDetector && !!taskLabels.length && !!modelLabels.length && (
<> <>
<Row type='flex' justify='start' align='middle'> <Row justify='start' align='middle'>
<Col span={10}> <Col span={10}>
{renderSelector( {renderSelector(match.model || '', 'Model labels', modelLabels, (modelLabel: string) =>
match.model || '', updateMatch(modelLabel, null))}
'Model labels',
modelLabels,
(modelLabel: string) => updateMatch(modelLabel, null),
)}
</Col> </Col>
<Col span={10} offset={1}> <Col span={10} offset={1}>
{renderSelector( {renderSelector(match.task || '', 'Task labels', taskLabels, (taskLabel: string) =>
match.task || '', updateMatch(null, taskLabel))}
'Task labels',
taskLabels,
(taskLabel: string) => updateMatch(null, taskLabel),
)}
</Col> </Col>
<Col span={1} offset={1}> <Col span={1} offset={1}>
<Tooltip <Tooltip
@ -219,7 +215,7 @@ function DetectorRunner(props: Props): JSX.Element {
)} )}
{isReId && ( {isReId && (
<div> <div>
<Row type='flex' align='middle' justify='start'> <Row align='middle' justify='start'>
<Col> <Col>
<Text>Threshold</Text> <Text>Threshold</Text>
</Col> </Col>
@ -239,7 +235,7 @@ function DetectorRunner(props: Props): JSX.Element {
</Tooltip> </Tooltip>
</Col> </Col>
</Row> </Row>
<Row type='flex' align='middle' justify='start'> <Row align='middle' justify='start'>
<Col> <Col>
<Text>Maximum distance</Text> <Text>Maximum distance</Text>
</Col> </Col>
@ -260,7 +256,7 @@ function DetectorRunner(props: Props): JSX.Element {
</Row> </Row>
</div> </div>
)} )}
<Row type='flex' align='middle' justify='end'> <Row align='middle' justify='end'>
<Col> <Col>
<Button <Button
disabled={!buttonEnabled} disabled={!buttonEnabled}
@ -269,10 +265,12 @@ function DetectorRunner(props: Props): JSX.Element {
runInference( runInference(
task, task,
model, model,
model.type === 'detector' ? { mapping, cleanup } : { model.type === 'detector' ?
threshold, { mapping, cleanup } :
max_distance: distance, {
}, threshold,
max_distance: distance,
},
); );
}} }}
> >

@ -48,7 +48,9 @@ function mapDispatchToProps(dispatch: ThunkDispatch): DispatchToProps {
} }
function ModelRunnerDialog(props: StateToProps & DispatchToProps): JSX.Element { function ModelRunnerDialog(props: StateToProps & DispatchToProps): JSX.Element {
const { reid, detectors, task, visible, runInference, closeDialog } = props; const {
reid, detectors, task, visible, runInference, closeDialog,
} = props;
const models = [...reid, ...detectors]; const models = [...reid, ...detectors];

@ -17,7 +17,7 @@ export default function DeployedModelItem(props: Props): JSX.Element {
const { model } = props; const { model } = props;
return ( return (
<Row className='cvat-models-list-item' type='flex'> <Row className='cvat-models-list-item'>
<Col span={3}> <Col span={3}>
<Tag color='purple'>{model.framework}</Tag> <Tag color='purple'>{model.framework}</Tag>
</Col> </Col>
@ -34,7 +34,9 @@ export default function DeployedModelItem(props: Props): JSX.Element {
<Select showSearch placeholder='Supported labels' style={{ width: '90%' }} value='Supported labels'> <Select showSearch placeholder='Supported labels' style={{ width: '90%' }} value='Supported labels'>
{model.labels.map( {model.labels.map(
(label): JSX.Element => ( (label): JSX.Element => (
<Select.Option key={label}>{label}</Select.Option> <Select.Option value={label} key={label}>
{label}
</Select.Option>
), ),
)} )}
</Select> </Select>

@ -20,9 +20,9 @@ export default function DeployedModelsListComponent(props: Props): JSX.Element {
return ( return (
<> <>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col md={22} lg={18} xl={16} xxl={14} className='cvat-models-list'> <Col md={22} lg={18} xl={16} xxl={14} className='cvat-models-list'>
<Row type='flex' align='middle' style={{ padding: '10px' }}> <Row align='middle' style={{ padding: '10px' }}>
<Col span={3}> <Col span={3}>
<Text strong>Framework</Text> <Text strong>Framework</Text>
</Col> </Col>

@ -13,22 +13,22 @@ import { EmptyTasksIcon as EmptyModelsIcon } from 'icons';
export default function EmptyListComponent(): JSX.Element { export default function EmptyListComponent(): JSX.Element {
return ( return (
<div className='cvat-empty-models-list'> <div className='cvat-empty-models-list'>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col> <Col>
<Icon className='cvat-empty-models-icon' component={EmptyModelsIcon} /> <Icon className='cvat-empty-models-icon' component={EmptyModelsIcon} />
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col> <Col>
<Text strong>No models deployed yet...</Text> <Text strong>No models deployed yet...</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col> <Col>
<Text type='secondary'>To annotate your tasks automatically</Text> <Text type='secondary'>To annotate your tasks automatically</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col> <Col>
<Text type='secondary'>deploy a model with </Text> <Text type='secondary'>deploy a model with </Text>
<a href={`${consts.NUCLIO_GUIDE}`}>nuclio</a> <a href={`${consts.NUCLIO_GUIDE}`}>nuclio</a>

@ -8,7 +8,7 @@ import Text from 'antd/lib/typography/Text';
export default function TopBarComponent(): JSX.Element { export default function TopBarComponent(): JSX.Element {
return ( return (
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col md={22} lg={20} xl={16} xxl={14}> <Col md={22} lg={20} xl={16} xxl={14}>
<Text className='cvat-title'>Models</Text> <Text className='cvat-title'>Models</Text>
</Col> </Col>

@ -47,7 +47,7 @@ export default function DetailsComponent(props: DetailsComponentProps): JSX.Elem
</Title> </Title>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='space-between'> <Row justify='space-between'>
<Col> <Col>
<Text type='secondary'> <Text type='secondary'>
{`Project #${project.id} created`} {`Project #${project.id} created`}

@ -11,6 +11,7 @@ import { Row, Col } from 'antd/lib/grid';
import Result from 'antd/lib/result'; import Result from 'antd/lib/result';
import Button from 'antd/lib/button'; import Button from 'antd/lib/button';
import Title from 'antd/lib/typography/Title'; import Title from 'antd/lib/typography/Title';
import { PlusOutlined } from '@ant-design/icons';
import { CombinedState, Task } from 'reducers/interfaces'; import { CombinedState, Task } from 'reducers/interfaces';
import { getProjectsAsync } from 'actions/projects-actions'; import { getProjectsAsync } from 'actions/projects-actions';
@ -18,7 +19,6 @@ import { cancelInferenceAsync } from 'actions/models-actions';
import TaskItem from 'components/tasks-page/task-item'; import TaskItem from 'components/tasks-page/task-item';
import DetailsComponent from './details'; import DetailsComponent from './details';
import ProjectTopBar from './top-bar'; import ProjectTopBar from './top-bar';
import { PlusOutlined } from '@ant-design/icons';
interface ParamType { interface ParamType {
id: string; id: string;
@ -67,11 +67,11 @@ export default function ProjectPageComponent(): JSX.Element {
} }
return ( return (
<Row type='flex' justify='center' align='top' className='cvat-project-page'> <Row justify='center' align='top' className='cvat-project-page'>
<Col md={22} lg={18} xl={16} xxl={14}> <Col md={22} lg={18} xl={16} xxl={14}>
<ProjectTopBar projectInstance={project} /> <ProjectTopBar projectInstance={project} />
<DetailsComponent project={project} /> <DetailsComponent project={project} />
<Row type='flex' justify='space-between' align='middle' className='cvat-project-page-tasks-bar'> <Row justify='space-between' align='middle' className='cvat-project-page-tasks-bar'>
<Col> <Col>
<Title level={4}>Tasks</Title> <Title level={4}>Tasks</Title>
</Col> </Col>

@ -13,11 +13,11 @@
margin: $grid-unit-size * 2 0; margin: $grid-unit-size * 2 0;
background: $background-color-1; background: $background-color-1;
.ant-row-flex:nth-child(1) { .ant-row:nth-child(1) {
margin-bottom: $grid-unit-size * 2; margin-bottom: $grid-unit-size * 2;
} }
.ant-row-flex:nth-child(2) .ant-col:nth-child(2) > span { .ant-row:nth-child(2) .ant-col:nth-child(2) > span {
margin-right: $grid-unit-size; margin-right: $grid-unit-size;
} }

@ -24,7 +24,7 @@ export default function ProjectTopBar(props: DetailsComponentProps): JSX.Element
const history = useHistory(); const history = useHistory();
return ( return (
<Row className='cvat-task-top-bar' type='flex' justify='space-between' align='middle'> <Row className='cvat-task-top-bar' justify='space-between' align='middle'>
<Col> <Col>
<Button onClick={() => history.push('/projects')} type='link' size='large'> <Button onClick={() => history.push('/projects')} type='link' size='large'>
<LeftOutlined /> <LeftOutlined />

@ -18,30 +18,30 @@ export default function EmptyListComponent(props: Props): JSX.Element {
const { notFound } = props; const { notFound } = props;
return ( return (
<div className='cvat-empty-projects-list'> <div className='cvat-empty-projects-list'>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col> <Col>
<Icon className='cvat-empty-projects-icon' component={EmptyTasksIcon} /> <Icon className='cvat-empty-projects-icon' component={EmptyTasksIcon} />
</Col> </Col>
</Row> </Row>
{notFound ? ( {notFound ? (
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col> <Col>
<Text strong>No results matched your search...</Text> <Text strong>No results matched your search...</Text>
</Col> </Col>
</Row> </Row>
) : ( ) : (
<> <>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col> <Col>
<Text strong>No projects created yet ...</Text> <Text strong>No projects created yet ...</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col> <Col>
<Text type='secondary'>To get started with your annotation project</Text> <Text type='secondary'>To get started with your annotation project</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col> <Col>
<Link to='/projects/create'>create a new one</Link> <Link to='/projects/create'>create a new one</Link>
</Col> </Col>

@ -12,10 +12,10 @@ import Card from 'antd/lib/card';
import Meta from 'antd/lib/card/Meta'; import Meta from 'antd/lib/card/Meta';
import Dropdown from 'antd/lib/dropdown'; import Dropdown from 'antd/lib/dropdown';
import Button from 'antd/lib/button'; import Button from 'antd/lib/button';
import { MoreOutlined } from '@ant-design/icons';
import { CombinedState, Project } from 'reducers/interfaces'; import { CombinedState, Project } from 'reducers/interfaces';
import ProjectActionsMenuComponent from './actions-menu'; import ProjectActionsMenuComponent from './actions-menu';
import { MoreOutlined } from '@ant-design/icons';
interface Props { interface Props {
projectInstance: Project; projectInstance: Project;

@ -38,7 +38,7 @@ export default function ProjectListComponent(): JSX.Element {
return ( return (
<> <>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col className='cvat-projects-list' md={22} lg={18} xl={16} xxl={14}> <Col className='cvat-projects-list' md={22} lg={18} xl={16} xxl={14}>
{projectInstances.map( {projectInstances.map(
(row: any[]): JSX.Element => ( (row: any[]): JSX.Element => (
@ -53,7 +53,7 @@ export default function ProjectListComponent(): JSX.Element {
)} )}
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col md={22} lg={18} xl={16} xxl={14}> <Col md={22} lg={18} xl={16} xxl={14}>
<Pagination <Pagination
className='cvat-projects-pagination' className='cvat-projects-pagination'

@ -47,20 +47,13 @@ export default function ProjectsPageComponent(): JSX.Element {
}, [gettingQuery]); }, [gettingQuery]);
if (projectFetching) { if (projectFetching) {
return ( return <Spin size='large' className='cvat-spinner' />;
<Spin size='large' className='cvat-spinner' />
);
} }
return ( return (
<div className='cvat-projects-page'> <div className='cvat-projects-page'>
<TopBarComponent /> <TopBarComponent />
{ projectsCount {projectsCount ? <ProjectListComponent /> : <EmptyListComponent notFound={anySearchQuery} />}
? (
<ProjectListComponent />
) : (
<EmptyListComponent notFound={anySearchQuery} />
)}
<FeedbackComponent /> <FeedbackComponent />
</div> </div>
); );

@ -15,7 +15,7 @@ export default function TopBarComponent(): JSX.Element {
const history = useHistory(); const history = useHistory();
return ( return (
<Row type='flex' justify='center' align='middle' className='cvat-projects-top-bar'> <Row justify='center' align='middle' className='cvat-projects-top-bar'>
<Col md={11} lg={9} xl={8} xxl={7}> <Col md={11} lg={9} xl={8} xxl={7}>
<Text className='cvat-title'>Projects</Text> <Text className='cvat-title'>Projects</Text>
<SearchField /> <SearchField />

@ -41,7 +41,7 @@ function RegisterPageComponent(props: RegisterPageComponentProps & RouteComponen
return ( return (
<> <>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col {...sizes}> <Col {...sizes}>
<Title level={2}> Create an account </Title> <Title level={2}> Create an account </Title>
<RegisterForm <RegisterForm
@ -59,7 +59,7 @@ function RegisterPageComponent(props: RegisterPageComponentProps & RouteComponen
); );
}} }}
/> />
<Row type='flex' justify='start' align='top'> <Row justify='start' align='top'>
<Col> <Col>
<Text strong> <Text strong>
Already have an account? Already have an account?

@ -47,7 +47,7 @@ function ResetPasswordPagePageComponent(props: ResetPasswordConfirmPageComponent
const { fetching, onResetPasswordConfirm } = props; const { fetching, onResetPasswordConfirm } = props;
return ( return (
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col {...sizes}> <Col {...sizes}>
<Title level={2}> Change password </Title> <Title level={2}> Change password </Title>
<ResetPasswordConfirmForm <ResetPasswordConfirmForm

@ -48,7 +48,7 @@ function ResetPasswordPagePageComponent(props: ResetPasswordPageComponentProps):
const { fetching, onResetPassword } = props; const { fetching, onResetPassword } = props;
return ( return (
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col {...sizes}> <Col {...sizes}>
<Title level={2}> Reset password </Title> <Title level={2}> Reset password </Title>
<ResetPasswordForm <ResetPasswordForm
@ -57,7 +57,7 @@ function ResetPasswordPagePageComponent(props: ResetPasswordPageComponentProps):
onResetPassword(resetPasswordData.email); onResetPassword(resetPasswordData.email);
}} }}
/> />
<Row type='flex' justify='start' align='top'> <Row justify='start' align='top'>
<Col> <Col>
<Text strong> <Text strong>
Go to Go to

@ -16,11 +16,11 @@ import getCore from 'cvat-core-wrapper';
import { getReposData, syncRepos } from 'utils/git-utils'; import { getReposData, syncRepos } from 'utils/git-utils';
import { ActiveInference } from 'reducers/interfaces'; import { ActiveInference } from 'reducers/interfaces';
import AutomaticAnnotationProgress from 'components/tasks-page/automatic-annotation-progress'; import AutomaticAnnotationProgress from 'components/tasks-page/automatic-annotation-progress';
import Descriptions from 'antd/lib/descriptions';
import UserSelector, { User } from './user-selector'; import UserSelector, { User } from './user-selector';
import BugTrackerEditor from './bug-tracker-editor'; import BugTrackerEditor from './bug-tracker-editor';
import LabelsEditorComponent from '../labels-editor/labels-editor'; import LabelsEditorComponent from '../labels-editor/labels-editor';
const core = getCore(); const core = getCore();
interface Props { interface Props {
@ -159,33 +159,11 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
const { overlap, segmentSize, imageQuality } = taskInstance; const { overlap, segmentSize, imageQuality } = taskInstance;
return ( return (
<> <Descriptions className='cvat-task-parameters' bordered layout='vertical' size='small'>
<Row type='flex' justify='start' align='middle'> <Descriptions.Item label='Overlap size'>{overlap}</Descriptions.Item>
<Col span={12}> <Descriptions.Item label='Segment size'>{segmentSize}</Descriptions.Item>
<Text strong className='cvat-text-color'> <Descriptions.Item label='Image quality'>{imageQuality}</Descriptions.Item>
Overlap size </Descriptions>
</Text>
<br />
<Text className='cvat-text-color'>{overlap}</Text>
</Col>
<Col span={12}>
<Text strong className='cvat-text-color'>
Segment size
</Text>
<br />
<Text className='cvat-text-color'>{segmentSize}</Text>
</Col>
</Row>
<Row type='flex' justify='space-between' align='middle'>
<Col span={12}>
<Text strong className='cvat-text-color'>
Image quality
</Text>
<br />
<Text className='cvat-text-color'>{imageQuality}</Text>
</Col>
</Row>
</>
); );
} }
@ -205,7 +183,7 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
); );
return ( return (
<Row className='cvat-task-details-user-block' type='flex' justify='space-between' align='middle'> <Row className='cvat-task-details-user-block' justify='space-between' align='middle'>
<Col span={12}> <Col span={12}>
{owner && ( {owner && (
<Text type='secondary'>{`Task #${taskInstance.id} Created by ${owner} on ${created}`}</Text> <Text type='secondary'>{`Task #${taskInstance.id} Created by ${owner} on ${created}`}</Text>
@ -318,21 +296,21 @@ export default class DetailsComponent extends React.PureComponent<Props, State>
return ( return (
<div className='cvat-task-details'> <div className='cvat-task-details'>
<Row type='flex' justify='start' align='middle'> <Row justify='start' align='middle'>
<Col>{this.renderTaskName()}</Col> <Col>{this.renderTaskName()}</Col>
</Row> </Row>
<Row type='flex' justify='space-between' align='top'> <Row justify='space-between' align='top'>
<Col md={8} lg={7} xl={7} xxl={6}> <Col md={8} lg={7} xl={7} xxl={6}>
<Row type='flex' justify='start' align='middle'> <Row justify='start' align='middle'>
<Col span={24}>{this.renderPreview()}</Col> <Col span={24}>{this.renderPreview()}</Col>
</Row> </Row>
<Row> <Row>
<Col>{this.renderParameters()}</Col> <Col span={24}>{this.renderParameters()}</Col>
</Row> </Row>
</Col> </Col>
<Col md={16} lg={17} xl={17} xxl={18}> <Col md={16} lg={17} xl={17} xxl={18}>
{this.renderDescription()} {this.renderDescription()}
<Row type='flex' justify='space-between' align='middle'> <Row justify='space-between' align='middle'>
<Col span={12}> <Col span={12}>
<BugTrackerEditor <BugTrackerEditor
instance={taskInstance} instance={taskInstance}

@ -17,7 +17,6 @@ import copy from 'copy-to-clipboard';
import getCore from 'cvat-core-wrapper'; import getCore from 'cvat-core-wrapper';
import UserSelector, { User } from './user-selector'; import UserSelector, { User } from './user-selector';
const core = getCore(); const core = getCore();
const baseURL = core.config.backendAPI.slice(0, -7); const baseURL = core.config.backendAPI.slice(0, -7);
@ -223,7 +222,7 @@ function JobListComponent(props: Props & RouteComponentProps): JSX.Element {
return ( return (
<div className='cvat-task-job-list'> <div className='cvat-task-job-list'>
<Row type='flex' justify='space-between' align='middle'> <Row justify='space-between' align='middle'>
<Col> <Col>
<Text className='cvat-text-color cvat-jobs-header'> Jobs </Text> <Text className='cvat-text-color cvat-jobs-header'> Jobs </Text>
<Tooltip trigger='click' title='Copied to clipboard!' mouseLeaveDelay={0}> <Tooltip trigger='click' title='Copied to clipboard!' mouseLeaveDelay={0}>

@ -58,7 +58,7 @@
} }
} }
> .ant-tag > i { > .ant-tag > span[role='img'] {
margin-right: 5px; margin-right: 5px;
} }
} }
@ -84,14 +84,19 @@
.cvat-task-preview-wrapper { .cvat-task-preview-wrapper {
overflow: hidden; overflow: hidden;
margin-bottom: 20px; margin-bottom: 20px;
width: 252px; width: $grid-unit-size * 32;
height: 144px; height: $grid-unit-size * 18;
display: table-cell; display: table-cell;
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
background-color: $background-color-2; background-color: $background-color-2;
} }
.cvat-task-parameters {
margin-top: $grid-unit-size * 2;
width: $grid-unit-size * 32;
}
.cvat-open-bug-tracker-button { .cvat-open-bug-tracker-button {
margin-left: 15px; margin-left: 15px;
} }
@ -112,8 +117,10 @@
} }
.cvat-job-item-status { .cvat-job-item-status {
i { .cvat-job-annotation-color {
margin-left: $grid-unit-size; span {
margin-left: $grid-unit-size;
}
} }
} }

@ -37,7 +37,9 @@ class TaskPageComponent extends React.PureComponent<Props> {
} }
public render(): JSX.Element { public render(): JSX.Element {
const { task, fetching, updating, getTask } = this.props; const {
task, fetching, updating, getTask,
} = this.props;
if (task === null || updating) { if (task === null || updating) {
if (task === null && !fetching) { if (task === null && !fetching) {
@ -60,7 +62,7 @@ class TaskPageComponent extends React.PureComponent<Props> {
return ( return (
<> <>
<Row type='flex' justify='center' align='top' className='cvat-task-details-wrapper'> <Row justify='center' align='top' className='cvat-task-details-wrapper'>
<Col md={22} lg={18} xl={16} xxl={14}> <Col md={22} lg={18} xl={16} xxl={14}>
<TopBarComponent taskInstance={(task as Task).instance} /> <TopBarComponent taskInstance={(task as Task).instance} />
<DetailsContainer task={task as Task} /> <DetailsContainer task={task as Task} />

@ -23,7 +23,7 @@ export default function DetailsComponent(props: DetailsComponentProps): JSX.Elem
const history = useHistory(); const history = useHistory();
return ( return (
<Row className='cvat-task-top-bar' type='flex' justify='space-between' align='middle'> <Row className='cvat-task-top-bar' justify='space-between' align='middle'>
<Col> <Col>
{taskInstance.projectId ? ( {taskInstance.projectId ? (
<Button <Button

@ -27,7 +27,7 @@ export default function AutomaticAnnotationProgress(props: Props): JSX.Element |
<Text strong>Automatic annotation</Text> <Text strong>Automatic annotation</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='space-between'> <Row justify='space-between'>
<Col span={22}> <Col span={22}>
<Progress <Progress
percent={Math.floor(activeInference.progress)} percent={Math.floor(activeInference.progress)}

@ -13,22 +13,22 @@ import { EmptyTasksIcon } from 'icons';
export default function EmptyListComponent(): JSX.Element { export default function EmptyListComponent(): JSX.Element {
return ( return (
<div className='cvat-empty-tasks-list'> <div className='cvat-empty-tasks-list'>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col> <Col>
<Icon className='cvat-empty-tasks-icon' component={EmptyTasksIcon} /> <Icon className='cvat-empty-tasks-icon' component={EmptyTasksIcon} />
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col> <Col>
<Text strong>No tasks created yet ...</Text> <Text strong>No tasks created yet ...</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col> <Col>
<Text type='secondary'>To get started with your annotation project</Text> <Text type='secondary'>To get started with your annotation project</Text>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col> <Col>
<Link to='/tasks/create'>create a new task</Link> <Link to='/tasks/create'>create a new task</Link>
<Text type='secondary'> or try to </Text> <Text type='secondary'> or try to </Text>

@ -104,7 +104,7 @@ class TaskItemComponent extends React.PureComponent<TaskItemProps & RouteCompone
return ( return (
<Col span={6}> <Col span={6}>
<Row type='flex' justify='space-between' align='top'> <Row justify='space-between' align='top'>
<Col> <Col>
<svg height='8' width='8' className={progressColor}> <svg height='8' width='8' className={progressColor}>
<circle cx='4' cy='4' r='4' strokeWidth='0' /> <circle cx='4' cy='4' r='4' strokeWidth='0' />
@ -141,7 +141,7 @@ class TaskItemComponent extends React.PureComponent<TaskItemProps & RouteCompone
return ( return (
<Col span={4}> <Col span={4}>
<Row type='flex' justify='end'> <Row justify='end'>
<Col> <Col>
<Button <Button
className='cvat-item-open-task-button' className='cvat-item-open-task-button'
@ -158,7 +158,7 @@ class TaskItemComponent extends React.PureComponent<TaskItemProps & RouteCompone
</Button> </Button>
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='end'> <Row justify='end'>
<Col className='cvat-item-open-task-actions'> <Col className='cvat-item-open-task-actions'>
<Text className='cvat-text-color'>Actions</Text> <Text className='cvat-text-color'>Actions</Text>
<Dropdown overlay={<ActionsMenuContainer taskInstance={taskInstance} />}> <Dropdown overlay={<ActionsMenuContainer taskInstance={taskInstance} />}>
@ -183,7 +183,7 @@ class TaskItemComponent extends React.PureComponent<TaskItemProps & RouteCompone
} }
return ( return (
<Row className='cvat-tasks-list-item' type='flex' justify='center' align='top' style={{ ...style }}> <Row className='cvat-tasks-list-item' justify='center' align='top' style={{ ...style }}>
{this.renderPreview()} {this.renderPreview()}
{this.renderDescription()} {this.renderDescription()}
{this.renderProgress()} {this.renderProgress()}

@ -17,17 +17,19 @@ export interface ContentListProps {
} }
export default function TaskListComponent(props: ContentListProps): JSX.Element { export default function TaskListComponent(props: ContentListProps): JSX.Element {
const { currentTasksIndexes, numberOfTasks, currentPage, onSwitchPage } = props; const {
currentTasksIndexes, numberOfTasks, currentPage, onSwitchPage,
} = props;
const taskViews = currentTasksIndexes.map((tid, id): JSX.Element => <TaskItem idx={id} taskID={tid} key={tid} />); const taskViews = currentTasksIndexes.map((tid, id): JSX.Element => <TaskItem idx={id} taskID={tid} key={tid} />);
return ( return (
<> <>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col className='cvat-tasks-list' md={22} lg={18} xl={16} xxl={14}> <Col className='cvat-tasks-list' md={22} lg={18} xl={16} xxl={14}>
{taskViews} {taskViews}
</Col> </Col>
</Row> </Row>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col md={22} lg={18} xl={16} xxl={14}> <Col md={22} lg={18} xl={16} xxl={14}>
<Pagination <Pagination
className='cvat-tasks-pagination' className='cvat-tasks-pagination'

@ -22,7 +22,7 @@ export default function TopBarComponent(props: VisibleTopBarProps): JSX.Element
return ( return (
<> <>
<Row type='flex' justify='center' align='middle'> <Row justify='center' align='middle'>
<Col md={11} lg={9} xl={8} xxl={7}> <Col md={11} lg={9} xl={8} xxl={7}>
<Text className='cvat-title'>Tasks</Text> <Text className='cvat-title'>Tasks</Text>
<Input.Search defaultValue={searchValue} onSearch={onSearch} size='large' placeholder='Search' /> <Input.Search defaultValue={searchValue} onSearch={onSearch} size='large' placeholder='Search' />

Loading…
Cancel
Save