Project form, raw label form

main
Boris Sekachev 5 years ago
parent 87f360aa13
commit ae14894796

@ -18,7 +18,7 @@ $completed-progress-color: #61c200;
$inprogress-progress-color: #1890ff;
$pending-progress-color: #c1c1c1;
$border-color-1: #c3c3c3;
$border-color-2: #d9d9d9;
$border-color-2: rgb(240, 240, 240);
$border-color-3: #242424;
$border-color-hover: #40a9ff;
$background-color-1: white;

@ -3,13 +3,13 @@
// SPDX-License-Identifier: MIT
import React, {
useState, useRef, useEffect, Component,
useState, useRef, useEffect, RefObject,
} from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router';
import { Col, Row } from 'antd/lib/grid';
import Text from 'antd/lib/typography/Text';
import Form, { FormComponentProps, WrappedFormUtils } from '@ant-design/compatible/lib/form/Form';
import Form, { FormInstance } from 'antd/lib/form';
import Button from 'antd/lib/button';
import Input from 'antd/lib/input';
import notification from 'antd/lib/notification';
@ -19,66 +19,57 @@ import { CombinedState } from 'reducers/interfaces';
import LabelsEditor from 'components/labels-editor/labels-editor';
import { createProjectAsync } from 'actions/projects-actions';
type FormRefType = Component<FormComponentProps<any>, any, any> & WrappedFormUtils;
const ProjectNameEditor = Form.create<FormComponentProps>()(
(props: FormComponentProps): JSX.Element => {
const { form } = props;
const { getFieldDecorator } = form;
return (
<Form onSubmit={(e): void => e.preventDefault()}>
<Form.Item hasFeedback label={<span>Name</span>}>
{getFieldDecorator('name', {
rules: [
{
required: true,
message: 'Please, specify a name',
},
],
})(<Input />)}
</Form.Item>
</Form>
);
},
);
const AdvanvedConfigurationForm = Form.create<FormComponentProps>()(
(props: FormComponentProps): JSX.Element => {
const { form } = props;
const { getFieldDecorator } = form;
return (
<Form onSubmit={(e): void => e.preventDefault()}>
<Form.Item
label={<span>Issue tracker</span>}
extra='Attach issue tracker where the project is described'
hasFeedback
>
{getFieldDecorator('bug_tracker', {
rules: [
{
validator: (_, value, callback): void => {
if (value && !patterns.validateURL.pattern.test(value)) {
callback('Issue tracker must be URL');
} else {
callback();
}
},
},
],
})(<Input />)}
</Form.Item>
</Form>
);
},
);
function NameConfigurationForm({ formRef }: { formRef: RefObject<FormInstance> }): JSX.Element {
return (
<Form layout='vertical' ref={formRef}>
<Form.Item
name='name'
hasFeedback
label='Name'
rules={[
{
required: true,
message: 'Please, specify a name',
},
]}
>
<Input />
</Form.Item>
</Form>
);
}
function AdvanvedConfigurationForm({ formRef }: { formRef: RefObject<FormInstance> }): JSX.Element {
return (
<Form layout='vertical' ref={formRef}>
<Form.Item
name='bug_tracker'
label='Issue tracker'
extra='Attach issue tracker where the project is described'
hasFeedback
rules={[
{
validator: (_, value, callback): void => {
if (value && !patterns.validateURL.pattern.test(value)) {
callback('Issue tracker must be URL');
} else {
callback();
}
},
},
]}
>
<Input />
</Form.Item>
</Form>
);
}
export default function CreateProjectContent(): JSX.Element {
const [projectLabels, setProjectLabels] = useState<any[]>([]);
const shouldShowNotification = useRef(false);
const nameFormRef = useRef<FormRefType>(null);
const advancedFormRef = useRef<FormRefType>(null);
const nameFormRef = useRef<FormInstance>(null);
const advancedFormRef = useRef<FormInstance>(null);
const dispatch = useDispatch();
const history = useHistory();
@ -102,28 +93,19 @@ export default function CreateProjectContent(): JSX.Element {
shouldShowNotification.current = true;
}, [newProjectId]);
const onSumbit = (): void => {
const onSumbit = async (): Promise<void> => {
interface Project {
[key: string]: any;
}
const projectData: Project = {};
if (nameFormRef.current !== null) {
nameFormRef.current.validateFields((error, value) => {
if (!error) {
projectData.name = value.name;
}
});
}
if (advancedFormRef.current !== null) {
advancedFormRef.current.validateFields((error, values) => {
if (!error) {
for (const [field, value] of Object.entries(values)) {
projectData[field] = value;
}
}
});
if (nameFormRef.current && advancedFormRef.current) {
const basicValues = await nameFormRef.current.validateFields();
const advancedValues = await advancedFormRef.current.validateFields();
projectData.name = basicValues.name;
for (const [field, value] of Object.entries(advancedValues)) {
projectData[field] = value;
}
}
projectData.labels = projectLabels;
@ -136,7 +118,7 @@ export default function CreateProjectContent(): JSX.Element {
return (
<Row type='flex' justify='start' align='middle' className='cvat-create-project-content'>
<Col span={24}>
<ProjectNameEditor ref={nameFormRef} />
<NameConfigurationForm formRef={nameFormRef} />
</Col>
<Col span={24}>
<Text className='cvat-text-color'>Labels:</Text>
@ -148,7 +130,7 @@ export default function CreateProjectContent(): JSX.Element {
/>
</Col>
<Col span={24}>
<AdvanvedConfigurationForm ref={advancedFormRef} />
<AdvanvedConfigurationForm formRef={advancedFormRef} />
</Col>
<Col span={24}>
<Button type='primary' onClick={onSumbit}>

@ -2,62 +2,64 @@
//
// SPDX-License-Identifier: MIT
import React from 'react';
import React, { RefObject } from 'react';
import { Row, Col } from 'antd/lib/grid';
import Input from 'antd/lib/input';
import Button from 'antd/lib/button';
import Tooltip from 'antd/lib/tooltip';
import Form, { FormComponentProps } from '@ant-design/compatible/lib/form/Form';
import Form, { FormInstance, RuleObject } from 'antd/lib/form';
import { Store } from 'antd/lib/form/interface';
import { Label, Attribute, validateParsedLabel, idGenerator } from './common';
type Props = FormComponentProps & {
labels: Label[];
onSubmit: (labels: Label[]) => void;
};
class RawViewer extends React.PureComponent<Props> {
private validateLabels = (_: any, value: string, callback: any): void => {
try {
const parsed = JSON.parse(value);
if (!Array.isArray(parsed)) {
callback('Field is expected to be a JSON array');
}
const labelNames = parsed.map((label: Label) => label.name);
if (new Set(labelNames).size !== labelNames.length) {
callback('Label names must be unique for the task');
}
function validateLabels(_: RuleObject, value: string): Promise<void> {
try {
const parsed = JSON.parse(value);
if (!Array.isArray(parsed)) {
return Promise.reject(new Error('Field is expected to be a JSON array'));
}
const labelNames = parsed.map((label: Label) => label.name);
if (new Set(labelNames).size !== labelNames.length) {
return Promise.reject(new Error('Label names must be unique for the task'));
}
for (const label of parsed) {
try {
validateParsedLabel(label);
} catch (error) {
callback(error.toString());
}
for (const label of parsed) {
try {
validateParsedLabel(label);
} catch (error) {
return Promise.reject(error);
}
} catch (error) {
callback(error.toString());
}
} catch (error) {
return Promise.reject(error);
}
callback();
};
return Promise.resolve();
}
private handleSubmit = (e: React.FormEvent): void => {
const { form, onSubmit } = this.props;
interface Props {
labels: Label[];
onSubmit: (labels: Label[]) => void;
}
e.preventDefault();
form.validateFields((error, values): void => {
if (!error) {
const parsed = JSON.parse(values.labels);
for (const label of parsed) {
label.id = label.id || idGenerator();
for (const attr of label.attributes) {
attr.id = attr.id || idGenerator();
}
}
onSubmit(parsed);
export default class RawViewer extends React.PureComponent<Props> {
private formRef: RefObject<FormInstance>;
public constructor(props: Props) {
super(props);
this.formRef = React.createRef<FormInstance>();
}
private handleSubmit = (values: Store): void => {
const { onSubmit } = this.props;
const parsed = JSON.parse(values.labels);
for (const label of parsed) {
label.id = label.id || idGenerator();
for (const attr of label.attributes) {
attr.id = attr.id || idGenerator();
}
});
}
onSubmit(parsed);
};
public render(): JSX.Element {
@ -76,19 +78,14 @@ class RawViewer extends React.PureComponent<Props> {
);
const textLabels = JSON.stringify(convertedLabels, null, 2);
const { form } = this.props;
return (
<Form onSubmit={this.handleSubmit}>
<Form.Item>
{form.getFieldDecorator('labels', {
initialValue: textLabels,
rules: [
{
validator: this.validateLabels,
},
],
})(<Input.TextArea rows={5} className='cvat-raw-labels-viewer' />)}
<Form layout='vertical' onFinish={this.handleSubmit} ref={this.formRef}>
<Form.Item
name='labels'
initialValue={textLabels}
rules={[{ validator: validateLabels }]}
>
<Input.TextArea rows={5} className='cvat-raw-labels-viewer' />
</Form.Item>
<Row type='flex' justify='start' align='middle'>
<Col>
@ -104,7 +101,9 @@ class RawViewer extends React.PureComponent<Props> {
danger
style={{ width: '150px' }}
onClick={(): void => {
form.resetFields();
if (this.formRef.current) {
this.formRef.current.resetFields();
}
}}
>
Reset
@ -116,5 +115,3 @@ class RawViewer extends React.PureComponent<Props> {
);
}
}
export default Form.create<Props>()(RawViewer);

Loading…
Cancel
Save