From 19980acc0c0103e13ca411c3f1b4fe5e0b921b7f Mon Sep 17 00:00:00 2001 From: Correl Date: Wed, 13 Jul 2022 00:04:35 -0400 Subject: [PATCH] WIP: Pagination --- src/Tutor/Api.hs | 12 +++++++++--- src/Tutor/Database.hs | 13 ++++++++----- src/Tutor/Pagination.hs | 12 ++++++++++++ src/Tutor/Select.hs | 2 +- 4 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 src/Tutor/Pagination.hs diff --git a/src/Tutor/Api.hs b/src/Tutor/Api.hs index f2699fb..5202464 100644 --- a/src/Tutor/Api.hs +++ b/src/Tutor/Api.hs @@ -27,9 +27,11 @@ import GHC.Generics (Generic) import qualified Paths_tutor as PT import Servant import Servant.OpenApi (HasOpenApi (toOpenApi)) +import qualified Tutor.Pagination as Pagination import Tutor.Card import Tutor.Config import Tutor.Database +import Data.Maybe (fromMaybe) data Status = Status { apiVersion :: T.Text, @@ -176,6 +178,8 @@ type SearchCards = :> QueryParam' '[Description "Query string"] "q" T.Text :> QueryParam' '[Description "Sorting method"] "sort_by" T.Text :> QueryParam' '[Description "Search across collection or all cards"] "in_collection" T.Text + :> QueryParam' '[Description "Pagination limit"] "limit" Int + :> QueryParam' '[Description "Pagination offset"] "offset" Int :> Get '[JSON] [Card] type TutorAPI = @@ -206,9 +210,11 @@ openapi = tutorServer :: Config -> Server TutorAPI tutorServer config = status config :<|> searchCards (tutorDatabase config) where - searchCards :: FilePath -> Maybe T.Text -> Maybe T.Text -> Maybe T.Text -> Handler [Card] - searchCards dbFile q sortBy inCollection = - liftIO $ Tutor.Database.searchCards dbFile q sortBy inCollection + searchCards :: FilePath -> Maybe T.Text -> Maybe T.Text -> Maybe T.Text -> Maybe Int -> Maybe Int -> Handler [Card] + searchCards dbFile q sortBy inCollection limit offset = + liftIO $ Pagination.items <$> Tutor.Database.searchCards dbFile q sortBy inCollection pagination + where pagination = Pagination.Pagination (fromMaybe 10 limit) (fromMaybe 0 offset) + docsServer :: Server DocsAPI docsServer = return openapi diff --git a/src/Tutor/Database.hs b/src/Tutor/Database.hs index 7ba9ebc..58fe9ea 100644 --- a/src/Tutor/Database.hs +++ b/src/Tutor/Database.hs @@ -14,12 +14,13 @@ import Database.SQLite.Simple.Internal import Database.SQLite.Simple.Ok import Database.SQLite.Simple.QQ import Tutor.Card +import qualified Tutor.Pagination as Pagination import qualified Tutor.Search as Search import Tutor.SearchParser import Tutor.Select ( Select (..), join, - limit, + limitOffset, orderBy, parameter, selectSimple, @@ -198,14 +199,16 @@ instance FromRow Card where } } -searchCards :: FilePath -> Maybe T.Text -> Maybe T.Text -> Maybe T.Text -> IO [Card] -searchCards dbFile q sortBy inCollection = +searchCards :: FilePath -> Maybe T.Text -> Maybe T.Text -> Maybe T.Text -> Pagination.Pagination -> IO (Pagination.Page Card) +searchCards dbFile q sortBy inCollection pagination = withConnection dbFile $ \conn -> - queryNamed + asPage <$> queryNamed conn (toQuery query) (selectParameters query) where + asPage results = + Pagination.Page Nothing Nothing results baseQuery = selectSimple [ "cards.scryfall_id", @@ -234,7 +237,7 @@ searchCards dbFile q sortBy inCollection = ELSE cards.color_identity END ASC|] <> orderBy "cards.name ASC" <> parameter ":last_update_key" ("last_update" :: T.Text) - <> limit 10 + <> limitOffset (Pagination.limit pagination) (Pagination.offset pagination) query = mconcat $ catMaybes diff --git a/src/Tutor/Pagination.hs b/src/Tutor/Pagination.hs new file mode 100644 index 0000000..38bbda1 --- /dev/null +++ b/src/Tutor/Pagination.hs @@ -0,0 +1,12 @@ +module Tutor.Pagination (Pagination(..), Page(..)) where + +data Pagination = Pagination + { limit :: Int + , offset :: Int + } + +data Page a = Page + { previous :: Maybe Pagination + , next :: Maybe Pagination + , items :: [a] + } diff --git a/src/Tutor/Select.hs b/src/Tutor/Select.hs index 3aae492..55820ff 100644 --- a/src/Tutor/Select.hs +++ b/src/Tutor/Select.hs @@ -96,7 +96,7 @@ toQuery select = [] -> Nothing xs -> Just $ "ORDER BY " <> sqlJoin ", " xs sqlLimitOffset = case (selectLimit select, selectOffset select) of - (Just l, Just o) -> Just "LIMIT :__limit, :__offset" + (Just l, Just o) -> Just "LIMIT :__limit OFFSET :__offset" (Just l, Nothing) -> Just "LIMIT :__limit" _ -> Nothing