module Asana.Api.Task
( Task(..)
, Membership(..)
, TaskStatusFilter(..)
, ResourceSubtype(..)
, PostTask(..)
, getTask
, getProjectTasks
, getProjectTasksCompletedSince
, postTask
, addTag
, putCompleted
, taskUrl
, extractNumberField
, extractEnumField
) where
import Asana.Api.Prelude
import Asana.Api.CustomField
import Asana.Api.Gid
import Asana.Api.Named
import Asana.Api.Request
import Asana.Api.Tag
import Data.Aeson
import Data.Aeson.Casing (aesonPrefix, snakeCase)
import Data.HashMap.Strict (HashMap)
import qualified Data.Text as T
import Data.Time (UTCTime, getCurrentTime)
import Data.Time.ISO8601 (formatISO8601)
data Membership = Membership
{ Membership -> Named
mProject :: Named
, Membership -> Maybe Named
mSection :: Maybe Named
}
deriving stock (Membership -> Membership -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Membership -> Membership -> Bool
$c/= :: Membership -> Membership -> Bool
== :: Membership -> Membership -> Bool
$c== :: Membership -> Membership -> Bool
Eq, forall x. Rep Membership x -> Membership
forall x. Membership -> Rep Membership x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Membership x -> Membership
$cfrom :: forall x. Membership -> Rep Membership x
Generic, Int -> Membership -> ShowS
[Membership] -> ShowS
Membership -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Membership] -> ShowS
$cshowList :: [Membership] -> ShowS
show :: Membership -> String
$cshow :: Membership -> String
showsPrec :: Int -> Membership -> ShowS
$cshowsPrec :: Int -> Membership -> ShowS
Show)
instance FromJSON Membership where
parseJSON :: Value -> Parser Membership
parseJSON = forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON forall a b. (a -> b) -> a -> b
$ ShowS -> Options
aesonPrefix ShowS
snakeCase
data ResourceSubtype = DefaultTask | Milestone | Section
deriving stock (ResourceSubtype -> ResourceSubtype -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ResourceSubtype -> ResourceSubtype -> Bool
$c/= :: ResourceSubtype -> ResourceSubtype -> Bool
== :: ResourceSubtype -> ResourceSubtype -> Bool
$c== :: ResourceSubtype -> ResourceSubtype -> Bool
Eq, forall x. Rep ResourceSubtype x -> ResourceSubtype
forall x. ResourceSubtype -> Rep ResourceSubtype x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ResourceSubtype x -> ResourceSubtype
$cfrom :: forall x. ResourceSubtype -> Rep ResourceSubtype x
Generic, Int -> ResourceSubtype -> ShowS
[ResourceSubtype] -> ShowS
ResourceSubtype -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ResourceSubtype] -> ShowS
$cshowList :: [ResourceSubtype] -> ShowS
show :: ResourceSubtype -> String
$cshow :: ResourceSubtype -> String
showsPrec :: Int -> ResourceSubtype -> ShowS
$cshowsPrec :: Int -> ResourceSubtype -> ShowS
Show)
instance FromJSON ResourceSubtype where
parseJSON :: Value -> Parser ResourceSubtype
parseJSON =
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON forall a b. (a -> b) -> a -> b
$ Options
defaultOptions { constructorTagModifier :: ShowS
constructorTagModifier = ShowS
snakeCase }
data Task = Task
{ Task -> Maybe Named
tAssignee :: Maybe Named
, Task -> Text
tName :: Text
, Task -> Bool
tCompleted :: Bool
, Task -> Maybe UTCTime
tCompletedAt :: Maybe UTCTime
, Task -> UTCTime
tCreatedAt :: UTCTime
, Task -> CustomFields
tCustomFields :: CustomFields
, Task -> [Membership]
tMemberships :: [Membership]
, Task -> Gid
tGid :: Gid
, Task -> ResourceSubtype
tResourceSubtype :: ResourceSubtype
, Task -> Text
tNotes :: Text
, Task -> [AsanaReference]
tProjects :: [AsanaReference]
, Task -> [Tag]
tTags :: [Tag]
}
deriving stock (Task -> Task -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Task -> Task -> Bool
$c/= :: Task -> Task -> Bool
== :: Task -> Task -> Bool
$c== :: Task -> Task -> Bool
Eq, forall x. Rep Task x -> Task
forall x. Task -> Rep Task x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Task x -> Task
$cfrom :: forall x. Task -> Rep Task x
Generic, Int -> Task -> ShowS
[Task] -> ShowS
Task -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Task] -> ShowS
$cshowList :: [Task] -> ShowS
show :: Task -> String
$cshow :: Task -> String
showsPrec :: Int -> Task -> ShowS
$cshowsPrec :: Int -> Task -> ShowS
Show)
instance FromJSON Task where
parseJSON :: Value -> Parser Task
parseJSON = forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON forall a b. (a -> b) -> a -> b
$ ShowS -> Options
aesonPrefix ShowS
snakeCase
getTask
:: (MonadUnliftIO m, MonadLogger m, MonadReader env m, HasAsanaAccessKey env)
=> Gid
-> m Task
getTask :: forall (m :: * -> *) env.
(MonadUnliftIO m, MonadLogger m, MonadReader env m,
HasAsanaAccessKey env) =>
Gid -> m Task
getTask Gid
taskId = forall (m :: * -> *) env a.
(MonadUnliftIO m, MonadLogger m, MonadReader env m,
HasAsanaAccessKey env, FromJSON a) =>
String -> m a
getSingle forall a b. (a -> b) -> a -> b
$ String
"/tasks/" forall a. Semigroup a => a -> a -> a
<> Text -> String
T.unpack (Gid -> Text
gidToText Gid
taskId)
data PostTask = PostTask
{ PostTask -> [Gid]
ptProjects :: [Gid]
, PostTask -> HashMap Gid Text
ptCustomFields :: HashMap Gid Text
, PostTask -> Text
ptName :: Text
, PostTask -> Text
ptNotes :: Text
, PostTask -> Maybe Gid
ptParent :: Maybe Gid
}
deriving stock forall x. Rep PostTask x -> PostTask
forall x. PostTask -> Rep PostTask x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep PostTask x -> PostTask
$cfrom :: forall x. PostTask -> Rep PostTask x
Generic
instance FromJSON PostTask where
parseJSON :: Value -> Parser PostTask
parseJSON = forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON forall a b. (a -> b) -> a -> b
$ ShowS -> Options
aesonPrefix ShowS
snakeCase
instance ToJSON PostTask where
toJSON :: PostTask -> Value
toJSON = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON forall a b. (a -> b) -> a -> b
$ ShowS -> Options
aesonPrefix ShowS
snakeCase
toEncoding :: PostTask -> Encoding
toEncoding = forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
genericToEncoding forall a b. (a -> b) -> a -> b
$ ShowS -> Options
aesonPrefix ShowS
snakeCase
postTask
:: (MonadUnliftIO m, MonadLogger m, MonadReader env m, HasAsanaAccessKey env)
=> PostTask
-> m (Result Task)
postTask :: forall (m :: * -> *) env.
(MonadUnliftIO m, MonadLogger m, MonadReader env m,
HasAsanaAccessKey env) =>
PostTask -> m (Result Task)
postTask PostTask
body = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. ApiData a -> a
adData forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. FromJSON a => Value -> Result a
fromJSON forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) env a.
(MonadUnliftIO m, MonadLogger m, MonadReader env m,
HasAsanaAccessKey env, ToJSON a) =>
String -> a -> m Value
post String
"/tasks" (forall a. a -> ApiData a
ApiData PostTask
body)
getProjectTasks
:: (MonadUnliftIO m, MonadLogger m, MonadReader env m, HasAsanaAccessKey env)
=> Gid
-> TaskStatusFilter
-> m [Named]
getProjectTasks :: forall (m :: * -> *) env.
(MonadUnliftIO m, MonadLogger m, MonadReader env m,
HasAsanaAccessKey env) =>
Gid -> TaskStatusFilter -> m [Named]
getProjectTasks Gid
projectId TaskStatusFilter
taskStatusFilter = do
UTCTime
now <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO UTCTime
getCurrentTime
forall (m :: * -> *) env a.
(MonadUnliftIO m, MonadLogger m, MonadReader env m,
HasAsanaAccessKey env, FromJSON a) =>
String -> [(String, String)] -> m [a]
getAllParams
(Text -> String
T.unpack forall a b. (a -> b) -> a -> b
$ Text
"/projects/" forall a. Semigroup a => a -> a -> a
<> Gid -> Text
gidToText Gid
projectId forall a. Semigroup a => a -> a -> a
<> Text
"/tasks")
(UTCTime -> [(String, String)]
completedSince UTCTime
now)
where
completedSince :: UTCTime -> [(String, String)]
completedSince UTCTime
now = case TaskStatusFilter
taskStatusFilter of
TaskStatusFilter
AllTasks -> []
TaskStatusFilter
IncompletedTasks -> [(String
"completed_since", UTCTime -> String
formatISO8601 UTCTime
now)]
data TaskStatusFilter = IncompletedTasks | AllTasks
getProjectTasksCompletedSince
:: (MonadUnliftIO m, MonadLogger m, MonadReader env m, HasAsanaAccessKey env)
=> Gid
-> UTCTime
-> m [Named]
getProjectTasksCompletedSince :: forall (m :: * -> *) env.
(MonadUnliftIO m, MonadLogger m, MonadReader env m,
HasAsanaAccessKey env) =>
Gid -> UTCTime -> m [Named]
getProjectTasksCompletedSince Gid
projectId UTCTime
since = forall (m :: * -> *) env a.
(MonadUnliftIO m, MonadLogger m, MonadReader env m,
HasAsanaAccessKey env, FromJSON a) =>
String -> [(String, String)] -> m [a]
getAllParams
(Text -> String
T.unpack forall a b. (a -> b) -> a -> b
$ Text
"/projects/" forall a. Semigroup a => a -> a -> a
<> Gid -> Text
gidToText Gid
projectId forall a. Semigroup a => a -> a -> a
<> Text
"/tasks")
[(String
"completed_since", UTCTime -> String
formatISO8601 UTCTime
since)]
addTag
:: (MonadUnliftIO m, MonadLogger m, MonadReader env m, HasAsanaAccessKey env)
=> Gid
-> Gid
-> m ()
addTag :: forall (m :: * -> *) env.
(MonadUnliftIO m, MonadLogger m, MonadReader env m,
HasAsanaAccessKey env) =>
Gid -> Gid -> m ()
addTag Gid
task Gid
tag =
forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) env a.
(MonadUnliftIO m, MonadLogger m, MonadReader env m,
HasAsanaAccessKey env, ToJSON a) =>
String -> a -> m Value
post (String
"/tasks/" forall a. Semigroup a => a -> a -> a
<> Text -> String
T.unpack (Gid -> Text
gidToText Gid
task) forall a. Semigroup a => a -> a -> a
<> String
"/addTag") forall a b. (a -> b) -> a -> b
$ forall a. a -> ApiData a
ApiData
([Pair] -> Value
object [Key
"tag" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Gid
tag])
putCompleted
:: (MonadUnliftIO m, MonadLogger m, MonadReader env m, HasAsanaAccessKey env)
=> Gid
-> Bool
-> m ()
putCompleted :: forall (m :: * -> *) env.
(MonadUnliftIO m, MonadLogger m, MonadReader env m,
HasAsanaAccessKey env) =>
Gid -> Bool -> m ()
putCompleted Gid
taskId Bool
completed =
forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) env a.
(MonadUnliftIO m, MonadLogger m, MonadReader env m,
HasAsanaAccessKey env, ToJSON a) =>
String -> a -> m Value
put (String
"/tasks/" forall a. Semigroup a => a -> a -> a
<> Text -> String
T.unpack (Gid -> Text
gidToText Gid
taskId)) forall a b. (a -> b) -> a -> b
$ forall a. a -> ApiData a
ApiData
([Pair] -> Value
object [Key
"completed" forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Bool
completed])
taskUrl :: Task -> Text
taskUrl :: Task -> Text
taskUrl Task {Bool
[AsanaReference]
[Tag]
[Membership]
Maybe UTCTime
Maybe Named
UTCTime
Text
Gid
CustomFields
ResourceSubtype
tTags :: [Tag]
tProjects :: [AsanaReference]
tNotes :: Text
tResourceSubtype :: ResourceSubtype
tGid :: Gid
tMemberships :: [Membership]
tCustomFields :: CustomFields
tCreatedAt :: UTCTime
tCompletedAt :: Maybe UTCTime
tCompleted :: Bool
tName :: Text
tAssignee :: Maybe Named
tTags :: Task -> [Tag]
tProjects :: Task -> [AsanaReference]
tNotes :: Task -> Text
tResourceSubtype :: Task -> ResourceSubtype
tGid :: Task -> Gid
tMemberships :: Task -> [Membership]
tCustomFields :: Task -> CustomFields
tCreatedAt :: Task -> UTCTime
tCompletedAt :: Task -> Maybe UTCTime
tCompleted :: Task -> Bool
tName :: Task -> Text
tAssignee :: Task -> Maybe Named
..} = Text
"https://app.asana.com/0/0/" forall a. Semigroup a => a -> a -> a
<> Gid -> Text
gidToText Gid
tGid forall a. Semigroup a => a -> a -> a
<> Text
"/f"
extractNumberField :: Text -> Task -> Maybe CustomField
Text
fieldName Task {Bool
[AsanaReference]
[Tag]
[Membership]
Maybe UTCTime
Maybe Named
UTCTime
Text
Gid
CustomFields
ResourceSubtype
tTags :: [Tag]
tProjects :: [AsanaReference]
tNotes :: Text
tResourceSubtype :: ResourceSubtype
tGid :: Gid
tMemberships :: [Membership]
tCustomFields :: CustomFields
tCreatedAt :: UTCTime
tCompletedAt :: Maybe UTCTime
tCompleted :: Bool
tName :: Text
tAssignee :: Maybe Named
tTags :: Task -> [Tag]
tProjects :: Task -> [AsanaReference]
tNotes :: Task -> Text
tResourceSubtype :: Task -> ResourceSubtype
tGid :: Task -> Gid
tMemberships :: Task -> [Membership]
tCustomFields :: Task -> CustomFields
tCreatedAt :: Task -> UTCTime
tCompletedAt :: Task -> Maybe UTCTime
tCompleted :: Task -> Bool
tName :: Task -> Text
tAssignee :: Task -> Maybe Named
..} =
forall a. [a] -> Maybe a
listToMaybe forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (CustomFields -> [CustomField]
getCustomFields CustomFields
tCustomFields) forall a b. (a -> b) -> a -> b
$ \case
customField :: CustomField
customField@(CustomNumber Gid
_ Text
t Maybe Scientific
_) -> CustomField
customField forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Text
t forall a. Eq a => a -> a -> Bool
== Text
fieldName)
CustomField
_ -> forall a. Maybe a
Nothing
extractEnumField :: Text -> Task -> Maybe CustomField
Text
fieldName Task {Bool
[AsanaReference]
[Tag]
[Membership]
Maybe UTCTime
Maybe Named
UTCTime
Text
Gid
CustomFields
ResourceSubtype
tTags :: [Tag]
tProjects :: [AsanaReference]
tNotes :: Text
tResourceSubtype :: ResourceSubtype
tGid :: Gid
tMemberships :: [Membership]
tCustomFields :: CustomFields
tCreatedAt :: UTCTime
tCompletedAt :: Maybe UTCTime
tCompleted :: Bool
tName :: Text
tAssignee :: Maybe Named
tTags :: Task -> [Tag]
tProjects :: Task -> [AsanaReference]
tNotes :: Task -> Text
tResourceSubtype :: Task -> ResourceSubtype
tGid :: Task -> Gid
tMemberships :: Task -> [Membership]
tCustomFields :: Task -> CustomFields
tCreatedAt :: Task -> UTCTime
tCompletedAt :: Task -> Maybe UTCTime
tCompleted :: Task -> Bool
tName :: Task -> Text
tAssignee :: Task -> Maybe Named
..} =
forall a. [a] -> Maybe a
listToMaybe forall a b. (a -> b) -> a -> b
$ forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (CustomFields -> [CustomField]
getCustomFields CustomFields
tCustomFields) forall a b. (a -> b) -> a -> b
$ \case
customField :: CustomField
customField@(CustomEnum Gid
_ Text
t [EnumOption]
_ Maybe Text
_) ->
if Text
t forall a. Eq a => a -> a -> Bool
== Text
fieldName then forall a. a -> Maybe a
Just CustomField
customField else forall a. Maybe a
Nothing
CustomField
_ -> forall a. Maybe a
Nothing