By | Chris Done |
At | 2011-06-11 |
Title | Added dev. activity log. |
Description |
Edit file amelie.cabal 33188 → 33188
36 36 ,hlint >= 1.8
37 37 ,filepath >= 1.1
38 38 ,directory >= 1.0
39 39 ,blaze-builder >= 0.2
40 40 ,ConfigFile >= 1.0
+ 41 ,feed >= 0.3
+ 42 ,download-curl >= 0.1
… … … … Edit file src/Main.hs 33188 → 33188
5 5 6 6 module Main (main) where
7 7 8 8 import Amelie.Config
9 9 import Amelie.Controller
+ 10 import Amelie.Controller.Activity as Activity
10 11 import Amelie.Controller.Browse as Browse
11 12 import Amelie.Controller.Cache (newCache)
12 13 import Amelie.Controller.Home as Home
13 14 import Amelie.Controller.New as New
14 15 import Amelie.Controller.Paste as Paste
… … … … 53 54 ,("/new",run New.handle)
54 55 ,("/new/:channel",run New.handle)
55 56 ,("/browse/page/:page/offset/:offset",run Browse.handle)
56 57 ,("/browse/page/:page",run Browse.handle)
57 58 ,("/browse",run Browse.handle)
+ 59 ,("/activity",run Activity.handle)
58 60 ]
59 61 run = runHandler conf p cache ans
… … … … Edit file src/Amelie/Config.hs 33188 → 33188
23 23 <- mapM (get c "POSTGRESQL")
24 24 ["host","port","user","pass","db"]
25 25 [domain]
26 26 <- mapM (get c "WEB")
27 27 ["domain"]
+ 28 [commits]
+ 29 <- mapM (get c "DEV")
+ 30 ["commits"]
+ 31 28 32 return Config {
29 33 configAnnounce = Announcer user pass host (read port)
30 34 , configPostgres = ConnectInfo pghost (read pgport) pguser pgpass pgdb
31 35 , configDomain = domain
+ 36 , configCommits = commits
32 37 }
33 38 case config of
34 39 Left cperr -> error $ show cperr
35 40 Right config -> return config
… … … … Edit file src/Amelie/Types.hs 33188 → 33188
8 8 ,module Amelie.Types.Channel
9 9 ,module Amelie.Types.Language
10 10 ,module Amelie.Types.Page
11 11 ,module Amelie.Types.Newtypes
12 12 ,module Amelie.Types.View
- 13 ,module Amelie.Types.Config)
+ 13 ,module Amelie.Types.Config
+ 14 ,module Amelie.Types.Activity)
14 15 where
15 16 16 17 import Amelie.Types.MVC
17 18 import Amelie.Types.Paste
18 19 import Amelie.Types.Channel
19 20 import Amelie.Types.Language
20 21 import Amelie.Types.Page
21 22 import Amelie.Types.Newtypes
22 23 import Amelie.Types.View
23 24 import Amelie.Types.Config
+ 25 import Amelie.Types.Activity
… … … … Edit file src/Amelie/View/Layout.hs 33188 → 33188
11 11 import Amelie.Types
12 12 import Amelie.View.Html
13 13 14 14 import Data.Monoid.Operator ((++))
15 15 import Prelude hiding ((++))
- 16 import Text.Blaze.Html5 as H hiding (map)
+ 16 import Text.Blaze.Html5 as H hiding (map,nav)
17 17 import qualified Text.Blaze.Html5.Attributes as A
18 18 19 19 -- | Render the page in a layout.
20 20 layoutPage :: Page -> Html
21 21 layoutPage Page{..} = do
… … … … 26 26 js "jquery.js"
27 27 js "amelie.js"
28 28 title $ toHtml $ pageTitle ++ " :: hpaste — Haskell Pastebin"
29 29 body ! A.id (toValue pageName) $
30 30 wrap $ do
+ 31 nav
31 32 logo
32 33 pageBody
33 34 foot
34 35 35 36 where js s = script ! A.type_ "text/javascript"
… … … … 43 44 img ! aClass "logo" ! A.src "/css/hpaste.png"
44 45 45 46 -- | Layout wrapper.
46 47 wrap :: Html -> Html
47 48 wrap x = H.div ! aClass "wrap" $ x
+ 49 + 50 -- | Navigation.
+ 51 nav :: Html
+ 52 nav = do
+ 53 H.div ! aClass "nav" $ do
+ 54 a ! A.href "/activity" $ "Changelog"
48 55 49 56 -- | Page footer.
50 57 foot :: Html
51 58 foot = H.div ! aClass "footer" $ p $
52 59 lnk "http://github.com/chrisdone/amelie" "Web site source code on Github"
… … … … Edit file src/Amelie/View/Style.hs 33188 → 33188
22 22 highlighter
23 23 form
24 24 home
25 25 browse
26 26 footer
+ 27 activity
27 28 28 29 -- | Footer.
29 30 footer :: CSS Rule
30 31 footer = do
31 32 classRule "footer" $ do
… … … … 48 49 border "0"
49 50 50 51 classRule "wrap" $ do
51 52 margin "auto"
52 53 textAlign "left"
+ 54 + 55 classRule "nav" $ do
+ 56 float "right"
+ 57 marginTop "1em"
53 58 54 59 -- | Paste form.
55 60 form :: CSS Rule
56 61 form = do
57 62 inputs
… … … … 220 225 margin "1em"
221 226 222 227 subRule ".amelie-inner" $ do
223 228 margin "auto"
224 229 width "15em"
+ 230 + 231 -- | Developer activity page styles.
+ 232 activity :: CSS Rule
+ 233 activity = do
+ 234 rule "#activity" $ do
+ 235 subRule ".amelie-wrap" $ do
+ 236 width "50em"
… … … … Edit file src/Amelie/Types/Cache.hs 33188 → 33188
12 12 import Data.Text.Lazy (Text)
13 13 14 14 data Key =
15 15 Home
16 16 | Paste Integer
+ 17 | Activity
17 18 deriving (Eq,Ord)
18 19 19 20 data Cache =
20 21 Cache {
21 22 cacheMap :: MVar (Map Key Text)
… … … … Edit file src/Amelie/Types/Config.hs 33188 → 33188
10 10 -- | Site-wide configuration.
11 11 data Config = Config {
12 12 configAnnounce :: Announcer
13 13 , configPostgres :: ConnectInfo
14 14 , configDomain :: String
+ 15 , configCommits :: String
15 16 } deriving (Show)
16 17 17 18 -- | Announcer configuration.
18 19 data Announcer = Announcer {
19 20 announceUser :: String
… … … … Add file src/Amelie/View/Activity.hs 33188
+ 1 {-# OPTIONS -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind #-} + 2 {-# LANGUAGE OverloadedStrings #-} + 3 {-# LANGUAGE RecordWildCards #-} + 4 + 5 -- | Activity page view. + 6 + 7 module Amelie.View.Activity + 8 (page) + 9 where + 10 + 11 import Amelie.Types + 12 import Amelie.View.Html + 13 import Amelie.View.Layout + 14 + 15 import Control.Monad + 16 import Data.Text (Text) + 17 import Prelude hiding ((++)) + 18 import Text.Blaze.Html5 as H hiding (map) + 19 + 20 -- | Render the activity page. + 21 page :: [Commit] -> Html + 22 page commits = + 23 layoutPage $ Page { + 24 pageTitle = "Development activity" + 25 , pageBody = activity commits + 26 , pageName = "activity" + 27 } + 28 + 29 -- | View the paginated pastes. + 30 activity :: [Commit] -> Html + 31 activity commits = do + 32 darkSection "Development activity" $ do + 33 p $ do "Repository: " + 34 href ("https://github.com/chrisdone/amelie/" :: Text) + 35 ("https://github.com/chrisdone/amelie/" :: Text) + 36 forM_ commits $ \Commit{..} -> do + 37 lightSection commitTitle $ do + 38 p $ toHtml $ show commitDate + 39 p $ href commitLink ("Go to diff" :: Text) Add file src/Amelie/Types/Activity.hs 33188
+ 1 module Amelie.Types.Activity where + 2 + 3 import Data.Text.Lazy (Text) + 4 import Data.Time (UTCTime) + 5 + 6 data Commit = Commit { + 7 commitTitle :: Text + 8 ,commitContent :: Text + 9 ,commitDate :: UTCTime + 10 ,commitLink :: Text + 11 } deriving Show Add file src/Amelie/Model/Activity.hs 33188
+ 1 {-# OPTIONS -Wall #-} + 2 {-# LANGUAGE OverloadedStrings #-} + 3 + 4 -- | Activity model. + 5 + 6 module Amelie.Model.Activity + 7 (getCommits) + 8 where + 9 + 10 import Amelie.Types + 11 import Amelie.Model + 12 + 13 import Control.Monad.IO (io) + 14 import Data.Maybe (mapMaybe) + 15 import Data.Text.Lazy (pack) + 16 import Data.Time + 17 import Network.Curl.Download + 18 import System.Locale + 19 import Text.Feed.Query + 20 + 21 -- | Get commits of this project from a commit feed. + 22 getCommits :: String -> Model [Commit] + 23 getCommits uri = io $ do + 24 result <- openAsFeed uri + 25 case result of + 26 Left _ -> return [] + 27 Right feed -> return $ + 28 let items = getFeedItems feed + 29 in mapMaybe makeCommit items + 30 + 31 where makeCommit item = do + 32 title <- getItemTitle item + 33 datestr <- getItemDate item + 34 date <- parseDateString datestr + 35 link <- getItemLink item + 36 return $ Commit { + 37 commitTitle = pack $ title + 38 , commitContent = "" -- Getting content from atom does not work. + 39 , commitDate = date + 40 , commitLink = pack link + 41 } + 42 -- E.g. 2011-06-11T11:15:11-07:00 + 43 parseDateString = parseTime defaultTimeLocale "%Y-%M-%dT%T%Z" Add file src/Amelie/Controller/Activity.hs 33188
+ 1 {-# OPTIONS -Wall #-} + 2 {-# LANGUAGE OverloadedStrings #-} + 3 + 4 -- | Activity page controller. + 5 + 6 module Amelie.Controller.Activity + 7 (handle) + 8 where + 9 + 10 import Amelie.Controller (outputText) + 11 import Amelie.Controller.Cache (cache) + 12 import Amelie.Model + 13 import Amelie.Model.Activity (getCommits) + 14 import Amelie.Types.Cache as Key + 15 import Amelie.View.Activity (page) + 16 + 17 import Control.Monad.Env (env) + 18 + 19 handle :: Controller () + 20 handle = do + 21 html <- cache Key.Activity $ do + 22 uri <- env $ configCommits . controllerStateConfig + 23 commits <- model $ getCommits uri + 24 return $ Just $ page commits + 25 maybe (return ()) outputText html