feat(ui): Add Legal, Write modules

This commit is contained in:
robin 2022-11-11 10:22:00 +08:00
parent 7e30f74d6d
commit ac76c3af0f
8 changed files with 277 additions and 17 deletions

View File

@ -916,6 +916,7 @@ ui:
interface: Interface
smtp: SMTP
branding: Branding
legal: Legal
dashboard:
title: Dashboard
welcome: Welcome to Answer Admin!
@ -1108,10 +1109,20 @@ ui:
smtp_authentication:
label: SMTP Authentication
msg: SMTP authentication cannot be empty.
'yes': 'Yes'
'no': 'No'
"yes": "Yes"
"no": "No"
branding:
page_title: Branding
legal:
page_title: Legal
terms_of_service:
label: Terms of Service
msg: Terms of service cannot be empty.
text: "You can add terms of service content here. If you already have a document hosted elsewhere, provide the full URL here."
privacy_policy:
label: Privacy Policy
msg: Privacy policy cannot be empty.
text: "You can add privacy policy content here. If you already have a document hosted elsewhere, provide the full URL here."
form:
empty: cannot be empty
invalid: is invalid

View File

@ -59,6 +59,8 @@ export const ADMIN_NAV_MENUS = [
{ name: 'interface' },
{ name: 'branding' },
{ name: 'smtp' },
{ name: 'legal' },
{ name: 'write' },
],
},
];

View File

@ -289,6 +289,16 @@ export interface SiteSettings {
interface: AdminSettingsInterface;
}
export interface AdminSettingsLegal {
terms_of_service: string;
privacy_policy: string;
}
export interface AdminSettingsWrite {
recommend_tags: string;
required_tags: string;
}
/**
* @description interface for Activity
*/

View File

@ -916,6 +916,8 @@ ui:
interface: Interface
smtp: SMTP
branding: Branding
legal: Legal
write: Write
dashboard:
title: Dashboard
welcome: Welcome to Answer Admin!
@ -1108,22 +1110,29 @@ ui:
smtp_authentication:
label: SMTP Authentication
msg: SMTP authentication cannot be empty.
'yes': 'Yes'
'no': 'No'
"yes": "Yes"
"no": "No"
branding:
page_title: Branding
logo:
label: Logo
text: The logo image at the top left of your site. Use a wide rectangular image with a height of 56 and an aspect ratio greater than 3:1. If left blank, the site title text will be shown.
mobile_logo:
label: Mobile Logo (optional)
text: The logo used on mobile version of your site. Use a wide rectangular image with a height of 56. If left blank, the image from the “logo” setting will be used.
square_icon:
label: Square Icon
text: Image used as the base for metadata icons. Should ideally be larger than 512x512.
favicon:
label: Favicon (optional)
text: A favicon for your site. To work correctly over a CDN it must be a png. Will be resized to 32x32. If left blank, “square icon” will be used.
legal:
page_title: Legal
terms_of_service:
label: Terms of Service
msg: Terms of service cannot be empty.
text: "You can add terms of service content here. If you already have a document hosted elsewhere, provide the full URL here."
privacy_policy:
label: Privacy Policy
msg: Privacy policy cannot be empty.
text: "You can add privacy policy content here. If you already have a document hosted elsewhere, provide the full URL here."
write:
page_title: Write
recommend_tags:
label: Recommend Tags
msg: Recommend tags cannot be empty.
text: "Please input tag slug above, one tag per line."
required_tags:
label: Required Tags
text: "Every new question must have at least one recommend tag"
form:
empty: cannot be empty
invalid: is invalid

View File

@ -0,0 +1,108 @@
import React, { FC, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { SchemaForm, JSONSchema, initFormData, UISchema } from '@/components';
import type * as Type from '@/common/interface';
// import { useToast } from '@/hooks';
// import { siteInfoStore } from '@/stores';
import { useGeneralSetting } from '@/services';
import '../index.scss';
const Legal: FC = () => {
const { t } = useTranslation('translation', {
keyPrefix: 'admin.legal',
});
// const Toast = useToast();
// const updateSiteInfo = siteInfoStore((state) => state.update);
const { data: setting } = useGeneralSetting();
const schema: JSONSchema = {
title: t('page_title'),
required: ['terms_of_service', 'privacy_policy'],
properties: {
terms_of_service: {
type: 'string',
title: t('terms_of_service.label'),
description: t('terms_of_service.text'),
},
privacy_policy: {
type: 'string',
title: t('privacy_policy.label'),
description: t('privacy_policy.text'),
},
},
};
const uiSchema: UISchema = {
terms_of_service: {
'ui:widget': 'textarea',
'ui:options': {
rows: 10,
},
},
privacy_policy: {
'ui:widget': 'textarea',
'ui:options': {
rows: 10,
},
},
};
const [formData, setFormData] = useState(initFormData(schema));
const onSubmit = (evt) => {
evt.preventDefault();
evt.stopPropagation();
const reqParams: Type.AdminSettingsLegal = {
terms_of_service: formData.terms_of_service.value,
privacy_policy: formData.privacy_policy.value,
};
console.log(reqParams);
// updateGeneralSetting(reqParams)
// .then(() => {
// Toast.onShow({
// msg: t('update', { keyPrefix: 'toast' }),
// variant: 'success',
// });
// updateSiteInfo(reqParams);
// })
// .catch((err) => {
// if (err.isError && err.key) {
// formData[err.key].isInvalid = true;
// formData[err.key].errorMsg = err.value;
// }
// setFormData({ ...formData });
// });
};
useEffect(() => {
if (!setting) {
return;
}
const formMeta = {};
Object.keys(setting).forEach((k) => {
formMeta[k] = { ...formData[k], value: setting[k] };
});
setFormData({ ...formData, ...formMeta });
}, [setting]);
const handleOnChange = (data) => {
setFormData(data);
};
return (
<>
<h3 className="mb-4">{t('page_title')}</h3>
<SchemaForm
schema={schema}
formData={formData}
onSubmit={onSubmit}
uiSchema={uiSchema}
onChange={handleOnChange}
/>
</>
);
};
export default Legal;

View File

@ -0,0 +1,105 @@
import React, { FC, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { SchemaForm, JSONSchema, initFormData, UISchema } from '@/components';
import type * as Type from '@/common/interface';
// import { useToast } from '@/hooks';
// import { siteInfoStore } from '@/stores';
import { useGeneralSetting } from '@/services';
import '../index.scss';
const Legal: FC = () => {
const { t } = useTranslation('translation', {
keyPrefix: 'admin.write',
});
// const Toast = useToast();
// const updateSiteInfo = siteInfoStore((state) => state.update);
const { data: setting } = useGeneralSetting();
const schema: JSONSchema = {
title: t('page_title'),
required: ['terms_of_service', 'privacy_policy'],
properties: {
recommend_tags: {
type: 'string',
title: t('recommend_tags.label'),
description: t('recommend_tags.text'),
},
required_tags: {
type: 'boolean',
title: t('required_tags.label'),
description: t('required_tags.text'),
},
},
};
const uiSchema: UISchema = {
recommend_tags: {
'ui:widget': 'textarea',
'ui:options': {
rows: 5,
},
},
required_tags: {
'ui:widget': 'switch',
},
};
const [formData, setFormData] = useState(initFormData(schema));
const onSubmit = (evt) => {
evt.preventDefault();
evt.stopPropagation();
const reqParams: Type.AdminSettingsWrite = {
recommend_tags: formData.recommend_tags.value,
required_tags: formData.required_tags.value,
};
console.log(reqParams);
// updateGeneralSetting(reqParams)
// .then(() => {
// Toast.onShow({
// msg: t('update', { keyPrefix: 'toast' }),
// variant: 'success',
// });
// updateSiteInfo(reqParams);
// })
// .catch((err) => {
// if (err.isError && err.key) {
// formData[err.key].isInvalid = true;
// formData[err.key].errorMsg = err.value;
// }
// setFormData({ ...formData });
// });
};
useEffect(() => {
if (!setting) {
return;
}
const formMeta = {};
Object.keys(setting).forEach((k) => {
formMeta[k] = { ...formData[k], value: setting[k] };
});
setFormData({ ...formData, ...formMeta });
}, [setting]);
const handleOnChange = (data) => {
setFormData(data);
};
return (
<>
<h3 className="mb-4">{t('page_title')}</h3>
<SchemaForm
schema={schema}
formData={formData}
onSubmit={onSubmit}
uiSchema={uiSchema}
onChange={handleOnChange}
/>
</>
);
};
export default Legal;

View File

@ -8,7 +8,14 @@ import { ADMIN_NAV_MENUS } from '@/common/constants';
import './index.scss';
const formPaths = ['general', 'smtp', 'interface', 'branding'];
const formPaths = [
'general',
'smtp',
'interface',
'branding',
'legal',
'write',
];
const Dashboard: FC = () => {
const { t } = useTranslation('translation', { keyPrefix: 'page_title' });

View File

@ -255,6 +255,14 @@ const routes: RouteNode[] = [
path: 'branding',
page: 'pages/Admin/Branding',
},
{
path: 'legal',
page: 'pages/Admin/Legal',
},
{
path: 'write',
page: 'pages/Admin/Write',
},
],
},
{