asana-1.0.0.0: library/Asana/Api/CustomField.hs
module Asana.Api.CustomField
( CustomField(..)
, CustomFields(..)
, customEnumId
, EnumOption(..)
, putCustomField
, putCustomFields
) where
import Asana.Api.Prelude
import Asana.Api.Gid (Gid, gidToText)
import Asana.Api.Request
import Data.Aeson
import Data.Aeson.Casing (aesonPrefix, snakeCase)
import Data.List (find)
import Data.Scientific (Scientific)
import Data.String (fromString)
import qualified Data.Text as T
data CustomField
= CustomNumber Gid Text (Maybe Scientific)
| CustomEnum Gid Text [EnumOption] (Maybe Text)
| CustomText Gid Text (Maybe Text)
| Other -- ^ Unexpected types dumped here
deriving stock (Eq, Generic, Show)
newtype CustomFields = CustomFields { getCustomFields :: [CustomField] }
deriving stock (Show, Eq)
deriving newtype (FromJSON)
instance ToJSON CustomFields where
toJSON (CustomFields fields) = object $ concatMap toPair fields
where
toPair = \case
CustomNumber gid _ n -> [gidToKey gid .= n]
e@(CustomEnum gid _ _ _) -> [gidToKey gid .= customEnumId e]
_ -> []
-- fromString will give us Text for aeson-1.x and Key for aeson-2.x
gidToKey = fromString . T.unpack . gidToText
data EnumOption = EnumOption
{ eoGid :: Gid
, eoName :: Text
}
deriving stock (Eq, Generic, Show)
instance FromJSON EnumOption where
parseJSON = genericParseJSON $ aesonPrefix snakeCase
-- | Return a @'CustomField'@s value's Enum id, if possible
--
-- - Must be a @'CustomEnum'@
-- - Must have a value
-- - Must have an option with the same name as that value
--
customEnumId :: CustomField -> Maybe Gid
customEnumId (CustomEnum _ _ opts mValue) = do
value <- mValue
option <- find ((== value) . eoName) opts
pure $ eoGid option
customEnumId _ = Nothing
instance FromJSON CustomField where
parseJSON = withObject "CustomField" $ \o -> do
oType <- o .: "type"
case (oType :: Text) of
"text" -> CustomText <$> o .: "gid" <*> o .: "name" <*> o .: "text_value"
"number" ->
CustomNumber <$> o .: "gid" <*> o .: "name" <*> o .: "number_value"
"enum" -> do
value <- o .: "enum_value"
CustomEnum
<$> (o .: "gid")
<*> (o .: "name")
<*> (o .: "enum_options")
<*> case value of
Object vo -> vo .:? "name"
_ -> pure Nothing
_ -> pure Other
putCustomField
:: (MonadUnliftIO m, MonadLogger m, MonadReader env m, HasAsanaAccessKey env)
=> Gid
-> CustomField
-> m ()
putCustomField taskId = putCustomFields taskId . CustomFields . pure
putCustomFields
:: (MonadUnliftIO m, MonadLogger m, MonadReader env m, HasAsanaAccessKey env)
=> Gid
-> CustomFields
-> m ()
putCustomFields taskId fields =
void $ put ("/tasks/" <> T.unpack (gidToText taskId)) $ ApiData
(object ["custom_fields" .= fields])