mirror of
https://github.com/wgh136/nysoure.git
synced 2025-09-27 04:17:23 +00:00
Add comment update functionality with UI integration
This commit is contained in:
@@ -934,6 +934,22 @@ class Network {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updateComment(
|
||||||
|
commentID: number,
|
||||||
|
content: string,
|
||||||
|
): Promise<Response<any>> {
|
||||||
|
try {
|
||||||
|
const response = await axios.putForm(
|
||||||
|
`${this.apiBaseUrl}/comments/${commentID}`,
|
||||||
|
{ content },
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
} catch (e: any) {
|
||||||
|
console.error(e);
|
||||||
|
return { success: false, message: e.toString() };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async listComments(
|
async listComments(
|
||||||
resourceID: number,
|
resourceID: number,
|
||||||
page: number = 1,
|
page: number = 1,
|
||||||
|
@@ -1199,7 +1199,7 @@ function Comments({ resourceId }: { resourceId: number }) {
|
|||||||
) : (
|
) : (
|
||||||
<InfoAlert
|
<InfoAlert
|
||||||
message={t("You need to log in to comment")}
|
message={t("You need to log in to comment")}
|
||||||
className={"my-4 alert-dash"}
|
className={"my-4 alert-info"}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<CommentsList
|
<CommentsList
|
||||||
@@ -1270,8 +1270,9 @@ function CommentTile({ comment }: { comment: Comment }) {
|
|||||||
? comment.content
|
? comment.content
|
||||||
: comment.content.substring(0, 300) + "...";
|
: comment.content.substring(0, 300) + "...";
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
return (
|
return (
|
||||||
<div className={"card card-border border-base-300 p-2 my-3"}>
|
<div className={"card bg-base-100 p-2 my-3 shadow-xs"}>
|
||||||
<div className={"flex flex-row items-center my-1 mx-1"}>
|
<div className={"flex flex-row items-center my-1 mx-1"}>
|
||||||
<div
|
<div
|
||||||
className="avatar cursor-pointer"
|
className="avatar cursor-pointer"
|
||||||
@@ -1289,9 +1290,9 @@ function CommentTile({ comment }: { comment: Comment }) {
|
|||||||
{comment.user.username}
|
{comment.user.username}
|
||||||
</div>
|
</div>
|
||||||
<div className={"grow"}></div>
|
<div className={"grow"}></div>
|
||||||
<div className={"text-sm text-gray-500"}>
|
<Badge className={"badge-soft badge-primary badge-sm"}>
|
||||||
{new Date(comment.created_at).toLocaleString()}
|
{new Date(comment.created_at).toLocaleString()}
|
||||||
</div>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
<div className={"text-sm p-2 whitespace-pre-wrap"}>
|
<div className={"text-sm p-2 whitespace-pre-wrap"}>
|
||||||
{displayContent}
|
{displayContent}
|
||||||
@@ -1308,6 +1309,11 @@ function CommentTile({ comment }: { comment: Comment }) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{app.user?.id === comment.user.id && (
|
||||||
|
<div className={"flex flex-row-reverse"}>
|
||||||
|
<EditCommentDialog comment={comment} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1380,3 +1386,74 @@ function DeleteFileDialog({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function EditCommentDialog({
|
||||||
|
comment,
|
||||||
|
}: {
|
||||||
|
comment: Comment;
|
||||||
|
}) {
|
||||||
|
const [isLoading, setLoading] = useState(false);
|
||||||
|
const [content, setContent] = useState(comment.content);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const reload = useContext(context);
|
||||||
|
|
||||||
|
const handleUpdate = async () => {
|
||||||
|
if (isLoading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setLoading(true);
|
||||||
|
const res = await network.updateComment(comment.id, content);
|
||||||
|
const dialog = document.getElementById(
|
||||||
|
`edit_comment_dialog_${comment.id}`,
|
||||||
|
) as HTMLDialogElement;
|
||||||
|
dialog.close();
|
||||||
|
if (res.success) {
|
||||||
|
showToast({
|
||||||
|
message: t("Comment updated successfully"),
|
||||||
|
type: "success",
|
||||||
|
});
|
||||||
|
reload();
|
||||||
|
} else {
|
||||||
|
showToast({ message: res.message, type: "error" });
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
className={"btn btn-sm btn-ghost ml-1"}
|
||||||
|
onClick={() => {
|
||||||
|
const dialog = document.getElementById(
|
||||||
|
`edit_comment_dialog_${comment.id}`,
|
||||||
|
) as HTMLDialogElement;
|
||||||
|
dialog.showModal();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MdOutlineEdit size={16} className={"inline-block"} />
|
||||||
|
{t("Edit")}
|
||||||
|
</button>
|
||||||
|
<dialog id={`edit_comment_dialog_${comment.id}`} className="modal">
|
||||||
|
<div className="modal-box">
|
||||||
|
<h3 className="font-bold text-lg">{t("Edit Comment")}</h3>
|
||||||
|
<TextArea
|
||||||
|
label={t("Content")}
|
||||||
|
value={content}
|
||||||
|
onChange={(e) => setContent(e.target.value)}
|
||||||
|
/>
|
||||||
|
<div className="modal-action">
|
||||||
|
<form method="dialog">
|
||||||
|
<button className="btn btn-ghost">{t("Close")}</button>
|
||||||
|
</form>
|
||||||
|
<button className="btn btn-primary" onClick={handleUpdate}>
|
||||||
|
{isLoading ? (
|
||||||
|
<span className={"loading loading-spinner loading-sm"}></span>
|
||||||
|
) : null}
|
||||||
|
{t("Update")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@@ -14,6 +14,7 @@ func AddCommentRoutes(router fiber.Router) {
|
|||||||
api.Post("/:resourceID", createComment)
|
api.Post("/:resourceID", createComment)
|
||||||
api.Get("/:resourceID", listComments)
|
api.Get("/:resourceID", listComments)
|
||||||
api.Get("/user/:username", listCommentsWithUser)
|
api.Get("/user/:username", listCommentsWithUser)
|
||||||
|
api.Put("/:commentID", updateComment)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createComment(c fiber.Ctx) error {
|
func createComment(c fiber.Ctx) error {
|
||||||
@@ -89,3 +90,28 @@ func listCommentsWithUser(c fiber.Ctx) error {
|
|||||||
Message: "Comments retrieved successfully",
|
Message: "Comments retrieved successfully",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateComment(c fiber.Ctx) error {
|
||||||
|
userID, ok := c.Locals("uid").(uint)
|
||||||
|
if !ok {
|
||||||
|
return model.NewRequestError("You must be logged in to update comment")
|
||||||
|
}
|
||||||
|
commentIDStr := c.Params("commentID")
|
||||||
|
commentID, err := strconv.Atoi(commentIDStr)
|
||||||
|
if err != nil {
|
||||||
|
return model.NewRequestError("Invalid comment ID")
|
||||||
|
}
|
||||||
|
content := c.FormValue("content")
|
||||||
|
if content == "" {
|
||||||
|
return model.NewRequestError("Content cannot be empty")
|
||||||
|
}
|
||||||
|
comment, err := service.UpdateComment(uint(commentID), userID, content)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return c.JSON(model.Response[model.CommentView]{
|
||||||
|
Success: true,
|
||||||
|
Data: *comment,
|
||||||
|
Message: "Comment updated successfully",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@@ -70,3 +70,16 @@ func GetCommentByID(commentID uint) (*model.Comment, error) {
|
|||||||
}
|
}
|
||||||
return &comment, nil
|
return &comment, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UpdateCommentContent(commentID uint, content string) (*model.Comment, error) {
|
||||||
|
var comment model.Comment
|
||||||
|
if err := db.First(&comment, commentID).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
comment.Content = content
|
||||||
|
if err := db.Save(&comment).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
db.Preload("User").First(&comment, commentID)
|
||||||
|
return &comment, nil
|
||||||
|
}
|
||||||
|
@@ -69,3 +69,18 @@ func ListCommentsWithUser(username string, page int) ([]model.CommentWithResourc
|
|||||||
}
|
}
|
||||||
return res, totalPages, nil
|
return res, totalPages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UpdateComment(commentID, userID uint, content string) (*model.CommentView, error) {
|
||||||
|
comment, err := dao.GetCommentByID(commentID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, model.NewNotFoundError("Comment not found")
|
||||||
|
}
|
||||||
|
if comment.UserID != userID {
|
||||||
|
return nil, model.NewRequestError("You can only update your own comments")
|
||||||
|
}
|
||||||
|
updated, err := dao.UpdateCommentContent(commentID, content)
|
||||||
|
if err != nil {
|
||||||
|
return nil, model.NewInternalServerError("Error updating comment")
|
||||||
|
}
|
||||||
|
return updated.ToView(), nil
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user