Skip to content

Commit

Permalink
feat: able to set about content now
Browse files Browse the repository at this point in the history
  • Loading branch information
songquanpeng committed Nov 5, 2022
1 parent 54306e5 commit 8562c7f
Show file tree
Hide file tree
Showing 9 changed files with 232 additions and 106 deletions.
2 changes: 1 addition & 1 deletion common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ var StartTime = time.Now().Unix() // unit: second
var Version = "v0.0.0"
var SystemName = "项目模板"
var ServerAddress = "http://localhost:3000"
var FooterHTML = ""
var Footer = ""

// Any options with "Secret", "Token" in its key won't be return by GetOptions

Expand Down
13 changes: 12 additions & 1 deletion controller/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func GetStatus(c *gin.Context) {
"github_oauth": common.GitHubOAuthEnabled,
"github_client_id": common.GitHubClientId,
"system_name": common.SystemName,
"footer_html": common.FooterHTML,
"footer_html": common.Footer,
"wechat_qrcode": common.WeChatAccountQRCodeImageURL,
"wechat_login": common.WeChatAuthEnabled,
},
Expand All @@ -38,6 +38,17 @@ func GetNotice(c *gin.Context) {
return
}

func GetAbout(c *gin.Context) {
common.OptionMapRWMutex.RLock()
defer common.OptionMapRWMutex.RUnlock()
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": common.OptionMap["About"],
})
return
}

func SendEmailVerification(c *gin.Context) {
email := c.Query("email")
if err := common.Validate.Var(email, "required,email"); err != nil {
Expand Down
7 changes: 4 additions & 3 deletions model/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ func InitOptionMap() {
common.OptionMap["SMTPAccount"] = ""
common.OptionMap["SMTPToken"] = ""
common.OptionMap["Notice"] = ""
common.OptionMap["FooterHTML"] = common.FooterHTML
common.OptionMap["About"] = ""
common.OptionMap["Footer"] = common.Footer
common.OptionMap["ServerAddress"] = ""
common.OptionMap["GitHubClientId"] = ""
common.OptionMap["GitHubClientSecret"] = ""
Expand Down Expand Up @@ -108,8 +109,8 @@ func updateOptionMap(key string, value string) {
common.GitHubClientId = value
case "GitHubClientSecret":
common.GitHubClientSecret = value
case "FooterHTML":
common.FooterHTML = value
case "Footer":
common.Footer = value
case "WeChatServerAddress":
common.WeChatServerAddress = value
case "WeChatServerToken":
Expand Down
1 change: 1 addition & 0 deletions router/api-router.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ func SetApiRouter(router *gin.Engine) {
{
apiRouter.GET("/status", controller.GetStatus)
apiRouter.GET("/notice", controller.GetNotice)
apiRouter.GET("/about", controller.GetAbout)
apiRouter.GET("/verification", middleware.CriticalRateLimit(), controller.SendEmailVerification)
apiRouter.GET("/reset_password", middleware.CriticalRateLimit(), controller.SendPasswordResetEmail)
apiRouter.GET("/user/reset", controller.SendNewPasswordEmail)
Expand Down
12 changes: 6 additions & 6 deletions web/src/components/Footer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import React, { useEffect, useState } from 'react';
import { Container, Segment } from 'semantic-ui-react';

const Footer = () => {
const [footerHTML, setFooterHTML] = useState('');
const [Footer, setFooter] = useState('');
useEffect(() => {
let savedFooterHTML = localStorage.getItem('footer_html');
if (!savedFooterHTML) savedFooterHTML = '';
setFooterHTML(savedFooterHTML);
let savedFooter = localStorage.getItem('footer_html');
if (!savedFooter) savedFooter = '';
setFooter(savedFooter);
});

return (
<Segment vertical>
<Container textAlign="center">
{footerHTML === '' ? (
{Footer === '' ? (
<div className="custom-footer">
<a
href="https://github.com/songquanpeng/gin-template"
Expand All @@ -33,7 +33,7 @@ const Footer = () => {
) : (
<div
className="custom-footer"
dangerouslySetInnerHTML={{ __html: footerHTML }}
dangerouslySetInnerHTML={{ __html: Footer }}
></div>
)}
</Container>
Expand Down
162 changes: 162 additions & 0 deletions web/src/components/OtherSetting.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import React, { useEffect, useState } from 'react';
import { Button, Form, Grid, Modal } from 'semantic-ui-react';
import { API, showError, showSuccess } from '../helpers';
import { marked } from 'marked';

const OtherSetting = () => {
let [inputs, setInputs] = useState({
Footer: '',
Notice: '',
About: ''
});
let originInputs = {};
let [loading, setLoading] = useState(false);
const [showUpdateModal, setShowUpdateModal] = useState(false);
const [updateData, setUpdateData] = useState({
tag_name: '',
content: '',
});

const getOptions = async () => {
const res = await API.get('/api/option');
const { success, message, data } = res.data;
if (success) {
let newInputs = {};
data.forEach((item) => {
if (item.key in inputs) {
newInputs[item.key] = item.value;
}
});
setInputs(newInputs);
originInputs = newInputs;
} else {
showError(message);
}
};

useEffect(() => {
getOptions().then();
}, []);

const updateOption = async (key, value) => {
setLoading(true);
const res = await API.put('/api/option', {
key,
value
});
const { success, message } = res.data;
if (success) {
setInputs((inputs) => ({ ...inputs, [key]: value }));
} else {
showError(message);
}
setLoading(false);
};

const handleInputChange = async (e, { name, value }) => {
setInputs((inputs) => ({ ...inputs, [name]: value }));
};

const submitNotice = async () => {
await updateOption('Notice', inputs.Notice);
};

const submitFooter = async () => {
await updateOption('Footer', inputs.Footer);
};

const submitAbout = async () => {
await updateOption('About', inputs.About);
};

const openGitHubRelease = () => {
window.location =
'https://github.com/songquanpeng/gin-template/releases/latest';
};

const checkUpdate = async () => {
const res = await API.get(
'https://api.github.com/repos/songquanpeng/gin-template/releases/latest'
);
const { tag_name, body } = res.data;
if (tag_name === process.env.REACT_APP_VERSION) {
showSuccess(`已是最新版本:${tag_name}`);
} else {
setUpdateData({
tag_name: tag_name,
content: marked.parse(body),
});
setShowUpdateModal(true);
}
};

return (
<Grid columns={1}>
<Grid.Column>
<Form loading={loading}>
<Form.Button onClick={checkUpdate}>检查更新</Form.Button>
<Form.Group widths='equal'>
<Form.TextArea
label='公告'
placeholder='在此输入新的公告内容'
value={inputs.Notice}
name='Notice'
onChange={handleInputChange}
style={{ minHeight: 150, fontFamily: 'JetBrains Mono, Consolas' }}
/>
</Form.Group>
<Form.Button onClick={submitNotice}>保存公告</Form.Button>
<Form.Group widths='equal'>
<Form.TextArea
label='关于'
placeholder='在此输入新的关于内容,支持 Markdown & HTML 代码'
value={inputs.About}
name='About'
onChange={handleInputChange}
style={{ minHeight: 150, fontFamily: 'JetBrains Mono, Consolas' }}
/>
</Form.Group>
<Form.Button onClick={submitAbout}>保存关于</Form.Button>
<Form.Group widths='equal'>
<Form.Input
label='页脚'
placeholder='在此输入新的页脚,留空则使用默认页脚,支持 HTML 代码'
value={inputs.Footer}
name='Footer'
onChange={handleInputChange}
/>
</Form.Group>
<Form.Button onClick={submitFooter}>
设置页脚
</Form.Button>
</Form>
</Grid.Column>
<Modal
onClose={() => setShowUpdateModal(false)}
onOpen={() => setShowUpdateModal(true)}
open={showUpdateModal}
>
<Modal.Header>新版本:{updateData.tag_name}</Modal.Header>
<Modal.Content>
<Modal.Description>
<div
dangerouslySetInnerHTML={{ __html: updateData.content }}
></div>
</Modal.Description>
</Modal.Content>
<Modal.Actions>
<Button onClick={() => setShowUpdateModal(false)}>关闭</Button>
<Button
content="详情"
onClick={() => {
setShowUpdateModal(false);
openGitHubRelease();
}}
/>
</Modal.Actions>
</Modal>
</Grid>
);
};

export default OtherSetting;
34 changes: 1 addition & 33 deletions web/src/components/SystemSetting.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const SystemSetting = () => {
SMTPAccount: '',
SMTPToken: '',
ServerAddress: '',
FooterHTML: '',
Footer: '',
WeChatAuthEnabled: '',
WeChatServerAddress: '',
WeChatServerToken: '',
Expand Down Expand Up @@ -76,7 +76,6 @@ const SystemSetting = () => {
name === 'ServerAddress' ||
name === 'GitHubClientId' ||
name === 'GitHubClientSecret' ||
name === 'FooterHTML' ||
name === 'WeChatServerAddress' ||
name === 'WeChatServerToken' ||
name === 'WeChatAccountQRCodeImageURL'
Expand All @@ -87,10 +86,6 @@ const SystemSetting = () => {
}
};

const submitNotice = async () => {
await updateOption('Notice', inputs.Notice);
};

const submitServerAddress = async () => {
let ServerAddress = inputs.ServerAddress;
if (ServerAddress.endsWith('/')) {
Expand Down Expand Up @@ -163,33 +158,6 @@ const SystemSetting = () => {
<Form.Button onClick={submitServerAddress}>
更新服务器地址
</Form.Button>
<Form.Group widths="equal">
<Form.Input
label="页脚 HTML"
placeholder="留空则使用默认页脚"
value={inputs.FooterHTML}
name="FooterHTML"
onChange={handleInputChange}
/>
</Form.Group>
<Form.Button
onClick={() => {
updateOption('FooterHTML', inputs.FooterHTML).then();
}}
>
设置页脚 HTML
</Form.Button>
<Form.Group widths="equal">
<Form.TextArea
label="公告"
placeholder="在此输入新的公告"
value={inputs.Notice}
name="Notice"
onChange={handleInputChange}
style={{ minHeight: 150, fontFamily: 'JetBrains Mono, Consolas' }}
/>
</Form.Group>
<Form.Button onClick={submitNotice}>保存公告</Form.Button>
<Form.Group inline>
<Form.Checkbox
checked={inputs.PasswordLoginEnabled === 'true'}
Expand Down
55 changes: 43 additions & 12 deletions web/src/pages/About/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,47 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { Header, Segment } from 'semantic-ui-react';
import { API, showError } from '../../helpers';
import { marked } from 'marked';

const About = () => {
const [about, setAbout] = useState('');

const displayAbout = async () => {
const res = await API.get('/api/about');
const { success, message, data } = res.data;
if (success) {
let HTMLAbout = marked.parse(data);
localStorage.setItem('about', HTMLAbout);
setAbout(HTMLAbout);
} else {
showError(message);
setAbout('加载关于内容失败...');
}
};

useEffect(() => {
displayAbout().then();
}, []);

return (
<>
<Segment>
{
about === '' ? <>
<Header as='h3'>关于</Header>
<p>可在设置页面设置关于内容,支持 HTML & Markdown</p>
项目仓库地址:
<a href="https://github.com/songquanpeng/gin-template">
https://github.com/songquanpeng/gin-template
</a>
</> : <>
<div dangerouslySetInnerHTML={{ __html: about}}></div>
</>
}
</Segment>
</>
);
};

const About = () => (
<>
<Segment>
<Header as="h3">关于</Header>
GitHub:{' '}
<a href="https://github.com/songquanpeng/gin-template">
https://github.com/songquanpeng/gin-template
</a>
</Segment>
</>
);

export default About;
Loading

0 comments on commit 8562c7f

Please sign in to comment.