You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

280 lines
9.1 KiB
TypeScript

import React from 'react';
import {
Row,
Col,
Modal,
Button,
Select,
} from 'antd';
import Text from 'antd/lib/typography/Text';
import Title from 'antd/lib/typography/Title';
import moment from 'moment';
import LabelsEditorComponent from '../labels-editor/labels-editor';
import getCore from '../../core';
import patterns from '../../utils/validation-patterns';
const core = getCore();
interface Props {
previewImage: string;
taskInstance: any;
installedGit: boolean; // change to git repos url
registeredUsers: any[];
onTaskUpdate: (taskInstance: any) => void;
}
interface State {
name: string;
bugTracker: string;
assignee: any;
}
export default class DetailsComponent extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
const { taskInstance } = props;
this.state = {
name: taskInstance.name,
bugTracker: taskInstance.bugTracker,
assignee: taskInstance.assignee,
};
}
private renderTaskName() {
const { taskInstance } = this.props;
const { name } = this.state;
return (
<Title
level={4}
editable={{
onChange: (value: string) => {
this.setState({
name: value,
});
taskInstance.name = value;
this.props.onTaskUpdate(taskInstance);
},
}}
className='cvat-black-color'
>{name}</Title>
);
}
private renderPreview() {
return (
<div className='cvat-task-preview-wrapper'>
<img alt='Preview' className='cvat-task-preview' src={this.props.previewImage}/>
</div>
);
}
private renderParameters() {
const { taskInstance } = this.props;
const { overlap } = taskInstance;
const { segmentSize } = taskInstance;
const { imageQuality } = taskInstance;
const zOrder = taskInstance.zOrder.toString();
return (
<>
<Row type='flex' justify='start' align='middle'>
<Col span={12}>
<Text strong className='cvat-black-color'> Overlap size </Text>
<br/>
<Text className='cvat-black-color'>{overlap}</Text>
</Col>
<Col span={12}>
<Text strong className='cvat-black-color'> Segment size </Text>
<br/>
<Text className='cvat-black-color'>{segmentSize}</Text>
</Col>
</Row>
<Row type='flex' justify='space-between' align='middle'>
<Col span={12}>
<Text strong className='cvat-black-color'> Image quality </Text>
<br/>
<Text className='cvat-black-color'>{imageQuality}</Text>
</Col>
<Col span={12}>
<Text strong className='cvat-black-color'> Z-order </Text>
<br/>
<Text className='cvat-black-color'>{zOrder}</Text>
</Col>
</Row>
</>
);
}
private renderUsers() {
const { taskInstance } = this.props;
const owner = taskInstance.owner ? taskInstance.owner.username : null;
const assignee = this.state.assignee ? this.state.assignee.username : null;
const created = moment(taskInstance.createdDate).format('MMMM Do YYYY');
const assigneeSelect = (
<Select
value={assignee ? assignee : '\0'}
size='small'
showSearch
className='cvat-task-assignee-selector'
onChange={(value: string) => {
let [userInstance] = this.props.registeredUsers
.filter((user: any) => user.username === value);
if (userInstance === undefined) {
userInstance = null;
}
this.setState({
assignee: userInstance,
});
taskInstance.assignee = userInstance;
this.props.onTaskUpdate(taskInstance);
}}
>
<Select.Option key='-1' value='\0'>{'\0'}</Select.Option>
{ this.props.registeredUsers.map((user) => {
return (
<Select.Option key={user.id} value={user.username}>
{user.username}
</Select.Option>
);
})}
</Select>
);
return (
<Row type='flex' justify='space-between' align='middle'>
<Col span={12}>
{ owner ? <Text type='secondary'>
Created by {owner} on {created}
</Text> : null }
</Col>
<Col span={10}>
<Text type='secondary'>
{'Assigned to'}
{ assigneeSelect }
</Text>
</Col>
</Row>
);
}
private renderBugTracker() {
const { taskInstance } = this.props;
const { bugTracker } = this.state;
const onChangeValue = (value: string) => {
if (value && !patterns.validateURL.pattern.test(value)) {
Modal.error({
title: `Could not update the task ${taskInstance.id}`,
content: 'Issue tracker is expected to be URL',
});
} else {
this.setState({
bugTracker: value,
});
taskInstance.bugTracker = value;
this.props.onTaskUpdate(taskInstance);
}
}
if (bugTracker) {
return (
<Row>
<Col>
<Text strong className='cvat-black-color'> Issue Tracker </Text>
<br/>
<Text editable={{onChange: onChangeValue}}>{bugTracker}</Text>
<Button type='ghost' size='small' onClick={() => {
window.open(bugTracker, '_blank');
}} className='cvat-open-bug-tracker-button'>{'Open the issue'}</Button>
</Col>
</Row>
);
} else {
return (
<Row>
<Col>
<Text strong className='cvat-black-color'> Issue Tracker </Text>
<br/>
<Text editable={{onChange: onChangeValue}}>{'Not specified'}</Text>
</Col>
</Row>
);
}
}
private renderLabelsEditor() {
const { taskInstance } = this.props;
return (
<Row>
<Col>
<LabelsEditorComponent
labels={taskInstance.labels.map(
(label: any) => label.toJSON()
)}
onSubmit={(labels: any[]) => {
taskInstance.labels = labels.map((labelData) => {
return new core.classes.Label(labelData);
});
this.props.onTaskUpdate(taskInstance);
}}
/>
</Col>
</Row>
);
}
public componentDidUpdate(prevProps: Props) {
if (prevProps !== this.props) {
this.setState({
name: this.props.taskInstance.name,
bugTracker: this.props.taskInstance.bugTracker,
assignee: this.props.taskInstance.assignee,
});
}
}
public render() {
return (
<div className='cvat-task-details'>
<Row type='flex' justify='start' align='middle'>
<Col>
{ this.renderTaskName() }
</Col>
</Row>
<Row type='flex' justify='space-between' align='top'>
<Col md={8} lg={7} xl={7} xxl={6}>
<Row type='flex' justify='start' align='middle'>
<Col span={24}>
{ this.renderPreview() }
</Col>
</Row>
<Row>
<Col>
{ this.renderParameters() }
</Col>
</Row>
</Col>
<Col md={16} lg={17} xl={17} xxl={18}>
{ this.renderUsers() }
{ this.renderBugTracker() }
{ this.renderLabelsEditor() }
</Col>
</Row>
</div>
);
}
}