Skip to content

Commit 6de85c0

Browse files
authored
Merge pull request #1 from prb/claude/review-haskell-blog-server-011CUze3o7w6pDJcA8GWncVG
Review legacy Haskell blog server code
2 parents 66e9ace + 3750833 commit 6de85c0

34 files changed

Lines changed: 1238 additions & 1162 deletions

perpubplat.cabal

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,25 @@ stability: alpha
1111
build-type: Simple
1212
cabal-version: >= 1.2
1313

14-
Executable perpubplat.fcgi
14+
Executable perpubplat
1515
build-depends:
16-
base >= 3.0 && < 4.0, parsec >= 2.0, xhtml >= 3000, haskell98, filepath >= 1.0,
17-
old-time >= 1.0, containers, directory, utf8-string >= 0.2, HTTP >= 4000.0.4,
18-
old-locale >= 1.0, json >= 0.4.3, network >= 2.1, time >= 1.1.2.0,
19-
unix >= 2.3, fastcgi >= 3001.0.2.2, bytestring >= 0.9.0.1.1, pureMD5 >= 0.2.2,
16+
base >= 4.9 && < 5, parsec >= 3.1, filepath >= 1.0,
17+
containers, directory, utf8-string >= 0.2,
18+
network >= 2.1, network-uri >= 2.6, time >= 1.9,
19+
unix >= 2.3, bytestring >= 0.9.0.1.1, pureMD5 >= 0.2.2,
2020
base64-string, hslogger >= 1.0.5, xml >= 1.3.4,
21-
HDBC >= 2.1.0, HDBC-sqlite3 >= 2.1.0.0
21+
HDBC >= 2.1.0, HDBC-sqlite3 >= 2.1.0.0,
22+
http-client >= 0.5, http-client-tls >= 0.3, http-types >= 0.12,
23+
aeson >= 2.0, text >= 1.2, vector >= 0.12, scientific >= 0.3,
24+
lucid >= 2.9,
25+
wai >= 3.2, warp >= 3.3, case-insensitive >= 1.2,
26+
random >= 1.2
2227
main-is:
2328
perpubplat.hs
2429
hs-source-dirs:
2530
src, servletsrc
2631
ghc-options:
27-
-O -Werror -fwarn-unused-binds -fwarn-unused-imports -fwarn-unused-matches -threaded
32+
-O -fwarn-unused-binds -fwarn-unused-imports -fwarn-unused-matches -threaded
2833

2934
Executable runtests
3035
buildable:
@@ -36,4 +41,4 @@ Executable runtests
3641
hs-source-dirs:
3742
testsrc
3843
ghc-options:
39-
-O -Werror -fwarn-unused-binds -fwarn-unused-imports -fwarn-unused-matches -threaded
44+
-O -fwarn-unused-binds -fwarn-unused-imports -fwarn-unused-matches -threaded

servletsrc/perpubplat.hs

Lines changed: 216 additions & 193 deletions
Large diffs are not rendered by default.

src/Blog/Admin/PendingComments.hs

Lines changed: 145 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE OverloadedStrings #-}
12
module Blog.Admin.PendingComments where
23

34
import qualified Blog.Model.CommentBodyParser as CBP
@@ -8,149 +9,152 @@ import Utilities
89

910
import Data.Maybe
1011
import Blog.FrontEnd.ContentAtoms
11-
import Text.XHtml.Strict
12+
import Lucid
13+
import qualified Data.Text as T
14+
import qualified Data.Text.Lazy as TL
1215

1316
display_comments :: B.Model -> Int -> [B.Item] -> String
14-
display_comments m page cmts
15-
= showHtml
16-
. concatHtml $ [ header << stylesheet
17-
, body . (divid "container") . concatHtml $ [ navigation page cmts
18-
, nuke page chunk
19-
, concatHtml ( map (render m page) chunk ) ] ]
20-
where
21-
chunk = paginate C.comment_view_size page cmts
22-
23-
24-
nuke :: Int -> [B.Item] -> Html
25-
nuke _ [] = noHtml
26-
nuke n items = ( p ! [ theclass "nuke_em" ] )
27-
$ nuke_comments_form (map (show . B.internal_id) items) n
28-
29-
navigation :: Int -> [B.Item] -> Html
30-
navigation _ [] = (p ! [ theclass "comment_nav" ] )
31-
<< stringToHtml "There are no comments waiting for review."
32-
navigation n cmts = ( p ! [ theclass "comment_nav" ] )
33-
. concatHtml $ [ stringToHtml ( "There " ++ isare )
34-
, bold . stringToHtml . show . length $ cmts
35-
, stringToHtml ( plural ++ " waiting for review." )
36-
, br
37-
, page_enumeration n cmts ]
38-
where
39-
isare = case length cmts of
40-
1 -> "is "
41-
_ -> "are "
42-
plural = case length cmts of
43-
1 -> " comment "
44-
_ -> " comments "
45-
46-
page_enumeration :: Int -> [B.Item] -> Html
47-
page_enumeration _ [] = noHtml
48-
page_enumeration n s | (1 == last_page C.comment_view_size s) = noHtml
49-
| otherwise = concatHtml $ map (page_link n lp) [1..lp]
17+
display_comments m page cmts =
18+
TL.unpack . renderText $ do
19+
head_ stylesheet
20+
body_ $ divid "container" $ do
21+
navigation page cmts
22+
nuke page chunk
23+
mconcat $ map (render m page) chunk
24+
where
25+
chunk = paginate C.comment_view_size page cmts
26+
27+
nuke :: Int -> [B.Item] -> Html ()
28+
nuke _ [] = mempty
29+
nuke n items = p_ [class_ "nuke_em"] $
30+
nuke_comments_form (map (show . B.internal_id) items) n
31+
32+
navigation :: Int -> [B.Item] -> Html ()
33+
navigation _ [] = p_ [class_ "comment_nav"] $
34+
toHtml ("There are no comments waiting for review." :: String)
35+
navigation n cmts = p_ [class_ "comment_nav"] $ do
36+
toHtml ( "There " ++ isare )
37+
strong_ $ toHtml $ show $ length cmts
38+
toHtml ( plural ++ " waiting for review." )
39+
br_ []
40+
page_enumeration n cmts
41+
where
42+
isare = case length cmts of
43+
1 -> "is "
44+
_ -> "are "
45+
plural = case length cmts of
46+
1 -> " comment "
47+
_ -> " comments "
48+
49+
page_enumeration :: Int -> [B.Item] -> Html ()
50+
page_enumeration _ [] = mempty
51+
page_enumeration n s | (1 == last_page C.comment_view_size s) = mempty
52+
| otherwise = mconcat $ map (page_link n lp) [1..lp]
5053
where
5154
lp = last_page C.comment_view_size s
5255

53-
page_link :: Int -> Int -> Int -> Html
54-
page_link i k j | (i == j) = (bold . stringToHtml . show $ j)
55-
+++ if (j==k) then
56-
noHtml
57-
else
58-
(stringToHtml " ")
59-
| otherwise = (_at (U.pending_comments $ Just j) (show j)) +++ (stringToHtml " ")
60-
61-
render :: B.Model -> Int -> B.Item -> Html
62-
render m n i = (thediv ! [ theclass "comment_container" ])
63-
. (table ! [ theclass "comment_wrapper" ] ) . tr . concatHtml $
64-
[ ( td ! [ theclass "data_cell" ] )
65-
. concatHtml $ [ ( p ! [ theclass "comment_preview_fields" ])
66-
. concatHtml $ [ render_author . B.author $ i
67-
, br
68-
, d . B.created $ i
69-
, stringToHtml " / # "
70-
, d . show . B.internal_id $ i
71-
, stringToHtml " / re: "
72-
, _a (parent_plink) (primHtml . B.title $ parent) ]
73-
, (thediv ! [ theclass "comment_body_preview"])
74-
<< ( CBP.convert_comment_body . B.body $ i ) ]
75-
, ( td ! [ theclass "action_cell" ] )
76-
. concatHtml $ [ post_comment_form int_id n
77-
, edit_comment_form int_id
78-
, delete_comment_form int_id n ]
79-
]
80-
where
81-
int_id = show . B.internal_id $ i
82-
parent = (B.item_by_id m) . fromJust . B.parent $ i
83-
parent_plink = B.permalink m parent
84-
d = bold . stringToHtml
85-
86-
post_comment_form :: String -> Int -> Html
87-
post_comment_form int_id n = ( form ! [ identifier $ "post-" ++ int_id
88-
, method "post"
89-
, action . U.post_comment $ int_id] )
90-
. concatHtml $ [ callback int_id n
91-
, input ! [ thetype "submit"
92-
, value "Post"
93-
, theclass "post_comment_submit" ] ]
94-
95-
delete_comment_form :: String -> Int -> Html
96-
delete_comment_form int_id n = ( form ! [ identifier $ "delete-" ++ int_id
97-
, method "post"
98-
, action U.delete_comment] )
99-
. concatHtml $ [ callback int_id n
100-
, input ! [ thetype "submit"
101-
, value "Delete"
102-
, theclass "delete_comment_submit" ] ]
103-
104-
105-
nuke_comments_form :: [String] -> Int -> Html
106-
nuke_comments_form int_ids n = ( form ! [ identifier $ "nuke"
107-
, method "post"
108-
, action U.delete_comments ] )
109-
. concatHtml $ [ callbacks int_ids n
110-
, input ! [ thetype "submit"
111-
, value "Nuke All On Page"
112-
, theclass "nuke_comments_submit" ] ]
113-
114-
callbacks :: [String] -> Int -> Html
115-
callbacks int_ids n = (hidden_int_ids int_ids)
116-
+++ (hidden_page n)
117-
118-
hidden_int_id :: String -> Html
119-
hidden_int_id int_id = input ! [ thetype "hidden"
120-
, name "id"
121-
, value int_id ]
122-
123-
hidden_int_ids :: [String] -> Html
124-
hidden_int_ids = concatHtml . map (\x -> input ! [ thetype "hidden"
125-
, name $ "id_" ++ x
126-
, value x ])
127-
128-
hidden_page :: Int -> Html
129-
hidden_page n = input ! [ thetype "hidden"
130-
, name "page"
131-
, value (show n) ]
132-
133-
callback :: String -> Int -> Html
134-
callback int_id n = (hidden_int_id int_id)
135-
+++ (hidden_page n)
136-
137-
edit_comment_form :: String -> Html
138-
edit_comment_form int_id = ( form ! [ identifier $ "edit-" ++ int_id
139-
, method "get"
140-
, action . U.review_comment $ int_id ] )
141-
<< input ! [ thetype "submit"
142-
, value "Edit"
143-
, theclass "edit_comment_submit" ]
144-
145-
render_author :: B.Author -> Html
146-
render_author a = concatHtml [ bold . stringToHtml . B.name $ a
147-
, stringToHtml " / "
148-
, bold . stringToHtml $ case (B.email a) of
149-
Nothing -> "<no email>"
150-
Just e -> e
151-
, stringToHtml " / "
152-
, case B.uri a of
153-
Nothing ->
154-
stringToHtml "<no URI>"
155-
Just u ->
156-
_a u (bold . stringToHtml $ u) ]
56+
page_link :: Int -> Int -> Int -> Html ()
57+
page_link i k j | (i == j) = do
58+
strong_ $ toHtml $ show j
59+
if (j==k) then mempty else toHtml (" " :: String)
60+
| otherwise = do
61+
_at (U.pending_comments $ Just j) (show j)
62+
toHtml (" " :: String)
63+
64+
render :: B.Model -> Int -> B.Item -> Html ()
65+
render m n i = div_ [class_ "comment_container"] $
66+
table_ [class_ "comment_wrapper"] $ tr_ $ do
67+
td_ [class_ "data_cell"] $ do
68+
p_ [class_ "comment_preview_fields"] $ do
69+
render_author $ B.author i
70+
br_ []
71+
d $ B.created i
72+
toHtml (" / # " :: String)
73+
d $ show $ B.internal_id i
74+
toHtml (" / re: " :: String)
75+
_a parent_plink (toHtmlRaw $ B.title parent)
76+
div_ [class_ "comment_body_preview"] $
77+
CBP.convert_comment_body $ B.body i
78+
td_ [class_ "action_cell"] $ do
79+
post_comment_form int_id n
80+
edit_comment_form int_id
81+
delete_comment_form int_id n
82+
where
83+
int_id = show . B.internal_id $ i
84+
parent = (B.item_by_id m) . fromJust . B.parent $ i
85+
parent_plink = B.permalink m parent
86+
d = strong_ . toHtml
87+
88+
post_comment_form :: String -> Int -> Html ()
89+
post_comment_form int_id n = form_ [ id_ (T.pack $ "post-" ++ int_id)
90+
, method_ "post"
91+
, action_ (T.pack $ U.post_comment int_id) ] $ do
92+
callback int_id n
93+
input_ [ type_ "submit"
94+
, value_ "Post"
95+
, class_ "post_comment_submit" ]
96+
97+
delete_comment_form :: String -> Int -> Html ()
98+
delete_comment_form int_id n = form_ [ id_ (T.pack $ "delete-" ++ int_id)
99+
, method_ "post"
100+
, action_ (T.pack U.delete_comment) ] $ do
101+
callback int_id n
102+
input_ [ type_ "submit"
103+
, value_ "Delete"
104+
, class_ "delete_comment_submit" ]
105+
106+
nuke_comments_form :: [String] -> Int -> Html ()
107+
nuke_comments_form int_ids n = form_ [ id_ "nuke"
108+
, method_ "post"
109+
, action_ (T.pack U.delete_comments) ] $ do
110+
callbacks int_ids n
111+
input_ [ type_ "submit"
112+
, value_ "Nuke All On Page"
113+
, class_ "nuke_comments_submit" ]
114+
115+
callbacks :: [String] -> Int -> Html ()
116+
callbacks int_ids n = do
117+
hidden_int_ids int_ids
118+
hidden_page n
119+
120+
hidden_int_id :: String -> Html ()
121+
hidden_int_id int_id = input_ [ type_ "hidden"
122+
, name_ "id"
123+
, value_ (T.pack int_id) ]
124+
125+
hidden_int_ids :: [String] -> Html ()
126+
hidden_int_ids = mconcat . map (\x -> input_ [ type_ "hidden"
127+
, name_ (T.pack $ "id_" ++ x)
128+
, value_ (T.pack x) ])
129+
130+
hidden_page :: Int -> Html ()
131+
hidden_page n = input_ [ type_ "hidden"
132+
, name_ "page"
133+
, value_ (T.pack $ show n) ]
134+
135+
callback :: String -> Int -> Html ()
136+
callback int_id n = do
137+
hidden_int_id int_id
138+
hidden_page n
139+
140+
edit_comment_form :: String -> Html ()
141+
edit_comment_form int_id = form_ [ id_ (T.pack $ "edit-" ++ int_id)
142+
, method_ "get"
143+
, action_ (T.pack $ U.review_comment int_id) ] $
144+
input_ [ type_ "submit"
145+
, value_ "Edit"
146+
, class_ "edit_comment_submit" ]
147+
148+
render_author :: B.Author -> Html ()
149+
render_author a = do
150+
strong_ $ toHtml $ B.name a
151+
toHtml (" / " :: String)
152+
strong_ $ toHtml $ case (B.email a) of
153+
Nothing -> "<no email>"
154+
Just e -> e
155+
toHtml (" / " :: String)
156+
case B.uri a of
157+
Nothing ->
158+
toHtml ("<no URI>" :: String)
159+
Just u ->
160+
_a u (strong_ $ toHtml u)

src/Blog/BackEnd/AsyncLogHandler.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,5 @@ append n i h c = do { ((p,m),l,ts) <- readChan c
4040
else
4141
append n (i+1) h c }
4242

43-
printex :: Handle -> CE.Exception -> IO ()
43+
printex :: Handle -> CE.SomeException -> IO ()
4444
printex h e = hPutStrLn System.IO.stderr $ "Error writing to log handle " ++ (show h) ++ ": " ++ show e

src/Blog/BackEnd/HitTracker.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import qualified System.Log.Logger as L
1414

1515
data HitTracker = HitTracker { events :: CCC.Chan Request
1616
, database_worker :: DatabaseWorker
17-
, hits :: ! (DM.Map String Int)
17+
, hits :: !(DM.Map String Int)
1818
, tracker_tid :: CC.ThreadId }
1919

2020
data Request = TallyHit { h_item :: Item }

0 commit comments

Comments
 (0)