From 5a9687f62490ce41f5d007e5a5f35f2993fcb8bc Mon Sep 17 00:00:00 2001 From: Tareq Hasan Date: Sat, 30 Mar 2024 01:51:37 +0600 Subject: [PATCH] feat: added post deletion, editing, comment deletion and dark mode support. --- app/Helpers/Formatting.php | 77 ++++++++++++++ .../Controllers/Admin/CommentController.php | 16 +++ .../Controllers/Admin/FeedbackController.php | 65 ++++++++++++ .../Controllers/Admin/PostsController.php | 49 --------- .../Controllers/Frontend/BoardController.php | 4 +- .../Frontend/CommentController.php | 4 +- .../Controllers/Frontend/PostController.php | 4 + package.json | 4 +- resources/js/Components/CommentBox.tsx | 9 +- resources/js/Components/Comments.tsx | 68 ++++++++++-- resources/js/Components/VoteButton.tsx | 6 +- resources/js/Layouts/FrontendLayout.tsx | 22 ++-- resources/js/Pages/Admin/Boards/Index.tsx | 4 +- resources/js/Pages/Admin/Boards/Show.tsx | 14 +-- .../js/Pages/Admin/Feedbacks/EditFeedback.tsx | 78 ++++++++++++++ resources/js/Pages/Admin/Feedbacks/Index.tsx | 4 +- resources/js/Pages/Admin/Feedbacks/Show.tsx | 100 ++++++++++++++---- resources/js/Pages/Admin/Status.tsx | 2 +- .../js/Pages/Frontend/Board/PostForm.tsx | 4 +- resources/js/Pages/Frontend/Board/Show.tsx | 23 ++-- .../Pages/Frontend/Partials/HomeBoardList.tsx | 4 +- .../Pages/Frontend/Partials/HomeRoadmap.tsx | 17 ++- resources/js/Pages/Frontend/Post.tsx | 19 ++-- resources/js/types/index.d.ts | 1 + resources/views/app.blade.php | 2 +- routes/web.php | 10 +- yarn.lock | 43 +++++++- 27 files changed, 510 insertions(+), 143 deletions(-) create mode 100644 app/Helpers/Formatting.php create mode 100644 app/Http/Controllers/Admin/CommentController.php delete mode 100644 app/Http/Controllers/Admin/PostsController.php create mode 100644 resources/js/Pages/Admin/Feedbacks/EditFeedback.tsx diff --git a/app/Helpers/Formatting.php b/app/Helpers/Formatting.php new file mode 100644 index 0000000..9113d61 --- /dev/null +++ b/app/Helpers/Formatting.php @@ -0,0 +1,77 @@ +$0', $text); + } + + /** + * Replaces double line breaks with paragraph elements. + * + * @param string $text The text to process. + * @param bool $br Whether to add line breaks. + * @return string The processed text with paragraph elements. + */ + public static function wpautop($text, $br = true) + { + if (trim($text) === '') { + return ''; + } + + // Just to make things a little easier, pad the end. + $text = $text . "\n"; + + // Change multiple
's into two line breaks, which will turn into paragraphs. + $text = preg_replace('|\s*|', "\n\n", $text); + + // Add a double line break after hr tags, which are self closing. + $text = preg_replace('!()!', "$1\n\n", $text); + + // Standardize newline characters to "\n". + $text = str_replace(array( "\r\n", "\r" ), "\n", $text); + + // Remove more than two contiguous line breaks. + $text = preg_replace("/\n\n+/", "\n\n", $text); + + // Split up the contents into an array of strings, separated by double line breaks. + $paragraphs = preg_split('/\n\s*\n/', $text, -1, PREG_SPLIT_NO_EMPTY); + + // Reset $text prior to rebuilding. + $text = ''; + + // Rebuild the content as a string, wrapping every bit with a

. + foreach ($paragraphs as $paragraph) { + $text .= '

' . trim($paragraph, "\n") . "

\n"; + } + + // Under certain strange conditions it could create a P of entirely whitespace. + $text = preg_replace('|

\s*

|', '', $text); + + return $text; + } +} diff --git a/app/Http/Controllers/Admin/CommentController.php b/app/Http/Controllers/Admin/CommentController.php new file mode 100644 index 0000000..ecc5bd5 --- /dev/null +++ b/app/Http/Controllers/Admin/CommentController.php @@ -0,0 +1,16 @@ +delete(); + + return response()->json(['message' => 'Comment deleted']); + } +} diff --git a/app/Http/Controllers/Admin/FeedbackController.php b/app/Http/Controllers/Admin/FeedbackController.php index 42bd5c5..942d625 100644 --- a/app/Http/Controllers/Admin/FeedbackController.php +++ b/app/Http/Controllers/Admin/FeedbackController.php @@ -7,6 +7,7 @@ use App\Models\Board; use App\Models\Status; use App\Models\Comment; +use App\Helpers\Formatting; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use App\Notifications\FeedbackStatusChanged; @@ -59,6 +60,9 @@ public function show(Post $post) $boards = Board::select('id', 'name', 'posts', 'slug')->get(); $statuses = Status::select('id', 'name', 'color')->get(); + $post->raw_body = $post->body; + $post->body = Formatting::transformBody($post->body); + return inertia('Admin/Feedbacks/Show', [ 'post' => $post, 'boards' => $boards, @@ -67,6 +71,60 @@ public function show(Post $post) ]); } + public function store(Request $request) + { + $rules = [ + 'title' => 'required', + 'body' => 'required', + 'status_id' => 'required|exists:statuses,id', + 'board_id' => 'required|exists:boards,id', + ]; + + if ($request->has('behalf_id') && $request->behalf_id) { + $rules['behalf_id'] = 'exists:users,id'; + } + + $request->validate($rules); + + $args = [ + 'title' => strip_tags($request->title), + 'body' => strip_tags($request->body), + 'status_id' => $request->status_id, + 'board_id' => $request->board_id, + ]; + + if ($request->behalf_id) { + $args['created_by'] = $request->behalf_id; + $args['by'] = auth()->id(); + } + + $post = Post::create($args); + + if ($post) { + $post->votes()->create([ + 'user_id' => $post->created_by, + 'board_id' => $post->board_id, + ]); + } + + return redirect()->route('admin.feedbacks.show', $post)->with('success', 'Post created successfully'); + } + + public function updateContent(Request $request, Post $post) + { + $request->validate([ + 'title' => 'required', + 'body' => 'required', + ]); + + $post->update([ + 'title' => strip_tags($request->title), + 'body' => strip_tags($request->body), + ]); + + return redirect()->route('admin.feedbacks.show', $post)->with('success', 'Content updated successfully.'); + } + public function update(Request $request, Post $post) { $request->validate([ @@ -113,6 +171,13 @@ private function notify($post) }); } + public function destroy(Post $post) + { + $post->delete(); + + return redirect()->route('admin.feedbacks.index')->with('success', 'Feedback deleted successfully.'); + } + public function addVote(Post $post, Request $request) { $request->validate([ diff --git a/app/Http/Controllers/Admin/PostsController.php b/app/Http/Controllers/Admin/PostsController.php deleted file mode 100644 index 528e655..0000000 --- a/app/Http/Controllers/Admin/PostsController.php +++ /dev/null @@ -1,49 +0,0 @@ - 'required', - 'body' => 'required', - 'status_id' => 'required|exists:statuses,id', - 'board_id' => 'required|exists:boards,id', - ]; - - if ($request->has('behalf_id') && $request->behalf_id) { - $rules['behalf_id'] = 'exists:users,id'; - } - - $request->validate($rules); - - $args = [ - 'title' => $request->title, - 'body' => $request->body, - 'status_id' => $request->status_id, - 'board_id' => $request->board_id, - ]; - - if ($request->behalf_id) { - $args['created_by'] = $request->behalf_id; - $args['by'] = auth()->id(); - } - - $post = Post::create($args); - - if ($post) { - $post->votes()->create([ - 'user_id' => $post->created_by, - 'board_id' => $post->board_id, - ]); - } - - return redirect()->route('admin.feedbacks.show', $post)->with('success', 'Post created successfully'); - } -} diff --git a/app/Http/Controllers/Frontend/BoardController.php b/app/Http/Controllers/Frontend/BoardController.php index 24fa4f2..9a625e8 100644 --- a/app/Http/Controllers/Frontend/BoardController.php +++ b/app/Http/Controllers/Frontend/BoardController.php @@ -69,8 +69,8 @@ public function store(Request $request, Board $board) try { $post = Post::create([ - 'title' => $request->title, - 'body' => $request->body, + 'title' => strip_tags($request->title), + 'body' => strip_tags($request->body), 'board_id' => $board->id, 'status_id' => null, 'created_by' => auth()->user()->id, diff --git a/app/Http/Controllers/Frontend/CommentController.php b/app/Http/Controllers/Frontend/CommentController.php index c5afabb..5041a28 100644 --- a/app/Http/Controllers/Frontend/CommentController.php +++ b/app/Http/Controllers/Frontend/CommentController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\Frontend; +use App\Helpers\Formatting; use App\Models\Post; use App\Models\User; use App\Models\Comment; @@ -29,6 +30,7 @@ public function index(Request $request, Post $post) if (isset($groupedComments[$parentId])) { foreach ($groupedComments[$parentId] as $comment) { $children = $buildCommentTree($comment->id); + $comment->body = Formatting::transformBody($comment->body); $comment->children = $children; $result[] = $comment; } @@ -53,7 +55,7 @@ public function store(Request $request, Post $post) ]); $comment = $post->comments()->create([ - 'body' => $request->body, + 'body' => strip_tags($request->body), 'user_id' => auth()->user()->id, 'parent_id' => $parentId === 0 ? null : $parentId, ]); diff --git a/app/Http/Controllers/Frontend/PostController.php b/app/Http/Controllers/Frontend/PostController.php index 02844c4..f59ce7c 100644 --- a/app/Http/Controllers/Frontend/PostController.php +++ b/app/Http/Controllers/Frontend/PostController.php @@ -2,6 +2,8 @@ namespace App\Http\Controllers\Frontend; +use App\Helpers\Formatting; +use App\Http\Controllers\Admin\FeedbackController; use App\Models\Post; use Illuminate\Http\Request; use App\Http\Controllers\Controller; @@ -15,6 +17,8 @@ public function show(Board $board, $post) $post = Post::where('slug', $post)->withVote()->firstOrFail(); $post->load('creator'); + $post->body = Formatting::transformBody($post->body); + $data = [ 'post' => $post, 'board' => $board, diff --git a/package.json b/package.json index b71ee73..dfffe97 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "dependencies": { "@heroicons/react": "^2.1.1", "@radix-ui/react-popover": "^1.0.7", - "@wedevs/tail-react": "^0.3.3", + "@wedevs/tail-react": "^0.5.0", "classnames": "^2.5.1", "lodash.debounce": "^4.0.8", "react-color": "^2.19.3" @@ -39,4 +39,4 @@ "path": "./node_modules/cz-conventional-changelog" } } -} +} \ No newline at end of file diff --git a/resources/js/Components/CommentBox.tsx b/resources/js/Components/CommentBox.tsx index 1434c73..96e3283 100644 --- a/resources/js/Components/CommentBox.tsx +++ b/resources/js/Components/CommentBox.tsx @@ -94,9 +94,12 @@ const CommentBox = ({ post, parent, onComment }: Props) => { }; return ( -
+ {showButtons && ( -
+
{parent ? (   diff --git a/resources/js/Components/Comments.tsx b/resources/js/Components/Comments.tsx index e59dad3..d48a3f1 100644 --- a/resources/js/Components/Comments.tsx +++ b/resources/js/Components/Comments.tsx @@ -1,9 +1,12 @@ -import { BoardType, CommentType, PageProps, PostType, User } from '@/types'; +import { BoardType, CommentType, PostType, User } from '@/types'; import React, { useEffect, useState } from 'react'; import { formatDate } from '@/utils'; import CommentBox from './CommentBox'; import classNames from 'classnames'; +import { usePage } from '@inertiajs/react'; +import axios from 'axios'; +import { on } from 'events'; type CommentsProps = { post: PostType; @@ -14,6 +17,7 @@ type CommentProps = { comment: CommentType; post: PostType; parentId?: number; + onCommentDelete: (commentId: number) => void; }; const Comments: React.FC = ({ post }) => { @@ -56,11 +60,11 @@ const Comments: React.FC = ({ post }) => {
{comments.length > 0 && !isFetching && ( -
-

Comments

+
+

Comments

-
Sort By
+
Sort By