You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
4.7 KiB
159 lines
4.7 KiB
/** @jsx jsx */
|
|
import { useRef } from 'react';
|
|
import { jsx } from '@emotion/core';
|
|
import { Row, Col, Tooltip, Input, Checkbox, Select } from 'antd';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useUIState, useSetUIState } from '../store/ui';
|
|
import { useSchemaDispatch } from '../store/schema';
|
|
import { schemaType } from '../utils/schema';
|
|
import { SchemaType, SchemaItem, KeyRoute } from '../model';
|
|
import FieldInput from './field-input';
|
|
import AddNode from './add-node';
|
|
import {
|
|
CaretDownIcon,
|
|
CaretRightIcon,
|
|
EditIcon,
|
|
SettingIcon,
|
|
PlusIcon,
|
|
CloseIcon,
|
|
} from '../utils/styles/common';
|
|
|
|
const { Option } = Select;
|
|
|
|
interface SchemaItemProps {
|
|
field: string;
|
|
data: SchemaItem;
|
|
required: boolean;
|
|
keyRoute: KeyRoute;
|
|
children: React.ReactChild | null;
|
|
}
|
|
|
|
function SchemaFormItem({
|
|
field,
|
|
data,
|
|
required,
|
|
keyRoute,
|
|
children,
|
|
}: SchemaItemProps): JSX.Element {
|
|
const fieldRef = useRef<Input>(null);
|
|
|
|
const { t } = useTranslation();
|
|
const schemaDispatch = useSchemaDispatch();
|
|
const setUIState = useSetUIState();
|
|
const uiState = useUIState();
|
|
const key = keyRoute.join('-');
|
|
const visible = uiState[key] !== false;
|
|
|
|
const toggleFormVisible = (): void => {
|
|
setUIState((prev) => ({ ...prev, [key]: !visible }));
|
|
};
|
|
|
|
const toggleRequired = (): void => {
|
|
if (!fieldRef.current) return;
|
|
|
|
const newField = fieldRef.current.state.value;
|
|
const fieldKeyRoute = keyRoute.slice(0, -1).concat(newField);
|
|
|
|
if (required) {
|
|
schemaDispatch({ type: 'REMOVE_REQUIRED', keyRoute: fieldKeyRoute });
|
|
} else {
|
|
schemaDispatch({ type: 'ADD_REQUIRED', keyRoute: fieldKeyRoute });
|
|
}
|
|
};
|
|
|
|
const addChildField = (): void => {
|
|
schemaDispatch({ type: 'ADD_CHILD_FIELD', keyRoute: keyRoute.concat('properties') });
|
|
};
|
|
|
|
const addSiblingField = (): void => {
|
|
schemaDispatch({ type: 'ADD_SIBLING_FIELD', keyRoute });
|
|
};
|
|
|
|
const removeField = (): void => {
|
|
schemaDispatch({ type: 'REMOVE_FIELD', keyRoute });
|
|
};
|
|
|
|
const changeField = (value: string): void => {
|
|
schemaDispatch({ type: 'CHANGE_FIELD', keyRoute, field: value });
|
|
};
|
|
|
|
const changeType = (value: SchemaType): void => {
|
|
schemaDispatch({ type: 'CHANGE_TYPE', keyRoute, fieldType: value });
|
|
};
|
|
|
|
const changeTitle = (e: React.ChangeEvent<HTMLInputElement>): void => {
|
|
schemaDispatch({ type: 'CHANGE_TITLE', keyRoute, title: e.target.value });
|
|
};
|
|
|
|
const changeDesc = (e: React.ChangeEvent<HTMLInputElement>): void => {
|
|
schemaDispatch({ type: 'CHANGE_DESC', keyRoute, desc: e.target.value });
|
|
};
|
|
|
|
return (
|
|
<div css={{ marginTop: '10px' }}>
|
|
<Row align="middle">
|
|
<Col span="8" css={{ paddingLeft: `${keyRoute.length * 10}px` }}>
|
|
<Row align="middle">
|
|
<Col span="2">
|
|
{data.type === 'object' && visible && <CaretDownIcon onClick={toggleFormVisible} />}
|
|
{data.type === 'object' && !visible && <CaretRightIcon onClick={toggleFormVisible} />}
|
|
</Col>
|
|
<Col span="22">
|
|
<FieldInput
|
|
ref={fieldRef}
|
|
value={field}
|
|
changeField={changeField}
|
|
addonAfter={
|
|
<Tooltip placement="top" title={t('required')}>
|
|
<Checkbox checked={required} onChange={toggleRequired} />
|
|
</Tooltip>
|
|
}
|
|
/>
|
|
</Col>
|
|
</Row>
|
|
</Col>
|
|
<Col span="3">
|
|
<Select value={data.type} onChange={changeType}>
|
|
{schemaType.map((type) => (
|
|
<Option key={type} value={type}>
|
|
{type}
|
|
</Option>
|
|
))}
|
|
</Select>
|
|
</Col>
|
|
<Col span="5">
|
|
<Input
|
|
value={data.title}
|
|
onChange={changeTitle}
|
|
placeholder={t('title')}
|
|
addonAfter={<EditIcon />}
|
|
/>
|
|
</Col>
|
|
<Col span="5">
|
|
<Input
|
|
value={data.description}
|
|
onChange={changeDesc}
|
|
placeholder={t('description')}
|
|
addonAfter={<EditIcon />}
|
|
/>
|
|
</Col>
|
|
<Col span="3">
|
|
<Tooltip placement="top" title={t('setting')}>
|
|
<SettingIcon />
|
|
</Tooltip>
|
|
<CloseIcon onClick={removeField} />
|
|
{data.type === 'object' ? (
|
|
<AddNode addChildField={addChildField} addSiblingField={addSiblingField} />
|
|
) : (
|
|
<Tooltip placement="top" title={t('add_sibling_node')}>
|
|
<PlusIcon onClick={addSiblingField} />
|
|
</Tooltip>
|
|
)}
|
|
</Col>
|
|
</Row>
|
|
{visible && children ? <div css={{ marginTop: '10px' }}>{children}</div> : null}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default SchemaFormItem;
|
|
|