Skip to content

Commit

Permalink
YAML editing: Include current tags and notes for reference
Browse files Browse the repository at this point in the history
  • Loading branch information
ad-si committed Apr 23, 2024
1 parent c240837 commit a20a6d0
Show file tree
Hide file tree
Showing 8 changed files with 260 additions and 25 deletions.
2 changes: 2 additions & 0 deletions tasklite-core/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,12 @@ tests:
- aeson
- hourglass
- hspec
- neat-interpolation
- optparse-applicative
- sqlite-simple
- tasklite-core
- text
- yaml

benchmarks:
tasklite-bench:
Expand Down
19 changes: 10 additions & 9 deletions tasklite-core/source/ImportExport.hs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ import Data.Text.Lazy.Encoding qualified as TL
import Data.Time.ISO8601.Duration qualified as Iso
import Data.ULID (ulidFromInteger)
import Data.Vector qualified as V
import Data.Yaml as Yaml (ParseException, decodeEither', encode)
import Data.Yaml as Yaml (ParseException, decodeEither')
import Database.SQLite.Simple as Sql (Connection, query_)
import FullTask (FullTask)
import Lib (
Expand Down Expand Up @@ -115,6 +115,7 @@ import Task (
waiting_utc
),
setMetadataField,
taskToEditableYaml,
textToTaskState,
zeroTask,
)
Expand Down Expand Up @@ -718,8 +719,8 @@ data PreEdit


editTaskByTask :: PreEdit -> Connection -> Task -> IO (Doc AnsiStyle)
editTaskByTask preEdit connection taskToEdit = do
let taskYaml = Yaml.encode taskToEdit
editTaskByTask preEdit conn taskToEdit = do
taskYaml <- taskToEditableYaml conn taskToEdit
newContent <- case preEdit of
ApplyPreEdit editFunc -> pure $ editFunc taskYaml
NoPreEdit -> runUserEditorDWIM yamlTemplate taskYaml
Expand Down Expand Up @@ -764,15 +765,15 @@ editTaskByTask preEdit connection taskToEdit = do
else Nothing
}

updateTask connection taskFixed
updateTask conn taskFixed
warnings <-
insertTags
connection
conn
Nothing
taskFixed
(tags importTaskRecord)
insertNotes
connection
conn
Nothing
taskFixed
(notes importTaskRecord)
Expand All @@ -786,6 +787,6 @@ editTaskByTask preEdit connection taskToEdit = do


editTask :: Config -> Connection -> IdText -> IO (Doc AnsiStyle)
editTask conf connection idSubstr = do
execWithTask conf connection idSubstr $ \taskToEdit -> do
editTaskByTask NoPreEdit connection taskToEdit
editTask conf conn idSubstr = do
execWithTask conf conn idSubstr $ \taskToEdit -> do
editTaskByTask NoPreEdit conn taskToEdit
3 changes: 2 additions & 1 deletion tasklite-core/source/Lib.hs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ import Utils (
ulidTextToDateTime,
utcFormatReadable,
utcTimeToDateTime,
vsepCollapse,
(<$$>),
(<++>),
)
Expand Down Expand Up @@ -389,7 +390,7 @@ insertTags connection mbCreatedUtc task tags = do
(insertRecord "task_to_tag" connection taskToTag P.>> pure "")
(handleTagDupError taskToTag.tag)

pure $ vsep insertWarnings
pure $ vsepCollapse insertWarnings


insertNotes :: Connection -> Maybe DateTime -> Task -> [Note] -> IO ()
Expand Down
81 changes: 66 additions & 15 deletions tasklite-core/source/Task.hs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
{-# LANGUAGE QuasiQuotes #-}

{-|
Datatype to represent a task as stored in the `tasks` table
-}
module Task where

import Protolude as P (
import Protolude (
Applicative ((<*>)),
Either (Left, Right),
Enum (toEnum),
Eq ((==)),
Float,
Foldable (elem),
Functor (fmap),
Generic,
Hashable,
Expand All @@ -21,6 +22,7 @@ import Protolude as P (
decodeUtf8,
fst,
otherwise,
pure,
show,
snd,
($),
Expand All @@ -30,29 +32,23 @@ import Protolude as P (
(<$>),
(<&>),
)
import Protolude qualified as P

import Data.Aeson as Aeson (
FromJSON,
ToJSON,
Value (Object),
encode,
eitherDecodeStrictText,
encode,
)
import Data.Aeson.Key as Key (fromText)
import Data.Aeson.KeyMap as KeyMap (fromList, insert)
import Data.ByteString.Lazy qualified as BSL
import Data.Csv as Csv (ToField (..), ToNamedRecord, ToRecord)
import Data.Csv qualified as Csv
import Data.Generics (Data)
import Data.Hourglass (DateTime, timePrint)
import Data.Text as T (
Text,
dropEnd,
intercalate,
pack,
replace,
toLower,
unpack,
)
import Data.Text (Text, pack)
import Data.Text qualified as T
import Data.Yaml as Yaml (encode)
import Database.SQLite.Simple as Sql (
FromRow (..),
Expand All @@ -74,6 +70,8 @@ import Test.QuickCheck (Arbitrary (arbitrary))
import Test.QuickCheck.Instances.Text ()

import Config (defaultConfig, utcFormat)
import Database.SQLite.Simple (Connection, Only (Only), query)
import Database.SQLite.Simple.QQ (sql)


data TaskState
Expand Down Expand Up @@ -107,8 +105,8 @@ instance FromJSON TaskState
instance ToJSON TaskState


instance ToRecord TaskState
instance ToNamedRecord TaskState
instance Csv.ToRecord TaskState
instance Csv.ToNamedRecord TaskState


instance Csv.ToField TaskState where
Expand Down Expand Up @@ -395,3 +393,56 @@ setMetadataField fieldNameText value task =
Just $ Object $ fromList [(Key.fromText fieldNameText, value)]
_ -> metadata task
}


{-| Convert a task to a YAML string that can be edited
| and then converted back to a task.
| Tags and notes are commented out, so they are not accidentally added again.
-}
taskToEditableYaml :: Connection -> Task -> P.IO P.ByteString
taskToEditableYaml conn task = do
(tags :: [[P.Text]]) <-
query
conn
[sql|
SELECT tag
FROM task_to_tag
WHERE task_ulid == ?
|]
(Only $ ulid task)

(notes :: [[P.Text]]) <-
query
conn
[sql|
SELECT note
FROM task_to_note
WHERE task_ulid == ?
|]
(Only $ ulid task)

let indentNoteContent noteContent =
noteContent
& T.strip
& T.lines
<&> T.stripEnd
& T.intercalate "\n# "

pure $
( task
& Yaml.encode
& P.decodeUtf8
)
<> "\n# | Existing tags and notes can't be edited here, \
\but new ones can be added\n\n"
<> (("# tags: " :: Text) <> P.show (P.concat tags) <> "\n")
<> "tags: []\n"
<> ( ("\n# notes:\n" :: Text)
<> ( notes
& P.concat
<&> (\note -> "# - " <> indentNoteContent note)
& T.unlines
)
)
<> "notes: []\n"
& P.encodeUtf8
4 changes: 4 additions & 0 deletions tasklite-core/source/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ x <$$> y = x <++> y
infixr 6 <$$>


vsepCollapse :: [Doc ann] -> Doc ann
vsepCollapse = P.foldr (<$$>) Empty


zeroTime :: DateTime
zeroTime = timeFromElapsedP 0

Expand Down
3 changes: 3 additions & 0 deletions tasklite-core/tasklite-core.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ test-suite tasklite-test
CliSpec
LibSpec
TestUtils
TypesSpec
Paths_tasklite_core
autogen-modules:
Paths_tasklite_core
Expand All @@ -159,11 +160,13 @@ test-suite tasklite-test
, base >=4.7 && <5
, hourglass
, hspec
, neat-interpolation
, optparse-applicative
, protolude
, sqlite-simple
, tasklite-core
, text
, yaml
default-language: GHC2021

benchmark tasklite-bench
Expand Down
2 changes: 2 additions & 0 deletions tasklite-core/test/Spec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ import TaskToNote qualified
import TaskToTag (TaskToTag)
import TaskToTag qualified
import TestUtils (withMemoryDb)
import TypesSpec qualified
import Utils (parseUlidText, parseUlidUtcSection, parseUtc, ulid2utc)


Expand Down Expand Up @@ -442,6 +443,7 @@ testSuite conf now = do
ulid2utc updatedTask.ulid `shouldBe` Just utcFromUlid
_ -> P.die "More than one task found"

TypesSpec.spec
LibSpec.spec now
CliSpec.spec

Expand Down
Loading

0 comments on commit a20a6d0

Please sign in to comment.