feat: improve the tdk of reply (#506)

* feat: improve the tdk of reply

* Update ReplyBox.js

* Update NodeBox.js

* Update SingleReplyBox.js

Co-authored-by: Yang Luo <hsluoyz@qq.com>
This commit is contained in:
Nekotoxin 2022-05-05 20:07:20 +08:00 committed by GitHub
parent 4b364edd87
commit 89fe3d423a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 124 additions and 13 deletions

View File

@ -19,6 +19,7 @@ import (
"strconv"
"github.com/casbin/casnode/object"
"github.com/casbin/casnode/service"
"github.com/casbin/casnode/util"
)
@ -152,6 +153,8 @@ func (c *ApiController) AddReply() {
panic(err)
}
reply.Tags = service.Finalword(reply.Content)
previousReply := object.GetReplyByContentAndAuthor(reply.Content, reply.Author)
if previousReply != nil {
c.ResponseError("You have same reply before.")

View File

@ -23,18 +23,19 @@ import (
)
type Reply struct {
Id int `xorm:"int notnull pk autoincr" json:"id"`
Author string `xorm:"varchar(100) index" json:"author"`
TopicId int `xorm:"int index" json:"topicId"`
ParentId int `xorm:"int" json:"parentId"`
CreatedTime string `xorm:"varchar(40)" json:"createdTime"`
Deleted bool `xorm:"bool" json:"deleted"`
IsHidden bool `xorm:"bool" json:"isHidden"`
ThanksNum int `xorm:"int" json:"thanksNum"`
EditorType string `xorm:"varchar(40)" json:"editorType"`
Content string `xorm:"mediumtext" json:"content"`
Ip string `xorm:"varchar(100)" json:"ip"`
State string `xorm:"varchar(100)" json:"state"`
Id int `xorm:"int notnull pk autoincr" json:"id"`
Author string `xorm:"varchar(100) index" json:"author"`
TopicId int `xorm:"int index" json:"topicId"`
ParentId int `xorm:"int" json:"parentId"`
Tags []string `xorm:"varchar(200)" json:"tags"`
CreatedTime string `xorm:"varchar(40)" json:"createdTime"`
Deleted bool `xorm:"bool" json:"deleted"`
IsHidden bool `xorm:"bool" json:"isHidden"`
ThanksNum int `xorm:"int" json:"thanksNum"`
EditorType string `xorm:"varchar(40)" json:"editorType"`
Content string `xorm:"mediumtext" json:"content"`
Ip string `xorm:"varchar(100)" json:"ip"`
State string `xorm:"varchar(100)" json:"state"`
}
var enableNestedReply, _ = beego.AppConfig.Bool("enableNestedReply")

View File

@ -45,6 +45,7 @@ import AuthCallback from "./AuthCallback";
import SilentSignin from "./SilentSignin";
import SignoutBox from "./main/SignoutBox";
import TopicBox from "./main/TopicBox";
import SingleReplyBox from "./main/SingleReplyBox";
import MemberBox from "./main/MemberBox";
import AllCreatedTopicsBox from "./main/AllCreatedTopicsBox";
import NewBox from "./main/NewBox";
@ -207,6 +208,12 @@ class App extends Component {
<TopicBox account={this.state.account} getNodeBackground={this.getNodeBackground} refreshFavorites={this.getFavoriteNum.bind(this)} refreshAccount={this.getAccount.bind(this)} />
</div>
</Route>
<Route exact path="/r/:replyId">
<div id={pcBrowser ? "Main" : ""}>
{pcBrowser ? <div className="sep20" /> : null}
<SingleReplyBox />
</div>
</Route>
<Route exact path="/member/:memberId">
<div id={pcBrowser ? "Main" : ""}>
<MemberBox account={this.state.account} refreshFavorites={this.getFavoriteNum.bind(this)} />

View File

@ -596,7 +596,8 @@ class NodeBox extends React.Component {
<div id={pcBrowser ? "Main" : ""}>
<Helmet>
<title>{`${this.state.nodeInfo.name} - ${Setting.getForumName()}`}</title>
<meta name="keywords" content={`${this.state.nodeInfo.name}, ${Setting.getForumName()}`} />
<meta name="keywords" content={`${this.state.nodeInfo.id},${this.state.nodeInfo.name}`} />
<meta name="description" content={this.state.nodeInfo.desc} />
</Helmet>
{pcBrowser ? <div className="sep20" /> : null}
{this.renderNode()}

View File

@ -298,6 +298,7 @@ class ReplyBox extends React.Component {
</div>
<div style={{ marginLeft: isChild ? "48px" : "60px" }}>
<div className="fr">
<Link to={`/r/${reply.id}`} style={{cursor: "default", textDecoration: "none"}} />
{this.props.account !== null && this.props.account !== undefined && this.props.account.id !== reply?.author ? (
reply?.thanksStatus === false ? (
<div id={`thank_area__${reply.id}`} className="thank_area" style={{ marginRight: "10px" }}>

View File

@ -0,0 +1,98 @@
// Copyright 2022 The casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import React from "react";
import * as Setting from "../Setting";
import * as ReplyBackend from "../backend/ReplyBackend";
import * as TopicBackend from "../backend/TopicBackend";
import { withRouter } from "react-router-dom";
import Avatar from "../Avatar";
import ReactMarkdown from "react-markdown";
import UserLink from "../UserLink";
import { Helmet } from "react-helmet";
class SingleReplyBox extends React.Component {
constructor(props) {
super(props);
this.state = {
classes: props,
reply: null,
topic: null,
};
}
componentDidMount() {
this.getReply(this.props.match.params.replyId);
}
getReply(replyId) {
ReplyBackend.getReplyWithDetails(replyId).then((res) => {
this.setState({
reply: res,
});
this.getTopic(res.topicId);
});
}
getTopic(topicId) {
TopicBackend.getTopic(topicId).then((res) => {
this.setState({
topic: res,
});
});
}
renderSingleReplyBox(reply) {
return (
<div id={`r_${reply.id}`}>
<div style={{ width: "48px", float: "left" }}>
<Avatar username={reply.author} avatar={reply.avatar} />
</div>
<div style={{ marginLeft: "60px" }}>
<strong>
<UserLink username={reply.author} classNameText={"dark"} />
</strong>
<div className={`reply_content ${this.state.topic?.nodeId}`}>
{reply.delete ? "" : <ReactMarkdown escapeHtml={false} renderers={{ image: this.renderImage, link: this.renderLink }} source={Setting.getFormattedContent(reply?.content, true)} />}
</div>
</div>
</div>
);
}
render() {
if (this.state.reply === null) {
return null;
}
if (this.state.topic === null) {
return null;
}
return (
<div>
<Helmet>
<title>{`${this.state.reply?.content} - ${this.state.reply?.author}`}</title>
<meta name="keywords" content={this.state.reply?.tags.join(",")} />
<meta name="description" content={`${this.state.topic?.title}`} />
</Helmet>
<div className={`box ${this.state.topic?.nodeId}`}>
<div id={`r_${this.state.reply?.id}`} className={`cell ${this.state.topic?.nodeId}`}>
{this.renderSingleReplyBox(this.state.reply)}
</div>
</div>
</div>
);
}
}
export default withRouter(SingleReplyBox);