packages feed

panda-0.0.0.5.1: Panda/Controller/Application.hs

-- the controller is the most complex module for a reason:
-- models are made as simple and small as possible
-- views are pure functions.

-- I believe this leads to more robust system, and provides much more
-- flexibility in both design and implementation


{-# OPTIONS -fno-monomorphism-restriction #-}


module Panda.Controller.Application where

import qualified Data.Map as Map

-- env
import Panda.Helper.Env hiding (tag)
import Prelude hiding ((.), (/), id)
import Panda.Type.State hiding (pager)
import qualified Panda.Config.Global as Config
import qualified Panda.Type.Pager as Pager

-- model
import qualified Panda.Model.Post as Post
import qualified Panda.Model.Static as Static
import qualified Panda.Model.Tag as Tag

-- view
import qualified Panda.View.Theme.BluePrint.Post as PostV
import qualified Panda.View.Theme.BluePrint.Template.Template as T
import qualified Panda.View.Theme.BluePrint.Static as StaticV
import qualified Panda.View.Theme.BluePrint.Tag as TagV
import qualified Panda.View.Theme.BluePrint.Search as SearchV
import qualified Panda.View.RSS as RSSV

blog_regex = "^/[0-9][0-9]-[0-9][0-9]-[0-9][0-9]"
  
pages = 
  [ ("^/$"                  ,index             )
  , ("^/([?].+$)?$"         ,index             )
  , ("^/rss.xml$"           ,index_feed        )
  , (blog_regex             ,blog              )
  , ("^/static/."           ,static            )
  , ("^/tag/.*/rss.xml$"    ,tag_feed          )
  , ("^/tag/."              ,tag               )
  , ("^/search"             ,search            )
  ]

per_page = Config.per_page

index = do
  blogs <- Post.list.liftIO
  p <- pager per_page $ blogs.length
  tags <- Tag.list.liftIO
  let nav = if p.Pager.current == 1 then home_nav else no_navigation
  let state = State Config.blog_id p tags nav
  
  blogs.map (Tag.fill_tag tags) .PostV.list state .output_html

index_feed = do
  blogs <- Post.list.liftIO
  blogs.RSSV.rss "" "" .output


blog = do
  id <- uri <.> ("blog/" ++)
  blog <- Post.get id .liftIO
  tags <- Tag.list.liftIO
  
  let state = State id Pager.empty tags no_navigation
  blog.Tag.fill_tag tags .PostV.view state .output_html

static = do
  id <- uri
  static_page <- Static.get id .liftIO
  tags <- Tag.list.liftIO
  
  let nav = if title.belongs_to Config.navigation then title else no_navigation where title = static_page.Static.title
  let state = State id Pager.empty tags nav
  StaticV.view state static_page .output_html


tag = do
  id <- uri
  tags <- Tag.list.liftIO
  let tag_name = Tag.get_name id
  case Tag.tag_map' tags .Map.lookup tag_name of
    Nothing -> "page not found" .output
    Just blog_set -> do
      blogs <- blog_set.to_list.rsort.mapM (Post.get) .liftIO <.> map (Tag.fill_tag tags)
      p <- pager per_page $ blogs.length
      let state = State id p tags no_navigation
      blogs.TagV.view state.output_html

tag_feed = do
  id <- uri <.> (split "/" >>> init >>> join "/")
  tags <- Tag.list.liftIO
  let tag_name = Tag.get_name id
  case Tag.tag_map' tags .Map.lookup tag_name of
    Nothing -> "page not found" .output
    Just blog_set -> do
      blogs <- blog_set.to_list.rsort.mapM (Post.get) .liftIO <.> map (Tag.fill_tag tags)
      blogs.RSSV.rss "tag" tag_name.output

search = do
  s <- param_with_default "s" ""
  blogs <- Post.search s .liftIO

  p <- pager per_page $ blogs.length
  tags <- Tag.list.liftIO
  query <- uri
  let state = State query p tags no_navigation

  blogs.map (Tag.fill_tag tags) .SearchV.view state s.output_html