{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
module UI.Draw.Task
( TaskWidget(..)
, renderTask
, parts
) where
import ClassyPrelude
import Control.Lens ((^.))
import Brick
import Data.Taskell.Date (dayToText, deadline)
import qualified Data.Taskell.Task as T (Task, contains, countCompleteSubtasks, countSubtasks,
description, due, hasSubtasks, name)
import Events.State.Types (current, mode, searchTerm, time)
import IO.Config.Layout (descriptionIndicator)
import Types (ListIndex (..), TaskIndex (..))
import UI.Draw.Field (getText, textField, widgetFromMaybe)
import UI.Draw.Mode
import UI.Draw.Types (DSWidget, DrawState (..), ReaderDrawState, TWidget)
import UI.Theme
import UI.Types (ResourceName)
data TaskWidget = TaskWidget
{ textW :: TWidget
, dateW :: TWidget
, summaryW :: TWidget
, subtasksW :: TWidget
}
renderDate :: T.Task -> DSWidget
renderDate task = do
today <- utctDay . (^. time) <$> asks dsState
pure . fromMaybe emptyWidget $
(\day -> withAttr (dlToAttr $ deadline today day) (txt $ dayToText today day)) <$>
task ^. T.due
renderSubtaskCount :: T.Task -> DSWidget
renderSubtaskCount task =
pure . fromMaybe emptyWidget $ bool Nothing (Just indicator) (T.hasSubtasks task)
where
complete = tshow $ T.countCompleteSubtasks task
total = tshow $ T.countSubtasks task
indicator = txt $ concat ["[", complete, "/", total, "]"]
renderDescIndicator :: T.Task -> DSWidget
renderDescIndicator task = do
indicator <- descriptionIndicator <$> asks dsLayout
pure . fromMaybe emptyWidget $ const (txt indicator) <$> task ^. T.description
renderText :: T.Task -> DSWidget
renderText task = pure $ textField (task ^. T.name)
indicators :: T.Task -> DSWidget
indicators task = do
widgets <- sequence (($ task) <$> [renderDescIndicator, renderSubtaskCount, renderDate])
pure . hBox $ padRight (Pad 1) <$> widgets
parts :: T.Task -> ReaderDrawState TaskWidget
parts task =
TaskWidget <$> renderText task <*> renderDate task <*> renderDescIndicator task <*>
renderSubtaskCount task
renderTask' :: (Int -> ResourceName) -> Int -> Int -> T.Task -> DSWidget
renderTask' rn listIndex taskIndex task = do
eTitle <- editingTitle . (^. mode) <$> asks dsState
selected <- (== (ListIndex listIndex, TaskIndex taskIndex)) . (^. current) <$> asks dsState
taskField <- getField . (^. mode) <$> asks dsState
after <- indicators task
widget <- renderText task
let name = rn taskIndex
widget' = widgetFromMaybe widget taskField
pure $
cached name .
(if selected && not eTitle
then visible
else id) .
padBottom (Pad 1) .
(<=> withAttr disabledAttr after) .
withAttr
(if selected
then taskCurrentAttr
else taskAttr) $
if selected && not eTitle
then widget'
else widget
renderTask :: (Int -> ResourceName) -> Int -> Int -> T.Task -> DSWidget
renderTask rn listIndex taskIndex task = do
searchT <- (getText <$>) . (^. searchTerm) <$> asks dsState
let taskWidget = renderTask' rn listIndex taskIndex task
case searchT of
Nothing -> taskWidget
Just term ->
if T.contains term task
then taskWidget
else pure emptyWidget