Skip to content

Commit

Permalink
start base api
Browse files Browse the repository at this point in the history
  • Loading branch information
sigrdrifa committed Jun 4, 2024
2 parents 5c13c46 + 0768076 commit 0e52829
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 18 deletions.
3 changes: 3 additions & 0 deletions hastl.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ library
, Models
, Api
, Api.User
, Api.Base
, Api.Templates.User
, Api.Templates.Base.Footer
, Logger
, DevelMain
-- other-modules:
Expand Down
4 changes: 1 addition & 3 deletions lib/Api.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ module Api (app) where

import Control.Monad.Reader (runReaderT)
import Servant (
MimeRender,
Proxy (Proxy),
Raw,
serveDirectoryFileServer,
Expand All @@ -15,7 +14,6 @@ import Servant.Server

import Api.User (UserAPI, userApi, userServer)
import Config (AppT (..), Config (..))
import Lucid (ToHtml)

{- | This functions tells Servant how to run the 'App' monad with our
'server' function.
Expand All @@ -31,7 +29,7 @@ convertApp :: Config -> AppT IO a -> Handler a
convertApp cfg appt = Handler $ runReaderT (runApp appt) cfg

{- | Since we also want to provide a minimal front end, we need to give
Servant a way to serve a directory with HTML and JavaScript. This
Servant a way to serve a directory with HTML and CSS. This
function creates a WAI application that just serves the files out of the
given directory.
-}
Expand Down
42 changes: 42 additions & 0 deletions lib/Api/Base.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}

module Api.Base where

import Lucid (Html, body_, charset_, doctypehtml_, head_, href_, link_, meta_, rel_, title_, type_)

import Servant (
Capture,
Get,
HasServer (ServerT),
JSON,
Post,
Proxy (..),
ReqBody,
err404,
throwError,
type (:<|>) (..),
type (:>),
)

import Api.Templates.Base.Footer (renderFooter)
import Servant.API.ContentTypes.Lucid (HTML)

{- | The base template for all pages.
This function takes the title of the page and the body of the page.
It returns a full HTML document.
The body of the page should be an HTML fragment.
-}
baseTemplate :: Html () -> Html () -> Html ()
baseTemplate title' body' = do
doctypehtml_ $ do
head_ $ do
meta_ [charset_ "utf-8"]
title_ title'
link_ [rel_ "stylesheet", type_ "text/css", href_ "/style.min.css"]
body_ $ do
body'
renderFooter

type BaseAPI = "/base" :> Get '[HTML] (Html ())
8 changes: 8 additions & 0 deletions lib/Api/Templates/Base/Footer.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{-# LANGUAGE OverloadedStrings #-}

module Api.Templates.Base.Footer where

import Lucid (Html, class_, div_, p_)

renderFooter :: Html ()
renderFooter = div_ [class_ "footer"] (p_ "This is the footer")
10 changes: 10 additions & 0 deletions lib/Api/Templates/User.hs
Original file line number Diff line number Diff line change
@@ -1 +1,11 @@
{-# LANGUAGE OverloadedStrings #-}
module Api.Templates.User where

import Models (User (userName))
import Lucid (Html, div_, class_, p_, ToHtml (toHtml))

renderUsers :: [User] -> Html ()
renderUsers [] = div_ [class_ "users"] (p_ "No data")
renderUsers users = div_ [class_ "users"] (do mapM_ renderUser users)
where renderUser user = p_ (toHtml (userName user))

21 changes: 7 additions & 14 deletions lib/Api/User.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,30 @@ import Servant (

import Config (AppT (..))
import Data.Text (Text)
import Lucid (Html, ToHtml (toHtml), class_, div_, p_)
import Lucid (Html)
import Servant.API.ContentTypes.Lucid ( HTML )
import Models (User (User), runDb, userEmail, userName)
import Models qualified as Md
import Api.Templates.User (renderUsers)

type UserAPI =
"users" :> Get '[JSON] [Entity User]
"users" :> Get '[HTML] (Html ())
:<|> "users" :> Capture "name" Text :> Get '[JSON] (Entity User)
:<|> "users" :> ReqBody '[JSON] User :> Post '[JSON] Int64
:<|> "usersTable" :> Get '[HTML] (Html ())

userApi :: Proxy UserAPI
userApi = Proxy

-- | The server that runs the UserAPI
userServer :: (MonadIO m) => ServerT UserAPI (AppT m)
userServer = allUsers :<|> singleUser :<|> createUser :<|> allUsersTbl
userServer = allUsers :<|> singleUser :<|> createUser

-- | Returns all users in the database.
allUsers :: (MonadIO m) => AppT m [Entity User]
allUsers :: (MonadIO m) => AppT m (Html ())
allUsers = do
logDebugNS "web" "allUsers"
runDb (selectList [] [])
users :: [Entity User] <- runDb (selectList [] [])
return $ renderUsers (map entityVal users)

-- | Returns a user by name or throws a 404 error.
singleUser :: (MonadIO m) => Text -> AppT m (Entity User)
Expand All @@ -72,11 +73,3 @@ createUser p = do
logDebugNS "web" "creating a user"
newUser <- runDb (insert (User (userName p) (userEmail p)))
return $ fromSqlKey newUser

allUsersTbl :: (MonadIO m) => AppT m (Html ())
allUsersTbl = do
users :: [Entity User] <- runDb (selectList [] [])
return $
div_ [class_ ""] (do (mapM_ f users))
where f (Entity _ u) = p_ (toHtml (userName u))

2 changes: 1 addition & 1 deletion static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<h1 class="text-3xl font-bold underline">hastl</h1>
<hr />
Modern web application framework
<button hx-get="/usersTable" hx-swap="outerHTML">
<button hx-get="/users" hx-swap="outerHTML">
Click Me
</button>
</div>
Expand Down

0 comments on commit 0e52829

Please sign in to comment.