diff --git a/src/Taskell/Data/Lists.hs b/src/Taskell/Data/Lists.hs index 4d5f4ced..c6b3c3ba 100644 --- a/src/Taskell/Data/Lists.hs +++ b/src/Taskell/Data/Lists.hs @@ -6,10 +6,11 @@ import Control.Lens ((^.)) import Data.Sequence as S (adjust', deleteAt, update, (!?), (|>)) import qualified Taskell.Data.List as L (List, Update, append, clearDue, count, due, empty, extract, - prepend, searchFor) + prepend, searchFor, tasks) import qualified Taskell.Data.Seq as S import qualified Taskell.Data.Task as T (Task, due) import Taskell.Types (ListIndex (ListIndex), Pointer, TaskIndex (TaskIndex)) +import Taskell.Data.List (List(List)) type Lists = Seq L.List @@ -34,6 +35,20 @@ due lists = sortOn ((^. T.due) . snd) dues format x lst = (\(y, t) -> ((ListIndex x, y), t)) <$> L.due lst dues = concat $ format S.<#> lists +-- TODO: Refactor +subTaskList :: Lists -> Seq (Pointer, T.Task) +subTaskList lists = seqs + where + seqs :: Seq (Pointer, T.Task) + seqs = concat $ format S.<#> lists + format :: Int -> L.List -> Seq (Pointer, T.Task) + format idx lst = (\(y, t) -> ( (ListIndex idx, y), t)) <$> taskList2 lst + taskList2 :: L.List -> Seq (TaskIndex, T.Task) + taskList2 (List title tasks) = taskList3 S.<#> tasks + taskList3 :: Int -> T.Task -> (TaskIndex, T.Task) + taskList3 index task = (TaskIndex index, task) + + clearDue :: Pointer -> Update clearDue (idx, tsk) = updateFn idx (L.clearDue tsk) diff --git a/src/Taskell/Events/Actions.hs b/src/Taskell/Events/Actions.hs index f8056f5f..46bb0fbc 100644 --- a/src/Taskell/Events/Actions.hs +++ b/src/Taskell/Events/Actions.hs @@ -16,13 +16,14 @@ import Taskell.Events.State.Types.Mode (DetailMode (..), ModalType (..), Mode (. import Taskell.IO.Keyboard (generate) import Taskell.IO.Keyboard.Types (Bindings, BoundActions) -import qualified Taskell.Events.Actions.Insert as Insert -import qualified Taskell.Events.Actions.Modal as Modal -import qualified Taskell.Events.Actions.Modal.Detail as Detail -import qualified Taskell.Events.Actions.Modal.Due as Due -import qualified Taskell.Events.Actions.Modal.Help as Help -import qualified Taskell.Events.Actions.Normal as Normal -import qualified Taskell.Events.Actions.Search as Search +import qualified Taskell.Events.Actions.Insert as Insert +import qualified Taskell.Events.Actions.Modal as Modal +import qualified Taskell.Events.Actions.Modal.Detail as Detail +import qualified Taskell.Events.Actions.Modal.Due as Due +import qualified Taskell.Events.Actions.Modal.Help as Help +import qualified Taskell.Events.Actions.Normal as Normal +import qualified Taskell.Events.Actions.Search as Search +import qualified Taskell.Events.Actions.Modal.TaskList as TaskList -- takes an event and returns a Maybe State event' :: Event -> Stateful @@ -44,6 +45,7 @@ event actions e state = do Modal (Detail _ DetailNormal) -> lookup e $ detail actions Modal Due {} -> lookup e $ due actions Modal (Help _) -> lookup e $ help actions + Modal TaskList {} -> lookup e $ taskList actions _ -> Nothing fromMaybe state $ case mEv of @@ -55,6 +57,7 @@ data ActionSets = ActionSets , detail :: BoundActions , help :: BoundActions , due :: BoundActions + , taskList :: BoundActions } generateActions :: Bindings -> ActionSets @@ -64,4 +67,5 @@ generateActions bindings = , detail = generate bindings Detail.events , help = generate bindings Help.events , due = generate bindings Due.events + , taskList = generate bindings TaskList.events } diff --git a/src/Taskell/Events/Actions/Modal.hs b/src/Taskell/Events/Actions/Modal.hs index 816f9c1f..b3f262ac 100644 --- a/src/Taskell/Events/Actions/Modal.hs +++ b/src/Taskell/Events/Actions/Modal.hs @@ -14,6 +14,7 @@ import qualified Taskell.Events.Actions.Modal.Detail as Detail import qualified Taskell.Events.Actions.Modal.Due as Due import qualified Taskell.Events.Actions.Modal.Help as Help import qualified Taskell.Events.Actions.Modal.MoveTo as MoveTo +import qualified Taskell.Events.Actions.Modal.TaskList as TaskList event :: Event -> Stateful event e s = @@ -22,4 +23,5 @@ event e s = Modal Detail {} -> Detail.event e s Modal MoveTo -> MoveTo.event e s Modal Due {} -> Due.event e s + Modal TaskList {} -> TaskList.event e s _ -> pure s diff --git a/src/Taskell/Events/Actions/Modal/TaskList.hs b/src/Taskell/Events/Actions/Modal/TaskList.hs new file mode 100644 index 00000000..c5fbdf4a --- /dev/null +++ b/src/Taskell/Events/Actions/Modal/TaskList.hs @@ -0,0 +1,16 @@ +{-# LANGUAGE OverloadedLists #-} + +module Taskell.Events.Actions.Modal.TaskList where + +import ClassyPrelude +import Graphics.Vty.Input.Events (Event) +import Taskell.Events.Actions.Types as A (ActionType (..)) +import Taskell.Events.State (normalMode, quit) +import Taskell.Events.State.Types (Stateful) +import Taskell.IO.Keyboard.Types (Actions) + +events :: Actions +events = [(A.Quit, quit)] + +event :: Event -> Stateful +event _ = normalMode diff --git a/src/Taskell/Events/Actions/Normal.hs b/src/Taskell/Events/Actions/Normal.hs index 20a85b0c..e14ec3be 100644 --- a/src/Taskell/Events/Actions/Normal.hs +++ b/src/Taskell/Events/Actions/Normal.hs @@ -15,6 +15,7 @@ import Taskell.Events.State.Modal.Detail (editDue, showDetail) import Taskell.Events.State.Modal.Due (showDue) import Taskell.Events.State.Types (Stateful) import Taskell.IO.Keyboard.Types (Actions) +import Taskell.Events.State.Modal.TaskList (showTaskList) events :: Actions events @@ -26,6 +27,7 @@ events , (A.Search, searchMode) , (A.Help, showHelp) , (A.Due, showDue) + , (A.TaskList, showTaskList) -- navigation , (A.Previous, previous) , (A.Next, next) diff --git a/src/Taskell/Events/Actions/Types.hs b/src/Taskell/Events/Actions/Types.hs index 34f2532b..f0bfd899 100644 --- a/src/Taskell/Events/Actions/Types.hs +++ b/src/Taskell/Events/Actions/Types.hs @@ -8,6 +8,7 @@ data ActionType | Redo | Search | Due + | TaskList | Help | Previous | Next @@ -51,6 +52,7 @@ read "undo" = Undo read "redo" = Redo read "search" = Search read "due" = Due +read "taskList" = TaskList read "help" = Help read "previous" = Previous read "next" = Next diff --git a/src/Taskell/Events/State/Modal/TaskList.hs b/src/Taskell/Events/State/Modal/TaskList.hs new file mode 100644 index 00000000..0ad31e42 --- /dev/null +++ b/src/Taskell/Events/State/Modal/TaskList.hs @@ -0,0 +1,14 @@ +module Taskell.Events.State.Modal.TaskList where + +import ClassyPrelude +import Control.Lens ((&), (.~), (^.)) +import Data.Sequence (Seq) +import qualified Data.Sequence as Seq +import qualified Taskell.Data.Lists as L +import Taskell.Events.State.Types (Stateful, lists, mode) +import Taskell.Events.State.Types.Mode (ModalType (TaskList), Mode (Modal)) + +showTaskList :: Stateful +showTaskList state = setMode (L.subTaskList $ state ^. lists) 0 state + where + setMode due pos state = pure $ state & mode .~ Modal (TaskList due pos) diff --git a/src/Taskell/Events/State/Types/Mode.hs b/src/Taskell/Events/State/Types/Mode.hs index 5d64fd2c..0809bb9d 100644 --- a/src/Taskell/Events/State/Types/Mode.hs +++ b/src/Taskell/Events/State/Types/Mode.hs @@ -27,6 +27,7 @@ data ModalType | MoveTo | Due (Seq (Pointer, Task)) Int + | TaskList (Seq (Pointer, Task)) Int | Detail DetailItem DetailMode deriving (Eq, Show) diff --git a/src/Taskell/IO/Keyboard.hs b/src/Taskell/IO/Keyboard.hs index 493f2e13..7087e61a 100644 --- a/src/Taskell/IO/Keyboard.hs +++ b/src/Taskell/IO/Keyboard.hs @@ -42,6 +42,7 @@ defaultBindings = , (BChar 'r', A.Redo) , (BChar '/', A.Search) , (BChar '!', A.Due) + , (BChar 'S', A.TaskList) , (BChar '?', A.Help) , (BChar 'k', A.Previous) , (BChar 'j', A.Next) diff --git a/src/Taskell/UI/Draw/Modal.hs b/src/Taskell/UI/Draw/Modal.hs index ae291708..e4fabde4 100644 --- a/src/Taskell/UI/Draw/Modal.hs +++ b/src/Taskell/UI/Draw/Modal.hs @@ -17,6 +17,7 @@ import Taskell.UI.Draw.Modal.Detail (detail) import Taskell.UI.Draw.Modal.Due (due) import Taskell.UI.Draw.Modal.Help (help) import Taskell.UI.Draw.Modal.MoveTo (moveTo) +import Taskell.UI.Draw.Modal.TaskList (taskList) import Taskell.UI.Draw.Types (DSWidget, DrawState (dsState), TWidget) import Taskell.UI.Theme (titleAttr) import Taskell.UI.Types (ResourceName (..)) @@ -41,4 +42,5 @@ renderModal = do Modal Detail {} -> surround =<< detail Modal MoveTo -> surround =<< moveTo Modal (Due tasks selected) -> surround =<< due tasks selected + Modal (TaskList t s) -> surround =<< taskList t s _ -> pure emptyWidget diff --git a/src/Taskell/UI/Draw/Modal/TaskList.hs b/src/Taskell/UI/Draw/Modal/TaskList.hs new file mode 100644 index 00000000..9bca35a4 --- /dev/null +++ b/src/Taskell/UI/Draw/Modal/TaskList.hs @@ -0,0 +1,58 @@ +module Taskell.UI.Draw.Modal.TaskList where + +import Brick (Padding (Pad)) +import Brick.Widgets.Core (cached, padBottom, padLeft, txt, vBox, visible, withAttr) +import ClassyPrelude +import Control.Lens ((^.)) +import Data.Sequence (Seq) +import qualified Data.Sequence as Seq +import Taskell.Data.Seq ((<#>)) +import Taskell.Data.Subtask (Subtask (Subtask), name) +import qualified Taskell.Data.Task as T +import Taskell.Types (Pointer) +import Taskell.UI.Draw.Task (TaskWidget (TaskWidget), parts) +import Taskell.UI.Draw.Types (DSWidget, ModalWidget, TWidget) +import Taskell.UI.Theme (taskAttr, taskCurrentAttr) +import Taskell.UI.Types (ResourceName (RNTaskList)) + +taskList :: Seq (Pointer, T.Task) -> Int -> ModalWidget +taskList tasks selectedIndex = do + let items = snd <$> tasks + withSubtasks = tasksWithSubtasks items + widgets <- sequence $ renderTask selectedIndex <#> withSubtasks + pure + ( "Sub-task List", + if null items + then txt "No Tasks with SubTasks" + else vBox $ toList widgets + ) + +renderTask :: Int -> Int -> T.Task -> DSWidget +renderTask current position task = do + (TaskWidget text date _ subTaskCount) <- parts task + let selected = current == position + subtasks = task ^. T.subtasks + let attr = + if selected + then taskCurrentAttr + else taskAttr + let shw = + if selected + then visible + else id + pure . shw . cached (RNTaskList position) + . padBottom (Pad 1) + . withAttr attr + $ vBox [text, renderSubTasks subtasks] + +renderSubTasks :: Seq Subtask -> TWidget +renderSubTasks subtasks = padLeft (Pad 1) . vBox $ renderSubTask <$> toList subtasks + +renderSubTask :: Subtask -> TWidget +renderSubTask s = txt $ s ^. name + +tasksWithSubtasks :: Seq T.Task -> Seq T.Task +tasksWithSubtasks = Seq.filter hasSubtask + where + hasSubtask :: T.Task -> Bool + hasSubtask t = Seq.length (t ^. T.subtasks) > 0 diff --git a/src/Taskell/UI/Types.hs b/src/Taskell/UI/Types.hs index cef58975..139564e3 100644 --- a/src/Taskell/UI/Types.hs +++ b/src/Taskell/UI/Types.hs @@ -11,4 +11,5 @@ data ResourceName | RNLists | RNModal | RNDue Int + | RNTaskList Int deriving (Show, Eq, Ord) diff --git a/templates/bindings.ini b/templates/bindings.ini index a4247486..ac5f194b 100644 --- a/templates/bindings.ini +++ b/templates/bindings.ini @@ -5,6 +5,7 @@ redo = r search = / help = ? due = ! +taskList = S # navigation previous = k