Skip to content

Commit 428274b

Browse files
committed
posts + comments
1 parent d0a1636 commit 428274b

File tree

16 files changed

+237
-3
lines changed

16 files changed

+237
-3
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CREATE TABLE comments (
2+
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
3+
post_id UUID NOT NULL,
4+
author TEXT NOT NULL,
5+
body TEXT NOT NULL
6+
);
7+
CREATE INDEX comments_post_id_index ON comments (post_id);
8+
ALTER TABLE comments ADD CONSTRAINT comments_ref_post_id FOREIGN KEY (post_id) REFERENCES posts (id) ON DELETE NO ACTION;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE comments RENAME COLUMN authos TO author;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE comments ADD COLUMN created_at TIMESTAMP WITH TIME ZONE DEFAULT now() NOT NULL;
2+
CREATE INDEX comments_created_at_index ON comments (created_at);

Application/Schema.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,13 @@ CREATE TABLE posts (
66
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
77
);
88
CREATE INDEX posts_created_at_index ON posts (created_at);
9+
CREATE TABLE comments (
10+
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
11+
post_id UUID NOT NULL,
12+
author TEXT NOT NULL,
13+
body TEXT NOT NULL,
14+
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL
15+
);
16+
CREATE INDEX comments_post_id_index ON comments (post_id);
17+
CREATE INDEX comments_created_at_index ON comments (created_at);
18+
ALTER TABLE comments ADD CONSTRAINT comments_ref_post_id FOREIGN KEY (post_id) REFERENCES posts (id) ON DELETE NO ACTION;

Web/Controller/Comments.hs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
module Web.Controller.Comments where
2+
3+
import Web.Controller.Prelude
4+
import Web.View.Comments.Index
5+
import Web.View.Comments.New
6+
import Web.View.Comments.Edit
7+
import Web.View.Comments.Show
8+
9+
instance Controller CommentsController where
10+
action CommentsAction = do
11+
comments <- query @Comment |> fetch
12+
render IndexView { .. }
13+
14+
action NewCommentAction { postId } = do
15+
let comment = newRecord
16+
|> set #postId postId
17+
post <- fetch postId
18+
render NewView { .. }
19+
20+
action ShowCommentAction { commentId } = do
21+
comment <- fetch commentId
22+
render ShowView { .. }
23+
24+
action EditCommentAction { commentId } = do
25+
comment <- fetch commentId
26+
render EditView { .. }
27+
28+
action UpdateCommentAction { commentId } = do
29+
comment <- fetch commentId
30+
comment
31+
|> buildComment
32+
|> ifValid \case
33+
Left comment -> render EditView { .. }
34+
Right comment -> do
35+
comment <- comment |> updateRecord
36+
setSuccessMessage "Comment updated"
37+
redirectTo EditCommentAction { .. }
38+
39+
action CreateCommentAction = do
40+
let comment = newRecord @Comment
41+
comment
42+
|> buildComment
43+
|> ifValid \case
44+
Left comment -> do
45+
post <- fetch comment.postId -- <---- NEW
46+
render NewView { .. }
47+
Right comment -> do
48+
comment <- comment |> createRecord
49+
setSuccessMessage "Comment created"
50+
redirectTo ShowPostAction { postId = comment.postId }
51+
52+
53+
action DeleteCommentAction { commentId } = do
54+
comment <- fetch commentId
55+
deleteRecord comment
56+
setSuccessMessage "Comment deleted"
57+
redirectTo CommentsAction
58+
59+
buildComment comment = comment
60+
|> fill @'["postId", "author", "body"]

Web/Controller/Posts.hs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import Web.View.Posts.Index
55
import Web.View.Posts.New
66
import Web.View.Posts.Edit
77
import Web.View.Posts.Show
8+
import qualified Text.MMark as MMark
9+
810

911
instance Controller PostsController where
1012
action PostsAction = do
@@ -19,6 +21,8 @@ instance Controller PostsController where
1921

2022
action ShowPostAction { postId } = do
2123
post <- fetch postId
24+
>>= pure . modify #comments (orderByDesc #createdAt)
25+
>>= fetchRelated #comments
2226
render ShowView { .. }
2327

2428
action EditPostAction { postId } = do
@@ -56,3 +60,11 @@ instance Controller PostsController where
5660
buildPost post = post
5761
|> fill @'["title", "body"]
5862
|> validateField #title nonEmpty
63+
|> validateField #body nonEmpty
64+
|> validateField #body isMarkdown
65+
66+
isMarkdown :: Text -> ValidatorResult
67+
isMarkdown text =
68+
case MMark.parse "" text of
69+
Left _ -> Failure "Please provide valid Markdown"
70+
Right _ -> Success

Web/FrontController.hs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ import Web.Controller.Prelude
55
import Web.View.Layout (defaultLayout)
66

77
-- Controller Imports
8+
import Web.Controller.Comments
89
import Web.Controller.Posts
910
import Web.Controller.Static
1011

1112
instance FrontController WebApplication where
1213
controllers =
1314
[ startPage WelcomeAction
1415
-- Generator Marker
16+
, parseRoute @CommentsController
1517
, parseRoute @PostsController
1618
]
1719

Web/Routes.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ import Web.Types
77
instance AutoRoute StaticController
88
instance AutoRoute PostsController
99

10+
11+
instance AutoRoute CommentsController
12+

Web/Types.hs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,13 @@ data PostsController
1818
| UpdatePostAction { postId :: !(Id Post) }
1919
| DeletePostAction { postId :: !(Id Post) }
2020
deriving (Eq, Show, Data)
21+
22+
data CommentsController
23+
= CommentsAction
24+
| NewCommentAction { postId :: !(Id Post) }
25+
| ShowCommentAction { commentId :: !(Id Comment) }
26+
| CreateCommentAction
27+
| EditCommentAction { commentId :: !(Id Comment) }
28+
| UpdateCommentAction { commentId :: !(Id Comment) }
29+
| DeleteCommentAction { commentId :: !(Id Comment) }
30+
deriving (Eq, Show, Data)

Web/View/Comments/Edit.hs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
module Web.View.Comments.Edit where
2+
import Web.View.Prelude
3+
4+
data EditView = EditView { comment :: Comment }
5+
6+
instance View EditView where
7+
html EditView { .. } = [hsx|
8+
{breadcrumb}
9+
<h1>Edit Comment</h1>
10+
{renderForm comment}
11+
|]
12+
where
13+
breadcrumb = renderBreadcrumb
14+
[ breadcrumbLink "Comments" CommentsAction
15+
, breadcrumbText "Edit Comment"
16+
]
17+
18+
renderForm :: Comment -> Html
19+
renderForm comment = formFor comment [hsx|
20+
{(textField #postId)}
21+
{(textField #author)}
22+
{(textField #body)}
23+
{submitButton}
24+
25+
|]

0 commit comments

Comments
 (0)