mirror of https://github.com/casbin/casnode.git
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:
parent
4b364edd87
commit
89fe3d423a
|
@ -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.")
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)} />
|
||||
|
|
|
@ -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()}
|
||||
|
|
|
@ -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" }}>
|
||||
|
|
|
@ -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);
|
Loading…
Reference in New Issue