Skip to content

Commit

Permalink
Ensure that a task can only be repeating or recurring
Browse files Browse the repository at this point in the history
  • Loading branch information
ad-si committed May 14, 2024
1 parent af51aaa commit d009274
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 64 deletions.
152 changes: 89 additions & 63 deletions tasklite-core/source/Lib.hs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ import Database.SQLite.Simple (
NamedParam ((:=)),
Only (Only),
Query (Query),
SQLData (SQLText),
SQLData (SQLNull, SQLText),
SQLError (sqlError),
ToRow,
changes,
Expand Down Expand Up @@ -1090,44 +1090,57 @@ repeatTasks conf connection duration ids = do
execWithTask conf connection idSubstr $ \task -> do
groupUlid <- formatUlid getULID

executeNamed
connection
[sql|
recDur :: [Only SQLData] <-
queryNamed
connection
[sql|
UPDATE tasks
SET
repetition_duration = :repetition_duration,
group_ulid = :group_ulid
WHERE ulid == :ulid
WHERE
ulid == :ulid AND
recurrence_duration IS NULL
RETURNING recurrence_duration
|]
[ ":repetition_duration" := durationIsoText
, ":group_ulid" := groupUlid
, ":ulid" := task.ulid
]
[ ":repetition_duration" := durationIsoText
, ":group_ulid" := groupUlid
, ":ulid" := task.ulid
]

-- If repetition is set for already closed task,
-- next task in series must be created immediately
creationMb <-
if isNothing task.closed_utc
then pure $ Just mempty
else
liftIO $
createNextRepetition conf connection $
task
{ Task.repetition_duration = Just durationIsoText
, Task.group_ulid = Just groupUlid
}
if recDur /= [Only SQLNull]
then
pure $
"⚠️ Task"
<+> dquotes (pretty task.body)
<+> "with id"
<+> dquotes (pretty task.ulid)
<+> "is already in a recurrence series"
else do
-- If repetition is set for already closed task,
-- next task in series must be created immediately
creationMb <-
if isNothing task.closed_utc
then pure $ Just mempty
else
liftIO $
createNextRepetition conf connection $
task
{ Task.repetition_duration = Just durationIsoText
, Task.group_ulid = Just groupUlid
}

pure $
"📅 Set repeat duration of task"
<+> dquotes (pretty task.body)
<+> "with id"
<+> dquotes (pretty task.ulid)
<+> "to"
<+> dquotes (pretty durationIsoText)
<++> ( creationMb
& fromMaybe
"⚠️ Next task in repetition series could not be created!"
)
pure $
"📅 Set repeat duration of task"
<+> dquotes (pretty task.body)
<+> "with id"
<+> dquotes (pretty task.ulid)
<+> "to"
<+> dquotes (pretty durationIsoText)
<++> ( creationMb
& fromMaybe
"⚠️ Next task in repetition series could not be created!"
)

pure $ vsep docs

Expand All @@ -1141,44 +1154,57 @@ recurTasks conf connection duration ids = do
execWithTask conf connection idSubstr $ \task -> do
groupUlid <- formatUlid getULID

executeNamed
connection
[sql|
repDur :: [Only SQLData] <-
queryNamed
connection
[sql|
UPDATE tasks
SET
recurrence_duration = :recurrence_duration,
group_ulid = :group_ulid
WHERE ulid == :ulid
WHERE
ulid == :ulid AND
repetition_duration IS NULL
RETURNING repetition_duration
|]
[ ":recurrence_duration" := durationIsoText
, ":group_ulid" := groupUlid
, ":ulid" := task.ulid
]
[ ":recurrence_duration" := durationIsoText
, ":group_ulid" := groupUlid
, ":ulid" := task.ulid
]

-- If recurrence is set for already closed task,
-- next task in series must be created immediately
creationMb <-
if isNothing task.closed_utc
then pure $ Just mempty
else
liftIO $
createNextRecurrence conf connection $
task
{ Task.recurrence_duration = Just durationIsoText
, Task.group_ulid = Just groupUlid
}
if repDur /= [Only SQLNull]
then
pure $
"⚠️ Task"
<+> dquotes (pretty task.body)
<+> "with id"
<+> dquotes (pretty task.ulid)
<+> "is already in a repetition series"
else do
-- If recurrence is set for already closed task,
-- next task in series must be created immediately
creationMb <-
if isNothing task.closed_utc
then pure $ Just mempty
else
liftIO $
createNextRecurrence conf connection $
task
{ Task.recurrence_duration = Just durationIsoText
, Task.group_ulid = Just groupUlid
}

pure $
"📅 Set recurrence duration of task"
<+> dquotes (pretty task.body)
<+> "with id"
<+> dquotes (pretty task.ulid)
<+> "to"
<+> dquotes (pretty durationIsoText)
<++> ( creationMb
& fromMaybe
"⚠️ Next task in recurrence series could not be created!"
)
pure $
"📅 Set recurrence duration of task"
<+> dquotes (pretty task.body)
<+> "with id"
<+> dquotes (pretty task.ulid)
<+> "to"
<+> dquotes (pretty durationIsoText)
<++> ( creationMb
& fromMaybe
"⚠️ Next task in recurrence series could not be created!"
)

pure $ vsep docs

Expand Down
23 changes: 22 additions & 1 deletion tasklite-core/test/LibSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import Protolude (
)
import Protolude qualified as P

import Control.Arrow ((>>>))
import Data.Aeson (decode)
import Data.List.Utils (subIndex)
import Data.Text (unpack)
Expand All @@ -39,7 +40,6 @@ import Test.Hspec (
)

import Config (defaultConfig)
import Control.Arrow ((>>>))
import FullTask (FullTask, emptyFullTask)
import FullTask qualified
import ImportExport (EditMode (ApplyPreEdit), editTaskByTask)
Expand All @@ -61,10 +61,12 @@ import Lib (
logTask,
newTasks,
nextTask,
recurTasks,
repeatTasks,
runFilter,
setDueUtc,
setReadyUtc,
unrepeatTasks,
updateTask,
)
import Note (Note)
Expand Down Expand Up @@ -465,6 +467,25 @@ spec = do
cliOutput <- addTag defaultConfig memConn newTag [task1.ulid]
show cliOutput `shouldEndWith` "Tag \"test\" is already assigned"

it "repeats a task and prevents recurring same task" $ do
withMemoryDb defaultConfig $ \memConn -> do
insertRecord "tasks" memConn task1
let oneWeek = Iso.DurationWeek (Iso.DurWeek 1)
repeatRes <- repeatTasks defaultConfig memConn oneWeek [task1.ulid]
P.show repeatRes `shouldContain` "Set repeat duration of task"

recurRes <- recurTasks defaultConfig memConn oneWeek [task1.ulid]
P.show recurRes `shouldContain` "is already in a repetition series"

unrepeatRes <- unrepeatTasks defaultConfig memConn [task1.ulid]
P.show unrepeatRes `shouldContain` "Removed repetition duration"

recurRes2 <- recurTasks defaultConfig memConn oneWeek [task1.ulid]
P.show recurRes2 `shouldContain` "Set recurrence duration of task"

repeatRes2 <- repeatTasks defaultConfig memConn oneWeek [task1.ulid]
P.show repeatRes2 `shouldContain` "is already in a recurrence series"

context "Editing a task" $ do
it "shows warning if a tag was duplicated" $ do
withMemoryDb defaultConfig $ \memConn -> do
Expand Down

0 comments on commit d009274

Please sign in to comment.