1
1
mirror of https://github.com/aelve/guide.git synced 2024-12-24 21:35:06 +03:00
guide/src/Main.hs

109 lines
2.9 KiB
Haskell
Raw Normal View History

{-# LANGUAGE
OverloadedStrings,
TemplateHaskell,
RecordWildCards,
RankNTypes,
NoImplicitPrelude
#-}
2016-02-02 12:35:39 +03:00
module Main (main) where
-- General
import BasePrelude hiding (Category)
-- Lenses
import Lens.Micro.Platform
-- IO
import Control.Monad.IO.Class
-- Text
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import Data.Text.Format hiding (format)
import qualified Data.Text.Format as Format
import Data.Text.Format.Params (Params)
-- Web
import Lucid hiding (for_)
import Web.Spock
import Network.Wai.Middleware.Static
data Category = Category {
_categoryId :: Int,
_categoryTitle :: Text,
_categoryItems :: [Text] }
makeLenses ''Category
data S = S {
_nextId :: Int,
_categories :: [Category] }
makeLenses ''S
categoryById :: Int -> Traversal' S Category
categoryById catId = categories . each . filtered ((== catId) . _categoryId)
2016-02-02 12:35:39 +03:00
main :: IO ()
main = runSpock 8080 $ spockT id $ do
middleware (staticPolicy (addBase "static"))
stateVar <- liftIO $ newIORef S {
_nextId = 0,
_categories = [] }
get root $ do
s <- liftIO $ readIORef stateVar
lucid $ renderRoot s
post "/add/category" $ do
title <- param' "title"
thisId <- liftIO $ view nextId <$> readIORef stateVar
let newCategory = Category {
_categoryId = thisId,
_categoryTitle = title,
_categoryItems = [] }
liftIO $ modifyIORef stateVar $
(categories %~ (++ [newCategory])) .
(nextId %~ succ)
lucid $ renderCategory newCategory
post ("/add/item" <//> var) $ \catId -> do
item <- param' "item"
-- TODO: maybe do something if the category doesn't exist (e.g. has been
-- already deleted)
liftIO $ modifyIORef stateVar $
categoryById catId . categoryItems %~ (++ [item])
renderRoot :: S -> Html ()
renderRoot s = do
loadJS "https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"
loadJS "/js.js"
div_ [id_ "categories"] $ do
mapM_ renderCategory (s ^. categories)
2016-02-02 20:14:02 +03:00
let handler = "if (event.keyCode == 13) {\
\ addCategory(this.value);\
\ this.value = ''; }"
input_ [type_ "text", placeholder_ "new category", onkeyup_ handler]
renderCategory :: Category -> Html ()
renderCategory Category{..} =
div_ [id_ (format "cat{}" [_categoryId])] $ do
h2_ (toHtml _categoryTitle)
ul_ $ do
mapM_ (li_ . toHtml) _categoryItems
2016-02-02 20:14:02 +03:00
let handler = format "if (event.keyCode == 13) {\
\ addItem({}, this.value);\
\ this.value = ''; }"
[_categoryId]
input_ [type_ "text", placeholder_ "new item", onkeyup_ handler]
-- Utils
loadJS :: Text -> Html ()
loadJS url = with (script_ "") [src_ url]
lucid :: Html a -> ActionT IO a
lucid = html . TL.toStrict . renderText
-- | Format a string (a bit 'Text.Printf.printf' but with different syntax).
format :: Params ps => Format -> ps -> Text
format f ps = TL.toStrict (Format.format f ps)