module Request.Article exposing ( FeedConfig , ListConfig , create , defaultFeedConfig , defaultListConfig , delete , feed , get , list , tags , toggleFavorite , update ) import Data.Article as Article exposing (Article, Body, slugToString) import Data.Article.Feed as Feed exposing (Feed) import Data.Article.Tag as Tag exposing (Tag) import Data.AuthToken exposing (AuthToken, withAuthorization) import Data.User as User exposing (Username) import Http import HttpBuilder exposing (RequestBuilder, withBody, withExpect, withQueryParams) import Json.Decode as Decode import Json.Encode as Encode import Request.Helpers exposing (apiUrl) -- SINGLE -- get : Maybe AuthToken -> Article.Slug -> Http.Request (Article Body) get maybeToken slug = let expect = Article.decoderWithBody |> Decode.field "article" |> Http.expectJson in apiUrl ("/articles/" ++ Article.slugToString slug) |> HttpBuilder.get |> HttpBuilder.withExpect expect |> withAuthorization maybeToken |> HttpBuilder.toRequest -- LIST -- type alias ListConfig = { tag : Maybe Tag , author : Maybe Username , favorited : Maybe Username , limit : Int , offset : Int } defaultListConfig : ListConfig defaultListConfig = { tag = Nothing , author = Nothing , favorited = Nothing , limit = 20 , offset = 0 } list : ListConfig -> Maybe AuthToken -> Http.Request Feed list config maybeToken = [ ( "tag", Maybe.map Tag.toString config.tag ) , ( "author", Maybe.map User.usernameToString config.author ) , ( "favorited", Maybe.map User.usernameToString config.favorited ) , ( "limit", Just (toString config.limit) ) , ( "offset", Just (toString config.offset) ) ] |> List.filterMap maybeVal |> buildFromQueryParams "/articles" |> withAuthorization maybeToken |> HttpBuilder.toRequest -- FEED -- type alias FeedConfig = { limit : Int , offset : Int } defaultFeedConfig : FeedConfig defaultFeedConfig = { limit = 10 , offset = 0 } feed : FeedConfig -> AuthToken -> Http.Request Feed feed config token = [ ( "limit", Just (toString config.limit) ) , ( "offset", Just (toString config.offset) ) ] |> List.filterMap maybeVal |> buildFromQueryParams "/articles/feed" |> withAuthorization (Just token) |> HttpBuilder.toRequest -- TAGS -- tags : Http.Request (List Tag) tags = Decode.field "tags" (Decode.list Tag.decoder) |> Http.get (apiUrl "/tags") -- FAVORITE -- toggleFavorite : Article a -> AuthToken -> Http.Request (Article ()) toggleFavorite article authToken = if article.favorited then unfavorite article.slug authToken else favorite article.slug authToken favorite : Article.Slug -> AuthToken -> Http.Request (Article ()) favorite = buildFavorite HttpBuilder.post unfavorite : Article.Slug -> AuthToken -> Http.Request (Article ()) unfavorite = buildFavorite HttpBuilder.delete buildFavorite : (String -> RequestBuilder a) -> Article.Slug -> AuthToken -> Http.Request (Article ()) buildFavorite builderFromUrl slug token = let expect = Article.decoder |> Decode.field "article" |> Http.expectJson in [ apiUrl "/articles", slugToString slug, "favorite" ] |> String.join "/" |> builderFromUrl |> withAuthorization (Just token) |> withExpect expect |> HttpBuilder.toRequest -- CREATE -- type alias CreateConfig record = { record | title : String , description : String , body : String , tags : List Tag } type alias EditConfig record = { record | title : String , description : String , body : String } create : CreateConfig record -> AuthToken -> Http.Request (Article Body) create config token = let expect = Article.decoderWithBody |> Decode.field "article" |> Http.expectJson article = Encode.object [ ( "title", Encode.string config.title ) , ( "description", Encode.string config.description ) , ( "body", Encode.string config.body ) , ( "tagList", Encode.list (List.map Tag.encode config.tags) ) ] body = Encode.object [ ( "article", article ) ] |> Http.jsonBody in apiUrl "/articles" |> HttpBuilder.post |> withAuthorization (Just token) |> withBody body |> withExpect expect |> HttpBuilder.toRequest update : Article.Slug -> EditConfig record -> AuthToken -> Http.Request (Article Body) update slug config token = let expect = Article.decoderWithBody |> Decode.field "article" |> Http.expectJson article = Encode.object [ ( "title", Encode.string config.title ) , ( "description", Encode.string config.description ) , ( "body", Encode.string config.body ) ] body = Encode.object [ ( "article", article ) ] |> Http.jsonBody in apiUrl ("/articles/" ++ slugToString slug) |> HttpBuilder.put |> withAuthorization (Just token) |> withBody body |> withExpect expect |> HttpBuilder.toRequest -- DELETE -- delete : Article.Slug -> AuthToken -> Http.Request () delete slug token = apiUrl ("/articles/" ++ Article.slugToString slug) |> HttpBuilder.delete |> withAuthorization (Just token) |> HttpBuilder.toRequest -- HELPERS -- maybeVal : ( a, Maybe b ) -> Maybe ( a, b ) maybeVal ( key, value ) = case value of Nothing -> Nothing Just val -> Just ( key, val ) buildFromQueryParams : String -> List ( String, String ) -> RequestBuilder Feed buildFromQueryParams url queryParams = url |> apiUrl |> HttpBuilder.get |> withExpect (Http.expectJson Feed.decoder) |> withQueryParams queryParams