// Copyright (C) 2020 Intel Corporation // // SPDX-License-Identifier: MIT import React from 'react'; import { Row, Col } from 'antd/lib/grid'; import Tag from 'antd/lib/tag'; import { CheckCircleOutlined, LoadingOutlined, WarningOutlined } from '@ant-design/icons'; import Modal from 'antd/lib/modal'; import notification from 'antd/lib/notification'; import Text from 'antd/lib/typography/Text'; import Title from 'antd/lib/typography/Title'; import moment from 'moment'; import getCore from 'cvat-core-wrapper'; import { getReposData, syncRepos } from 'utils/git-utils'; import { ActiveInference } from 'reducers/interfaces'; import AutomaticAnnotationProgress from 'components/tasks-page/automatic-annotation-progress'; import Descriptions from 'antd/lib/descriptions'; import UserSelector, { User } from './user-selector'; import BugTrackerEditor from './bug-tracker-editor'; import LabelsEditorComponent from '../labels-editor/labels-editor'; const core = getCore(); interface Props { previewImage: string; taskInstance: any; installedGit: boolean; // change to git repos url activeInference: ActiveInference | null; cancelAutoAnnotation(): void; onTaskUpdate: (taskInstance: any) => void; } interface State { name: string; repository: string; repositoryStatus: string; } export default class DetailsComponent extends React.PureComponent { private mounted: boolean; private previewImageElement: HTMLImageElement; private previewWrapperRef: React.RefObject; constructor(props: Props) { super(props); const { taskInstance } = props; this.mounted = false; this.previewImageElement = new Image(); this.previewWrapperRef = React.createRef(); this.state = { name: taskInstance.name, repository: '', repositoryStatus: '', }; } public componentDidMount(): void { const { taskInstance, previewImage } = this.props; const { previewImageElement, previewWrapperRef } = this; this.mounted = true; previewImageElement.onload = () => { const { height, width } = previewImageElement; if (width > height) { previewImageElement.style.width = '100%'; } else { previewImageElement.style.height = '100%'; } }; previewImageElement.src = previewImage; previewImageElement.alt = 'Preview'; if (previewWrapperRef.current) { previewWrapperRef.current.appendChild(previewImageElement); } getReposData(taskInstance.id) .then((data): void => { if (data !== null && this.mounted) { if (data.status.error) { notification.error({ message: 'Could not receive repository status', description: data.status.error, }); } else { this.setState({ repositoryStatus: data.status.value, }); } this.setState({ repository: data.url, }); } }) .catch((error): void => { if (this.mounted) { notification.error({ message: 'Could not receive repository status', description: error.toString(), }); } }); } public componentDidUpdate(prevProps: Props): void { const { taskInstance } = this.props; if (prevProps !== this.props) { this.setState({ name: taskInstance.name, }); } } public componentWillUnmount(): void { this.mounted = false; } private renderTaskName(): JSX.Element { const { name } = this.state; const { taskInstance, onTaskUpdate } = this.props; return ( { this.setState({ name: value, }); taskInstance.name = value; onTaskUpdate(taskInstance); }, }} className='cvat-text-color' > {name} ); } private renderPreview(): JSX.Element { const { previewWrapperRef } = this; // Add image on mount after get its width and height to fit it into wrapper return
; } private renderParameters(): JSX.Element { const { taskInstance } = this.props; const { overlap, segmentSize, imageQuality } = taskInstance; return ( {overlap} {segmentSize} {imageQuality} ); } private renderDescription(): JSX.Element { const { taskInstance, onTaskUpdate } = this.props; const owner = taskInstance.owner ? taskInstance.owner.username : null; const assignee = taskInstance.assignee ? taskInstance.assignee : null; const created = moment(taskInstance.createdDate).format('MMMM Do YYYY'); const assigneeSelect = ( { taskInstance.assignee = value; onTaskUpdate(taskInstance); }} /> ); return ( {owner && ( {`Task #${taskInstance.id} Created by ${owner} on ${created}`} )} Assigned to {assigneeSelect} ); } private renderDatasetRepository(): JSX.Element | boolean { const { taskInstance } = this.props; const { repository, repositoryStatus } = this.state; return ( !!repository && ( Dataset Repository
{repository} {repositoryStatus === 'sync' && ( Synchronized )} {repositoryStatus === 'merged' && ( Merged )} {repositoryStatus === 'syncing' && ( Syncing )} {repositoryStatus === '!sync' && ( { this.setState({ repositoryStatus: 'syncing', }); syncRepos(taskInstance.id) .then((): void => { if (this.mounted) { this.setState({ repositoryStatus: 'sync', }); } }) .catch((error): void => { if (this.mounted) { Modal.error({ width: 800, title: 'Could not synchronize the repository', content: error.toString(), }); this.setState({ repositoryStatus: '!sync', }); } }); }} > Synchronize )}
) ); } private renderLabelsEditor(): JSX.Element { const { taskInstance, onTaskUpdate } = this.props; return ( label.toJSON())} onSubmit={(labels: any[]): void => { taskInstance.labels = labels.map((labelData): any => new core.classes.Label(labelData)); onTaskUpdate(taskInstance); }} /> ); } public render(): JSX.Element { const { activeInference, cancelAutoAnnotation, taskInstance, onTaskUpdate, } = this.props; return (
{this.renderTaskName()} {this.renderPreview()} {this.renderParameters()} {this.renderDescription()} { taskInstance.bugTracker = bugTracker; onTaskUpdate(taskInstance); }} /> {this.renderDatasetRepository()} {!taskInstance.projectId && this.renderLabelsEditor()}
); } }