Basic showing, no CSS
Getty Ritter
10 years ago
| 3 | 3 | |
| 4 | 4 | module Main where |
| 5 | 5 | |
| 6 | import Control.Monad (forM_) | |
| 7 | import Data.HashMap (toList) | |
| 8 | -- import qualified Storage as S | |
| 9 | -- import qualified Templates as T | |
| 6 | import Control.Monad.IO.Class (liftIO) | |
| 7 | import Data.Text (Text) | |
| 8 | import qualified Data.Text as T | |
| 9 | import Data.HashMap.Strict (toList) | |
| 10 | import Lucid (renderBS) | |
| 11 | import qualified Storage as S | |
| 12 | import qualified Templates as T | |
| 10 | 13 | import Web.Spock.Safe |
| 11 | 14 | |
| 12 | 15 | {- / |
| 23 | 26 | |
| 24 | 27 | -} |
| 25 | 28 | |
| 26 |
projectR :: Path '[ |
|
| 29 | projectR :: Path '[String] | |
| 27 | 30 | projectR = "project" <//> var |
| 28 | 31 | |
| 29 | 32 | loginR :: Path '[] |
| 32 | 35 | editR :: Path '[] |
| 33 | 36 | editR = "edit" |
| 34 | 37 | |
| 35 |
editProjectR :: Path '[ |
|
| 38 | editProjectR :: Path '[String] | |
| 36 | 39 | editProjectR = "edit" <//> "project" <//> var |
| 37 | 40 | |
| 38 | 41 | main :: IO () |
| 39 | 42 | main = runSpock 8080 $ spockT id $ do |
| 40 | get Root $ do | |
| 41 | projs <- S.getProjects | |
| 42 |
|
|
| 43 | get root $ do | |
| 44 | projects <- liftIO S.getAllProjects | |
| 45 | lazyBytes (renderBS $ T.projectList projects) | |
| 43 | 46 | get projectR $ \ p -> do |
| 44 | text "whoo" | |
| 45 | post Root $ do | |
| 47 | project <- liftIO (S.getProject p) | |
| 48 | text (T.pack $ show project) | |
| 49 | {- | |
| 50 | post root $ do | |
| 46 | 51 | fs <- files |
| 47 | 52 | forM_ (toList fs) $ \ (k, v) -> do |
| 48 | liftIO $ putStrLn $ "name" ++ show k | |
| 49 | liftIO $ putStrLn $ "uf_name" ++ show (uf_name v) | |
| 50 |
liftIO $ |
|
| 53 | liftIO $ do | |
| 54 | putStrLn $ "name" ++ show k | |
| 55 | putStrLn $ "uf_name" ++ show (uf_name v) | |
| 56 | putStrLn $ "uf_contentType" ++ show (uf_contentType v) | |
| 57 | putStrLn $ "uf_tempLocation" ++ show (uf_tempLocation v) | |
| 51 | 58 | text "blah" |
| 59 | -} | |
| 1 | 1 | {-# LANGUAGE OverloadedStrings #-} |
| 2 | {-# LANGUAGE FlexibleInstances #-} | |
| 3 | {-# LANGUAGE DeriveGeneric #-} | |
| 4 | {-# LANGUAGE DeriveAnyClass #-} | |
| 5 | {-# LANGUAGE ViewPatterns #-} | |
| 6 | {-# LANGUAGE ScopedTypeVariables #-} | |
| 2 | 7 | |
| 3 | 8 | module Storage where |
| 4 | 9 | |
| 10 | import Control.Exception (catch) | |
| 5 | 11 | import Data.Aeson |
| 12 | import Data.ByteString.Lazy (ByteString) | |
| 6 | 13 | import Data.FileStore |
| 7 |
import Data. |
|
| 14 | import Data.Maybe (catMaybes) | |
| 15 | import Data.Monoid ((<>)) | |
| 16 | import Data.String (IsString) | |
| 17 | import Data.Text (Text) | |
| 18 | --import Data.UUID.V4 | |
| 19 | import GHC.Generics(Generic) | |
| 20 | ||
| 21 | (</>) :: (IsString m, Monoid m) => m -> m -> m | |
| 22 | x </> y = x <> "/" <> y | |
| 23 | ||
| 24 | data ImageType | |
| 25 | = ItPNG | |
| 26 | | ItJPG | |
| 27 | | ItGIF | |
| 28 | deriving (Eq, Show) | |
| 8 | 29 | |
| 9 | 30 | data Project = Project |
| 10 | 31 | { projectSlug :: Text |
| 11 | 32 | , projectName :: Text |
| 12 | 33 | , projectDescr :: Text |
| 13 | , projectImgs :: [Text] | |
| 14 | } deriving (Eq, Show) | |
| 34 | , projectImgs :: [String] | |
| 35 | } deriving (Eq, Show, Generic, FromJSON, ToJSON) | |
| 15 | 36 | |
| 16 | instance Contents (Maybe Project) where | |
| 17 | fromByteString = decode | |
| 18 | toByteString (Just x) = encode x | |
| 19 | toByteString Nothing = error "should not happen" | |
| 37 | recover :: forall a. IO (Maybe a) -> IO (Maybe a) | |
| 38 | recover action = action `catch` go | |
| 39 | where go :: FileStoreError -> IO (Maybe a) | |
| 40 | go _ = return Nothing | |
| 41 | ||
| 42 | fromValue :: FromJSON b => a -> (b -> a) -> ByteString -> a | |
| 43 | fromValue def f v = case decode v of | |
| 44 | Nothing -> def | |
| 45 | Just x -> f x | |
| 20 | 46 | |
| 21 | 47 | portfolioStore :: FileStore |
| 22 | 48 | portfolioStore = gitFileStore "portfolio-data" |
| 23 | 49 | |
| 24 | getProjectByName :: String -> IO (Maybe Project) | |
| 25 | getProjectByName name = retrieve (name <> ".json") portfolioStore Nothing | |
| 50 | getProjectNames :: IO [String] | |
| 51 | getProjectNames = fmap (fromValue [] id) | |
| 52 | (retrieve portfolioStore "projects.json" Nothing) | |
| 26 | 53 | |
| 27 | getImage :: String -> IO (Maybe ByteString) | |
| 28 | getImage name = retrieve ("images" </> name) portfolioStore Nothing | |
| 54 | getAllProjects :: IO [Project] | |
| 55 | getAllProjects = getProjectNames >>= (fmap catMaybes . mapM getProject) | |
| 29 | 56 | |
| 30 | newImage :: UploadedFile -> () | |
| 31 | newImage = undefined | |
| 57 | getProject :: String -> IO (Maybe Project) | |
| 58 | getProject name = | |
| 59 | fmap (fromValue Nothing Just) | |
| 60 | (retrieve portfolioStore (name <> ".json") Nothing) | |
| 61 | ||
| 62 | getImage :: String -> IO ByteString | |
| 63 | getImage name = retrieve portfolioStore ("images" </> name) Nothing | |
| 64 | ||
| 65 | {- | |
| 66 | imageType :: String -> ImageType | |
| 67 | imageType "image/gif" = ItGIF | |
| 68 | imageType "image/jpeg" = ItJPG | |
| 69 | imageType _ = ItPNG | |
| 70 | ||
| 71 | newImage :: UploadedFile -> IO () | |
| 72 | newImage uf = do | |
| 73 | let typ = imageType (uf_contentType uf) | |
| 74 | name <- nextRandom | |
| 75 | return () | |
| 76 | -} |
| 1 | {-# LANGUAGE OverloadedStrings #-} | |
| 2 | {-# LANGUAGE RecordWildCards #-} | |
| 3 | ||
| 4 | module Templates where | |
| 5 | ||
| 6 | import Data.Monoid ((<>)) | |
| 7 | import Data.Text (Text, pack) | |
| 8 | import Lucid | |
| 9 | import qualified Storage as S | |
| 10 | ||
| 11 | footer :: Html () | |
| 12 | footer = "© Empress Cortana 2015" | |
| 13 | ||
| 14 | page :: Html () -> Html () -> Html () | |
| 15 | page name contents = html_ $ do | |
| 16 | head_ $ do | |
| 17 | title_ name | |
| 18 | body_ $ do | |
| 19 | div_ [id_ "header"] $ h1_ name | |
| 20 | div_ [id_ "main"] $ contents | |
| 21 | div_ [id_ "footer"] $ footer | |
| 22 | ||
| 23 | projectList :: [S.Project] -> Html () | |
| 24 | projectList = page "empress cortana // portfolio" . mapM_ shortProj | |
| 25 | ||
| 26 | imgUrl :: String -> Text | |
| 27 | imgUrl s = pack ("imgs/" <> s) | |
| 28 | ||
| 29 | projUrl :: Text -> Text | |
| 30 | projUrl s = "project/" <> s | |
| 31 | ||
| 32 | shortProj :: S.Project -> Html () | |
| 33 | shortProj (S.Project { .. }) = div_ [class_ "project"] $ do | |
| 34 | div_ [id_ "name"] $ a_ [href_ (projUrl projectSlug)] $ toHtml projectName | |
| 35 | case projectImgs of | |
| 36 | (img:_) -> div_ [id_ "tile"] $ img_ [src_ (imgUrl img)] | |
| 37 | [] -> return () |
| 13 | 13 | Main-Is: Main.hs |
| 14 | 14 | Default-Language: Haskell2010 |
| 15 | 15 | GHC-Options: -Wall |
| 16 |
Build-Depends: base >= 4 && < 5, |
|
| 16 | Build-Depends: base >= 4 && < 5, | |
| 17 | Spock, | |
| 18 | unordered-containers, | |
| 19 | bytestring, | |
| 20 | text, | |
| 21 | aeson, | |
| 22 | transformers, | |
| 23 | uuid, | |
| 24 | filestore, | |
| 25 | lucid | |
| 17 | 26 | |
| 18 | 27 | Source-Repository head |
| 19 | 28 | Type: git |