{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE TupleSections #-}
module Network.DigitalOcean.Utils.Pagination where
import Data.Aeson
import Data.Aeson.Types
import qualified Data.Text as T
import qualified Data.Text as T
import Network.DigitalOcean.Types
import qualified Data.Set as Set
paginate
:: (Paginatable a, FromJSON (PaginationState a))
=> (String -> DO (PaginationState a))
-> PaginationState a
-> DO (PaginationState a)
paginate f s =
case nextUrl s of
Just url -> do
newState <- f url
return $ newState { curr = curr s ++ curr newState }
Nothing -> return s { isLast = True }
paginationQueryParams :: Maybe PaginationConfig -> QueryParams
paginationQueryParams Nothing = []
paginationQueryParams (Just (PaginationConfig pageSize _)) = [("per_page", show pageSize)]
paginateUntil
:: (Paginatable a, FromJSON (PaginationState a))
=> PaginationConfig
-> PaginationState a
-> (String -> DO (PaginationState a))
-> DO (PaginationState a)
paginateUntil config@PaginationConfig {..} state@PaginationState {..} f =
if length curr >= resultLimit || isLast
then
return state
else do
newState <- paginate f state
paginateUntil config newState f
(/?) :: FromJSON a => Parser (Maybe Object) -> T.Text -> Parser (Maybe a)
maybeParser /? key = maybeParser >>= maybe (return Nothing) (.:? key)
parsePaginationState :: Paginatable a => Object -> T.Text -> Parser (PaginationState a)
parsePaginationState v key = do
values <- v .: key
(next, total) <- parse_meta
let page = 1
return $ PaginationState values page next total False
where
parse_meta :: Parser (Maybe String, Maybe Int)
parse_meta =
(,)
<$> v .:? "links" /? "pages" /? "next"
<*> (v .:? "meta" /? "total")