Merge branch 'feat/ui-0.5.0' of git.backyard.segmentfault.com:opensource/answer into feat/ui-0.5.0

This commit is contained in:
haitao(lj) 2022-11-29 19:34:49 +08:00
commit 3ff28969e1
5 changed files with 106 additions and 29 deletions

View File

@ -287,9 +287,9 @@ export interface AdminSettingsSmtp {
from_name: string;
smtp_authentication: boolean;
smtp_host: string;
smtp_password: string;
smtp_password?: string;
smtp_port: number;
smtp_username: string;
smtp_username?: string;
test_email_recipient?: string;
}

View File

@ -76,7 +76,7 @@ const Index: FC<Props> = ({
)}
{objectType === 'question' && (
<div className="mb-4">
{tag.map((item) => {
{tag?.map((item) => {
return (
<Tag
key={item.slug_name}

View File

@ -2,6 +2,8 @@ import { FC } from 'react';
import { Form, Button, Stack } from 'react-bootstrap';
import { useTranslation } from 'react-i18next';
import classnames from 'classnames';
import BrandUpload from '../BrandUpload';
import TimeZonePicker from '../TimeZonePicker';
import type * as Type from '@/common/interface';
@ -51,7 +53,10 @@ export interface UISchema {
| 'url'
| 'week';
empty?: string;
validator?: (value) => Promise<string | true | void> | true | string;
validator?: (
value,
formData?,
) => Promise<string | true | void> | true | string;
textRender?: () => React.ReactElement;
imageType?: Type.UploadType;
acceptType?: string;
@ -141,7 +146,7 @@ const SchemaForm: FC<IProps> = ({
const value = formData[key]?.value;
promises.push({
key,
promise: validator(value),
promise: validator(value, formData),
});
}
});
@ -251,7 +256,10 @@ const SchemaForm: FC<IProps> = ({
uiSchema[key] || {};
if (widget === 'select') {
return (
<Form.Group key={title} controlId={key} className="mb-3">
<Form.Group
key={title}
controlId={key}
className={classnames('mb-3', formData[key].hidden && 'd-none')}>
<Form.Label>{title}</Form.Label>
<Form.Select
aria-label={description}
@ -267,13 +275,18 @@ const SchemaForm: FC<IProps> = ({
<Form.Control.Feedback type="invalid">
{formData[key]?.errorMsg}
</Form.Control.Feedback>
<Form.Text className="text-muted">{description}</Form.Text>
{description && (
<Form.Text className="text-muted">{description}</Form.Text>
)}
</Form.Group>
);
}
if (widget === 'checkbox' || widget === 'radio') {
return (
<Form.Group key={title} className="mb-3" controlId={key}>
<Form.Group
key={title}
className={classnames('mb-3', formData[key].hidden && 'd-none')}
controlId={key}>
<Form.Label>{title}</Form.Label>
<Stack direction="horizontal">
{properties[key].enum?.map((item, index) => {
@ -298,15 +311,19 @@ const SchemaForm: FC<IProps> = ({
<Form.Control.Feedback type="invalid">
{formData[key]?.errorMsg}
</Form.Control.Feedback>
<Form.Text className="text-muted">{description}</Form.Text>
{description && (
<Form.Text className="text-muted">{description}</Form.Text>
)}
</Form.Group>
);
}
if (widget === 'switch') {
console.log(formData[key]?.value, 'switch=====');
return (
<Form.Group key={title} className="mb-3" controlId={key}>
<Form.Group
key={title}
className={classnames('mb-3', formData[key].hidden && 'd-none')}
controlId={key}>
<Form.Label>{title}</Form.Label>
<Form.Check
required
@ -323,13 +340,18 @@ const SchemaForm: FC<IProps> = ({
<Form.Control.Feedback type="invalid">
{formData[key]?.errorMsg}
</Form.Control.Feedback>
<Form.Text className="text-muted">{description}</Form.Text>
{description && (
<Form.Text className="text-muted">{description}</Form.Text>
)}
</Form.Group>
);
}
if (widget === 'timezone') {
return (
<Form.Group key={title} className="mb-3" controlId={key}>
<Form.Group
key={title}
className={classnames('mb-3', formData[key].hidden && 'd-none')}
controlId={key}>
<Form.Label>{title}</Form.Label>
<TimeZonePicker
value={formData[key]?.value}
@ -343,14 +365,19 @@ const SchemaForm: FC<IProps> = ({
<Form.Control.Feedback type="invalid">
{formData[key]?.errorMsg}
</Form.Control.Feedback>
<Form.Text className="text-muted">{description}</Form.Text>
{description && (
<Form.Text className="text-muted">{description}</Form.Text>
)}
</Form.Group>
);
}
if (widget === 'upload') {
return (
<Form.Group key={title} className="mb-3" controlId={key}>
<Form.Group
key={title}
className={classnames('mb-3', formData[key].hidden && 'd-none')}
controlId={key}>
<Form.Label>{title}</Form.Label>
<BrandUpload
type={options.imageType || 'avatar'}
@ -366,14 +393,19 @@ const SchemaForm: FC<IProps> = ({
<Form.Control.Feedback type="invalid">
{formData[key]?.errorMsg}
</Form.Control.Feedback>
<Form.Text className="text-muted">{description}</Form.Text>
{description && (
<Form.Text className="text-muted">{description}</Form.Text>
)}
</Form.Group>
);
}
if (widget === 'textarea') {
return (
<Form.Group controlId={key} key={key} className="mb-3">
<Form.Group
controlId={key}
key={key}
className={classnames('mb-3', formData[key].hidden && 'd-none')}>
<Form.Label>{title}</Form.Label>
<Form.Control
as="textarea"
@ -389,12 +421,17 @@ const SchemaForm: FC<IProps> = ({
{formData[key]?.errorMsg}
</Form.Control.Feedback>
<Form.Text className="text-muted">{description}</Form.Text>
{description && (
<Form.Text className="text-muted">{description}</Form.Text>
)}
</Form.Group>
);
}
return (
<Form.Group controlId={key} key={key} className="mb-3">
<Form.Group
controlId={key}
key={key}
className={classnames('mb-3', formData[key].hidden && 'd-none')}>
<Form.Label>{title}</Form.Label>
<Form.Control
name={key}
@ -409,7 +446,9 @@ const SchemaForm: FC<IProps> = ({
{formData[key]?.errorMsg}
</Form.Control.Feedback>
<Form.Text className="text-muted">{description}</Form.Text>
{description && (
<Form.Text className="text-muted">{description}</Form.Text>
)}
</Form.Group>
);
})}

View File

@ -37,8 +37,8 @@ const Smtp: FC = () => {
type: 'boolean',
title: t('encryption.label'),
description: t('encryption.text'),
enum: ['SSL', ''],
enumNames: ['SSL', ''],
enum: ['SSL', 'None'],
enumNames: ['SSL', 'None'],
},
smtp_port: {
type: 'string',
@ -54,12 +54,10 @@ const Smtp: FC = () => {
smtp_username: {
type: 'string',
title: t('smtp_username.label'),
description: t('smtp_username.text'),
},
smtp_password: {
type: 'string',
title: t('smtp_password.label'),
description: t('smtp_password.text'),
},
test_email_recipient: {
type: 'string',
@ -70,15 +68,35 @@ const Smtp: FC = () => {
};
const uiSchema: UISchema = {
encryption: {
'ui:widget': 'radio',
'ui:widget': 'select',
},
smtp_username: {
'ui:options': {
validator: (value: string, formData) => {
if (formData.smtp_authentication.value) {
if (!value) {
return t('smtp_username.msg');
}
}
return true;
},
},
},
smtp_password: {
'ui:options': {
type: 'password',
validator: (value: string, formData) => {
if (formData.smtp_authentication.value) {
if (!value) {
return t('smtp_password.msg');
}
}
return true;
},
},
},
smtp_authentication: {
'ui:widget': 'radio',
'ui:widget': 'switch',
},
smtp_port: {
'ui:options': {
@ -116,8 +134,12 @@ const Smtp: FC = () => {
encryption: formData.encryption.value,
smtp_port: Number(formData.smtp_port.value),
smtp_authentication: formData.smtp_authentication.value,
smtp_username: formData.smtp_username.value,
smtp_password: formData.smtp_password.value,
...(formData.smtp_authentication.value
? { smtp_username: formData.smtp_username.value }
: {}),
...(formData.smtp_authentication.value
? { smtp_password: formData.smtp_password.value }
: {}),
test_email_recipient: formData.test_email_recipient.value,
};
@ -151,6 +173,22 @@ const Smtp: FC = () => {
setFormData(formState);
}, [setting]);
useEffect(() => {
if (formData.smtp_authentication.value) {
setFormData({
...formData,
smtp_username: { ...formData.smtp_username, hidden: false },
smtp_password: { ...formData.smtp_password, hidden: false },
});
} else {
setFormData({
...formData,
smtp_username: { ...formData.smtp_username, hidden: true },
smtp_password: { ...formData.smtp_password, hidden: true },
});
}
}, [formData.smtp_authentication]);
const handleOnChange = (data) => {
setFormData(data);
};

View File

@ -170,7 +170,7 @@ function diffText(newText: string, oldText: string): string {
return '';
}
if (!oldText) {
if (typeof oldText !== 'string') {
return newText
?.replace(/\n/gi, '<br>')
?.replace(/<iframe/gi, '&lt;iframe')