@@ -69,7 +69,7 @@ import Data.Text qualified as T
69
69
import Data.Text.Lazy qualified as TL
70
70
import Data.Text.Lazy.Encoding qualified as TL
71
71
import Data.ULID (ulidFromInteger )
72
- import Data.ULID.TimeStamp (getULIDTimeStamp )
72
+ import Data.ULID.TimeStamp (ULIDTimeStamp , getULIDTimeStamp )
73
73
import Data.Vector qualified as V
74
74
import Data.Yaml (
75
75
ParseException (InvalidYaml ),
@@ -89,6 +89,7 @@ import ImportTask (
89
89
setMissingFields ,
90
90
)
91
91
import Lib (
92
+ addEmptyTask ,
92
93
execWithConn ,
93
94
execWithTask ,
94
95
insertNotes ,
@@ -116,9 +117,10 @@ import Prettyprinter.Render.Terminal (
116
117
)
117
118
import System.Directory (createDirectoryIfMissing , listDirectory , removeFile )
118
119
import System.FilePath (isExtensionOf , takeExtension , (</>) )
120
+ import System.Hourglass (timeCurrentP )
119
121
import System.Posix.User (getEffectiveUserName )
120
122
import System.Process (readProcess )
121
- import Task (Task (.. ), setMetadataField , taskToEditableMarkdown )
123
+ import Task (Task (.. ), emptyTask , setMetadataField , taskToEditableMarkdown )
122
124
import Text.Editor (runUserEditorDWIM , yamlTemplate )
123
125
import Text.Parsec.Rfc2822 qualified as Email
124
126
import Text.ParserCombinators.Parsec as Parsec (parse )
@@ -128,6 +130,7 @@ import Utils (
128
130
IdText ,
129
131
countCharTL ,
130
132
emptyUlid ,
133
+ formatElapsedP ,
131
134
setDateTime ,
132
135
ulidTextToDateTime ,
133
136
zeroUlidTxt ,
@@ -631,6 +634,132 @@ editUntilValidMarkdown editMode conn initialMarkdown wipMarkdown = do
631
634
pure $ Right (newTask, BSL. toStrict yamlContent)
632
635
633
636
637
+ insertTaskFromEdit ::
638
+ Config ->
639
+ Connection ->
640
+ ImportTask ->
641
+ P. ByteString ->
642
+ P. Text ->
643
+ IO (Doc AnsiStyle )
644
+ insertTaskFromEdit conf conn importTaskRec newContent modified_utc = do
645
+ -- Insert empty task if the edited task was newly created
646
+ ulid <-
647
+ if T. null importTaskRec. task. ulid
648
+ then addEmptyTask conf conn <&> Task. ulid
649
+ else pure importTaskRec. task. ulid
650
+
651
+ effectiveUserName <- getEffectiveUserName
652
+ now <- getULIDTimeStamp <&> (show @ ULIDTimeStamp >>> T. toLower)
653
+ let
654
+ parseMetadata :: Value -> Parser Bool
655
+ parseMetadata val = case val of
656
+ Object obj -> do
657
+ let mdataMaybe = KeyMap. lookup " metadata" obj
658
+ pure $ case mdataMaybe of
659
+ Just (Object _) -> True
660
+ _ -> False
661
+ _ -> pure False
662
+
663
+ hasMetadata =
664
+ parseMaybe parseMetadata
665
+ =<< rightToMaybe (Yaml. decodeEither' newContent)
666
+
667
+ taskFixed =
668
+ importTaskRec. task
669
+ { Task. ulid = ulid
670
+ , Task. user =
671
+ if importTaskRec. task. user == " "
672
+ then T. pack effectiveUserName
673
+ else importTaskRec. task. user
674
+ , Task. metadata =
675
+ if hasMetadata == Just True
676
+ then importTaskRec. task. metadata
677
+ else Nothing
678
+ , -- Set to previous value to force SQL trigger to update it
679
+ Task. modified_utc = modified_utc
680
+ }
681
+ notesCorrectUtc =
682
+ importTaskRec. notes
683
+ <&> ( \ note ->
684
+ note
685
+ { Note. ulid =
686
+ if zeroUlidTxt `T.isPrefixOf` note. ulid
687
+ then note. ulid & T. replace zeroUlidTxt now
688
+ else note. ulid
689
+ }
690
+ )
691
+
692
+ updateTask conn taskFixed
693
+
694
+ nowDateTime <- dateCurrent
695
+
696
+ let taskFixedUtc =
697
+ if P. isNothing taskFixed. closed_utc
698
+ then taskFixed
699
+ else
700
+ taskFixed
701
+ { Task. modified_utc =
702
+ nowDateTime
703
+ & timePrint (toFormat importUtcFormat)
704
+ & T. pack
705
+ }
706
+
707
+ -- TODO: Remove after it was added to `createSetClosedUtcTrigger`
708
+ -- Update again with the same `state` field to avoid firing
709
+ -- SQL trigger which would overwrite the `closed_utc` field.
710
+ P. when (P. isJust taskFixed. closed_utc) $ do
711
+ updateTask conn taskFixedUtc
712
+
713
+ tagWarnings <- insertTags conn Nothing taskFixedUtc importTaskRec. tags
714
+ noteWarnings <- insertNotes conn Nothing taskFixedUtc notesCorrectUtc
715
+
716
+ args <- P. getArgs
717
+ postModifyResults <-
718
+ executeHooks
719
+ ( TL. toStrict $
720
+ TL. decodeUtf8 $
721
+ Aeson. encode $
722
+ object
723
+ [ " arguments" .= args
724
+ , " taskModified" .= taskFixedUtc
725
+ -- TODO: Add tags and notes to task
726
+ ]
727
+ )
728
+ conf. hooks. modify. post
729
+
730
+ let postModifyHookMsg =
731
+ ( postModifyResults
732
+ <&> \ case
733
+ Left error -> " ERROR:" <+> pretty error
734
+ Right hookResult -> pretty hookResult. message
735
+ & P. fold
736
+ )
737
+ <> hardline
738
+
739
+ pure $
740
+ tagWarnings
741
+ <$$> noteWarnings
742
+ <$$> " ✏️ Edited task"
743
+ <+> dquotes (pretty taskFixed. body)
744
+ <+> " with ulid"
745
+ <+> dquotes (pretty taskFixed. ulid)
746
+ <!!> postModifyHookMsg
747
+
748
+
749
+ enterTask :: Config -> Connection -> IO (Doc AnsiStyle )
750
+ enterTask conf conn = do
751
+ taskMarkdown <- taskToEditableMarkdown conn emptyTask
752
+ taskMarkdownTupleRes <-
753
+ editUntilValidMarkdown OpenEditorRequireEdit conn taskMarkdown taskMarkdown
754
+ case taskMarkdownTupleRes of
755
+ Left error -> case error of
756
+ InvalidYaml (Just (YamlException " " )) -> pure P. mempty
757
+ _ -> pure $ pretty $ Yaml. prettyPrintParseException error
758
+ Right (importTaskRec, newContent) -> do
759
+ modified_utc <- formatElapsedP conf timeCurrentP
760
+ insertTaskFromEdit conf conn importTaskRec newContent modified_utc
761
+
762
+
634
763
editTaskByTask :: Config -> EditMode -> Connection -> Task -> IO (Doc AnsiStyle )
635
764
editTaskByTask conf editMode conn taskToEdit = do
636
765
taskMarkdown <- taskToEditableMarkdown conn taskToEdit
@@ -641,101 +770,12 @@ editTaskByTask conf editMode conn taskToEdit = do
641
770
InvalidYaml (Just (YamlException " " )) -> pure P. mempty
642
771
_ -> pure $ pretty $ Yaml. prettyPrintParseException error
643
772
Right (importTaskRec, newContent) -> do
644
- effectiveUserName <- getEffectiveUserName
645
- now <- getULIDTimeStamp <&> (show >>> T. toLower)
646
- let
647
- parseMetadata :: Value -> Parser Bool
648
- parseMetadata val = case val of
649
- Object obj -> do
650
- let mdataMaybe = KeyMap. lookup " metadata" obj
651
- pure $ case mdataMaybe of
652
- Just (Object _) -> True
653
- _ -> False
654
- _ -> pure False
655
-
656
- hasMetadata =
657
- parseMaybe parseMetadata
658
- =<< rightToMaybe (Yaml. decodeEither' newContent)
659
-
660
- taskFixed =
661
- importTaskRec. task
662
- { Task. user =
663
- if importTaskRec. task. user == " "
664
- then T. pack effectiveUserName
665
- else importTaskRec. task. user
666
- , Task. metadata =
667
- if hasMetadata == Just True
668
- then importTaskRec. task. metadata
669
- else Nothing
670
- , -- Set to previous value to force SQL trigger to update it
671
- Task. modified_utc = taskToEdit. modified_utc
672
- }
673
- notesCorrectUtc =
674
- importTaskRec. notes
675
- <&> ( \ note ->
676
- note
677
- { Note. ulid =
678
- if zeroUlidTxt `T.isPrefixOf` note. ulid
679
- then note. ulid & T. replace zeroUlidTxt now
680
- else note. ulid
681
- }
682
- )
683
-
684
- updateTask conn taskFixed
685
-
686
- nowDateTime <- dateCurrent
687
-
688
- let taskFixedUtc =
689
- if P. isNothing taskFixed. closed_utc
690
- then taskFixed
691
- else
692
- taskFixed
693
- { Task. modified_utc =
694
- nowDateTime
695
- & timePrint (toFormat importUtcFormat)
696
- & T. pack
697
- }
698
-
699
- -- TODO: Remove after it was added to `createSetClosedUtcTrigger`
700
- -- Update again with the same `state` field to avoid firing
701
- -- SQL trigger which would overwrite the `closed_utc` field.
702
- P. when (P. isJust taskFixed. closed_utc) $ do
703
- updateTask conn taskFixedUtc
704
-
705
- tagWarnings <- insertTags conn Nothing taskFixedUtc importTaskRec. tags
706
- noteWarnings <- insertNotes conn Nothing taskFixedUtc notesCorrectUtc
707
-
708
- args <- P. getArgs
709
- postModifyResults <-
710
- executeHooks
711
- ( TL. toStrict $
712
- TL. decodeUtf8 $
713
- Aeson. encode $
714
- object
715
- [ " arguments" .= args
716
- , " taskModified" .= taskFixedUtc
717
- -- TODO: Add tags and notes to task
718
- ]
719
- )
720
- conf. hooks. modify. post
721
-
722
- let postModifyHookMsg =
723
- ( postModifyResults
724
- <&> \ case
725
- Left error -> " ERROR:" <+> pretty error
726
- Right hookResult -> pretty hookResult. message
727
- & P. fold
728
- )
729
- <> hardline
730
-
731
- pure $
732
- tagWarnings
733
- <$$> noteWarnings
734
- <$$> " ✏️ Edited task"
735
- <+> dquotes (pretty taskFixed. body)
736
- <+> " with ulid"
737
- <+> dquotes (pretty taskFixed. ulid)
738
- <!!> postModifyHookMsg
773
+ insertTaskFromEdit
774
+ conf
775
+ conn
776
+ importTaskRec
777
+ newContent
778
+ taskToEdit. modified_utc
739
779
740
780
741
781
-- TODO: Eliminate code duplications with `addTask`
0 commit comments