// Copyright (C) 2020 Intel Corporation // // SPDX-License-Identifier: MIT import React from 'react'; import { Row, Col } from 'antd/lib/grid'; import Icon from 'antd/lib/icon'; import Input from 'antd/lib/input'; import Checkbox from 'antd/lib/checkbox'; import Tooltip from 'antd/lib/tooltip'; import Form, { FormComponentProps } from 'antd/lib/form/Form'; import Text from 'antd/lib/typography/Text'; import patterns from 'utils/validation-patterns'; export interface AdvancedConfiguration { bugTracker?: string; zOrder: boolean; imageQuality?: number; overlapSize?: number; segmentSize?: number; startFrame?: number; stopFrame?: number; frameFilter?: string; lfs: boolean; repository?: string; useZipChunks: boolean; dataChunkSize?: number; useCache: boolean; } type Props = FormComponentProps & { onSubmit(values: AdvancedConfiguration): void; installedGit: boolean; }; function isPositiveInteger(_: any, value: any, callback: any): void { if (!value) { callback(); return; } const intValue = +value; if (Number.isNaN(intValue) || !Number.isInteger(intValue) || intValue < 1) { callback('Value must be a positive integer'); } callback(); } function isNonNegativeInteger(_: any, value: any, callback: any): void { if (!value) { callback(); return; } const intValue = +value; if (Number.isNaN(intValue) || intValue < 0) { callback('Value must be a non negative integer'); } callback(); } function isIntegerRange(min: number, max: number, _: any, value: any, callback: any): void { if (!value) { callback(); return; } const intValue = +value; if (Number.isNaN(intValue) || !Number.isInteger(intValue) || intValue < min || intValue > max) { callback(`Value must be an integer [${min}, ${max}]`); } callback(); } class AdvancedConfigurationForm extends React.PureComponent { public submit(): Promise { return new Promise((resolve, reject) => { const { form, onSubmit } = this.props; form.validateFields((error, values): void => { if (!error) { const filteredValues = { ...values }; delete filteredValues.frameStep; if (values.overlapSize && +values.segmentSize <= +values.overlapSize) { reject(new Error('Segment size must be more than overlap size')); } if ( typeof values.startFrame !== 'undefined' && typeof values.stopFrame !== 'undefined' && +values.stopFrame < +values.startFrame ) { reject(new Error('Stop frame must be more or equal start frame')); } onSubmit({ ...values, frameFilter: values.frameStep ? `step=${values.frameStep}` : undefined, }); resolve(); } else { reject(); } }); }); } public resetFields(): void { const { form } = this.props; form.resetFields(); } private renderZOrder(): JSX.Element { const { form } = this.props; return ( {form.getFieldDecorator('zOrder', { initialValue: false, valuePropName: 'checked', })( Z-order , )} ); } private renderImageQuality(): JSX.Element { const { form } = this.props; return ( Image quality}> {form.getFieldDecorator('imageQuality', { initialValue: 70, rules: [ { required: true, message: 'The field is required.', }, { validator: isIntegerRange.bind(null, 5, 100), }, ], })(} />)} ); } private renderOverlap(): JSX.Element { const { form } = this.props; return ( Overlap size}> {form.getFieldDecorator('overlapSize', { rules: [ { validator: isNonNegativeInteger, }, ], })()} ); } private renderSegmentSize(): JSX.Element { const { form } = this.props; return ( Segment size}> {form.getFieldDecorator('segmentSize', { rules: [ { validator: isPositiveInteger, }, ], })()} ); } private renderStartFrame(): JSX.Element { const { form } = this.props; return ( Start frame}> {form.getFieldDecorator('startFrame', { rules: [ { validator: isNonNegativeInteger, }, ], })()} ); } private renderStopFrame(): JSX.Element { const { form } = this.props; return ( Stop frame}> {form.getFieldDecorator('stopFrame', { rules: [ { validator: isNonNegativeInteger, }, ], })()} ); } private renderFrameStep(): JSX.Element { const { form } = this.props; return ( Frame step}> {form.getFieldDecorator('frameStep', { rules: [ { validator: isPositiveInteger, }, ], })()} ); } private renderGitLFSBox(): JSX.Element { const { form } = this.props; return ( {form.getFieldDecorator('lfs', { valuePropName: 'checked', initialValue: false, })( Use LFS (Large File Support): , )} ); } private renderGitRepositoryURL(): JSX.Element { const { form } = this.props; return ( Dataset repository URL} extra='Attach a repository to store annotations there' > {form.getFieldDecorator('repository', { rules: [ { validator: (_, value, callback): void => { if (!value) { callback(); } else { const [url, path] = value.split(/\s+/); if (!patterns.validateURL.pattern.test(url)) { callback('Git URL is not a valid'); } if (path && !patterns.validatePath.pattern.test(path)) { callback('Git path is not a valid'); } callback(); } }, }, ], })( , )} ); } private renderGit(): JSX.Element { return ( <> {this.renderGitRepositoryURL()} {this.renderGitLFSBox()} ); } private renderBugTracker(): JSX.Element { const { form } = this.props; return ( Issue tracker} extra='Attach issue tracker where the task is described' > {form.getFieldDecorator('bugTracker', { rules: [ { validator: (_, value, callback): void => { if (value && !patterns.validateURL.pattern.test(value)) { callback('Issue tracker must be URL'); } else { callback(); } }, }, ], })()} ); } private renderUzeZipChunks(): JSX.Element { const { form } = this.props; return ( {form.getFieldDecorator('useZipChunks', { initialValue: true, valuePropName: 'checked', })( Use zip chunks , )} ); } private renderCreateTaskMethod(): JSX.Element { const { form } = this.props; return ( {form.getFieldDecorator('useCache', { initialValue: true, valuePropName: 'checked', })( Use cache , )} ); } private renderChunkSize(): JSX.Element { const { form } = this.props; return ( Chunk size}> Defines a number of frames to be packed in a chunk when send from client to server. Server defines automatically if empty.
Recommended values:
1080p or less: 36
2k or less: 8 - 16
4k or less: 4 - 8
More: 1 - 4 } mouseLeaveDelay={0} > {form.getFieldDecorator('dataChunkSize', { rules: [ { validator: isPositiveInteger, }, ], })()}
); } public render(): JSX.Element { const { installedGit } = this.props; return (
{this.renderZOrder()} {this.renderUzeZipChunks()} {this.renderCreateTaskMethod()} {this.renderImageQuality()} {this.renderOverlap()} {this.renderSegmentSize()} {this.renderStartFrame()} {this.renderStopFrame()} {this.renderFrameStep()} {this.renderChunkSize()} {installedGit ? this.renderGit() : null} {this.renderBugTracker()}
); } } export default Form.create()(AdvancedConfigurationForm);