module MathiasSM.Yaml.Project (
Status (..),
statusName,
Project (..),
parseProject,
parseProjectYaml,
) where
import Control.Monad ((>=>))
import Data.Aeson (FromJSON (parseJSON), Object)
import Data.Maybe (fromMaybe)
import Data.Time (Day)
import MathiasSM.Metadata qualified as K
import MathiasSM.Yaml (Check (runCheck), decodeYaml, enumFromJSON, optional, required)
data Status = Alpha | Finished | Ongoing | Unmaintained
deriving (Status -> Status -> Bool
(Status -> Status -> Bool)
-> (Status -> Status -> Bool) -> Eq Status
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Status -> Status -> Bool
== :: Status -> Status -> Bool
$c/= :: Status -> Status -> Bool
/= :: Status -> Status -> Bool
Eq, Int -> Status -> ShowS
[Status] -> ShowS
Status -> String
(Int -> Status -> ShowS)
-> (Status -> String) -> ([Status] -> ShowS) -> Show Status
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Status -> ShowS
showsPrec :: Int -> Status -> ShowS
$cshow :: Status -> String
show :: Status -> String
$cshowList :: [Status] -> ShowS
showList :: [Status] -> ShowS
Show, Int -> Status
Status -> Int
Status -> [Status]
Status -> Status
Status -> Status -> [Status]
Status -> Status -> Status -> [Status]
(Status -> Status)
-> (Status -> Status)
-> (Int -> Status)
-> (Status -> Int)
-> (Status -> [Status])
-> (Status -> Status -> [Status])
-> (Status -> Status -> [Status])
-> (Status -> Status -> Status -> [Status])
-> Enum Status
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Status -> Status
succ :: Status -> Status
$cpred :: Status -> Status
pred :: Status -> Status
$ctoEnum :: Int -> Status
toEnum :: Int -> Status
$cfromEnum :: Status -> Int
fromEnum :: Status -> Int
$cenumFrom :: Status -> [Status]
enumFrom :: Status -> [Status]
$cenumFromThen :: Status -> Status -> [Status]
enumFromThen :: Status -> Status -> [Status]
$cenumFromTo :: Status -> Status -> [Status]
enumFromTo :: Status -> Status -> [Status]
$cenumFromThenTo :: Status -> Status -> Status -> [Status]
enumFromThenTo :: Status -> Status -> Status -> [Status]
Enum, Status
Status -> Status -> Bounded Status
forall a. a -> a -> Bounded a
$cminBound :: Status
minBound :: Status
$cmaxBound :: Status
maxBound :: Status
Bounded)
statusName :: Status -> String
statusName :: Status -> String
statusName Status
Alpha = String
"alpha"
statusName Status
Finished = String
"finished"
statusName Status
Ongoing = String
"ongoing"
statusName Status
Unmaintained = String
"unmaintained"
instance FromJSON Status where
parseJSON :: Value -> Parser Status
parseJSON = String -> (Status -> String) -> Value -> Parser Status
forall a.
(Enum a, Bounded a) =>
String -> (a -> String) -> Value -> Parser a
enumFromJSON String
"status" Status -> String
statusName
data Project = Project
{ Project -> String
projectTitle :: String
, Project -> String
projectHref :: String
, Project -> Status
projectStatus :: Status
, Project -> Day
projectStart :: Day
, Project -> Maybe Day
projectEnd :: Maybe Day
, Project -> String
projectShortDescription :: String
, Project -> String
projectLongDescription :: String
, Project -> [String]
projectTeam :: [String]
, Project -> Maybe Int
projectPriority :: Maybe Int
}
deriving (Project -> Project -> Bool
(Project -> Project -> Bool)
-> (Project -> Project -> Bool) -> Eq Project
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Project -> Project -> Bool
== :: Project -> Project -> Bool
$c/= :: Project -> Project -> Bool
/= :: Project -> Project -> Bool
Eq, Int -> Project -> ShowS
[Project] -> ShowS
Project -> String
(Int -> Project -> ShowS)
-> (Project -> String) -> ([Project] -> ShowS) -> Show Project
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Project -> ShowS
showsPrec :: Int -> Project -> ShowS
$cshow :: Project -> String
show :: Project -> String
$cshowList :: [Project] -> ShowS
showList :: [Project] -> ShowS
Show)
parseProject :: Object -> Either [String] Project
parseProject :: Object -> Either [String] Project
parseProject Object
o =
Check Project -> Either [String] Project
forall a. Check a -> Either [String] a
runCheck
( String
-> String
-> Status
-> Day
-> Maybe Day
-> String
-> String
-> [String]
-> Maybe Int
-> Project
Project
(String
-> String
-> Status
-> Day
-> Maybe Day
-> String
-> String
-> [String]
-> Maybe Int
-> Project)
-> Check String
-> Check
(String
-> Status
-> Day
-> Maybe Day
-> String
-> String
-> [String]
-> Maybe Int
-> Project)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object -> Key -> Check String
forall a. FromJSON a => Object -> Key -> Check a
required Object
o Key
K.Title
Check
(String
-> Status
-> Day
-> Maybe Day
-> String
-> String
-> [String]
-> Maybe Int
-> Project)
-> Check String
-> Check
(Status
-> Day
-> Maybe Day
-> String
-> String
-> [String]
-> Maybe Int
-> Project)
forall a b. Check (a -> b) -> Check a -> Check b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object -> Key -> Check String
forall a. FromJSON a => Object -> Key -> Check a
required Object
o Key
K.Href
Check
(Status
-> Day
-> Maybe Day
-> String
-> String
-> [String]
-> Maybe Int
-> Project)
-> Check Status
-> Check
(Day
-> Maybe Day
-> String
-> String
-> [String]
-> Maybe Int
-> Project)
forall a b. Check (a -> b) -> Check a -> Check b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object -> Key -> Check Status
forall a. FromJSON a => Object -> Key -> Check a
required Object
o Key
K.Status
Check
(Day
-> Maybe Day
-> String
-> String
-> [String]
-> Maybe Int
-> Project)
-> Check Day
-> Check
(Maybe Day -> String -> String -> [String] -> Maybe Int -> Project)
forall a b. Check (a -> b) -> Check a -> Check b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object -> Key -> Check Day
forall a. FromJSON a => Object -> Key -> Check a
required Object
o Key
K.StartDate
Check
(Maybe Day -> String -> String -> [String] -> Maybe Int -> Project)
-> Check (Maybe Day)
-> Check (String -> String -> [String] -> Maybe Int -> Project)
forall a b. Check (a -> b) -> Check a -> Check b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object -> Key -> Check (Maybe Day)
forall a. FromJSON a => Object -> Key -> Check (Maybe a)
optional Object
o Key
K.EndDate
Check (String -> String -> [String] -> Maybe Int -> Project)
-> Check String
-> Check (String -> [String] -> Maybe Int -> Project)
forall a b. Check (a -> b) -> Check a -> Check b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object -> Key -> Check String
forall a. FromJSON a => Object -> Key -> Check a
required Object
o Key
K.ShortDescription
Check (String -> [String] -> Maybe Int -> Project)
-> Check String -> Check ([String] -> Maybe Int -> Project)
forall a b. Check (a -> b) -> Check a -> Check b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object -> Key -> Check String
forall a. FromJSON a => Object -> Key -> Check a
required Object
o Key
K.LongDescription
Check ([String] -> Maybe Int -> Project)
-> Check [String] -> Check (Maybe Int -> Project)
forall a b. Check (a -> b) -> Check a -> Check b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ([String] -> Maybe [String] -> [String]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [String] -> [String])
-> Check (Maybe [String]) -> Check [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Object -> Key -> Check (Maybe [String])
forall a. FromJSON a => Object -> Key -> Check (Maybe a)
optional Object
o Key
K.Team)
Check (Maybe Int -> Project) -> Check (Maybe Int) -> Check Project
forall a b. Check (a -> b) -> Check a -> Check b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Object -> Key -> Check (Maybe Int)
forall a. FromJSON a => Object -> Key -> Check (Maybe a)
optional Object
o Key
K.Priority
)
Either [String] Project
-> (Project -> Either [String] Project) -> Either [String] Project
forall a b.
Either [String] a -> (a -> Either [String] b) -> Either [String] b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Project -> Either [String] Project
endsAfterStart
where
endsAfterStart :: Project -> Either [String] Project
endsAfterStart Project
project = case Project -> Maybe Day
projectEnd Project
project of
Just Day
end | Day
end Day -> Day -> Bool
forall a. Ord a => a -> a -> Bool
< Project -> Day
projectStart Project
project -> [String] -> Either [String] Project
forall a b. a -> Either a b
Left [String
"endDate: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Day -> String
forall a. Show a => a -> String
show Day
end String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
" is before startDate " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Day -> String
forall a. Show a => a -> String
show (Project -> Day
projectStart Project
project)]
Maybe Day
_ -> Project -> Either [String] Project
forall a b. b -> Either a b
Right Project
project
parseProjectYaml :: String -> Either [String] Project
parseProjectYaml :: String -> Either [String] Project
parseProjectYaml = String -> Either [String] Object
forall a. FromJSON a => String -> Either [String] a
decodeYaml (String -> Either [String] Object)
-> (Object -> Either [String] Project)
-> String
-> Either [String] Project
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> Object -> Either [String] Project
parseProject