Add finished/
This commit is contained in:
271
finished/src/Request/Article.elm
Normal file
271
finished/src/Request/Article.elm
Normal file
@@ -0,0 +1,271 @@
|
||||
module Request.Article
|
||||
exposing
|
||||
( FeedConfig
|
||||
, ListConfig
|
||||
, create
|
||||
, defaultFeedConfig
|
||||
, defaultListConfig
|
||||
, delete
|
||||
, feed
|
||||
, get
|
||||
, list
|
||||
, tags
|
||||
, toggleFavorite
|
||||
, update
|
||||
)
|
||||
|
||||
import Data.Article as Article exposing (Article, Body, Tag, slugToString)
|
||||
import Data.Article.Feed as Feed exposing (Feed)
|
||||
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 Article.tagToString 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 Article.tagDecoder)
|
||||
|> 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 String
|
||||
}
|
||||
|
||||
|
||||
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 Encode.string 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
|
||||
53
finished/src/Request/Article/Comments.elm
Normal file
53
finished/src/Request/Article/Comments.elm
Normal file
@@ -0,0 +1,53 @@
|
||||
module Request.Article.Comments exposing (delete, list, post)
|
||||
|
||||
import Data.Article as Article exposing (Article, Tag, slugToString)
|
||||
import Data.Article.Comment as Comment exposing (Comment, CommentId)
|
||||
import Data.AuthToken exposing (AuthToken, withAuthorization)
|
||||
import Http
|
||||
import HttpBuilder exposing (RequestBuilder, withExpect, withQueryParams)
|
||||
import Json.Decode as Decode
|
||||
import Json.Encode as Encode exposing (Value)
|
||||
import Request.Helpers exposing (apiUrl)
|
||||
|
||||
|
||||
-- LIST --
|
||||
|
||||
|
||||
list : Maybe AuthToken -> Article.Slug -> Http.Request (List Comment)
|
||||
list maybeToken slug =
|
||||
apiUrl ("/articles/" ++ Article.slugToString slug ++ "/comments")
|
||||
|> HttpBuilder.get
|
||||
|> HttpBuilder.withExpect (Http.expectJson (Decode.field "comments" (Decode.list Comment.decoder)))
|
||||
|> withAuthorization maybeToken
|
||||
|> HttpBuilder.toRequest
|
||||
|
||||
|
||||
|
||||
-- POST --
|
||||
|
||||
|
||||
post : Article.Slug -> String -> AuthToken -> Http.Request Comment
|
||||
post slug body token =
|
||||
apiUrl ("/articles/" ++ Article.slugToString slug ++ "/comments")
|
||||
|> HttpBuilder.post
|
||||
|> HttpBuilder.withBody (Http.jsonBody (encodeCommentBody body))
|
||||
|> HttpBuilder.withExpect (Http.expectJson (Decode.field "comment" Comment.decoder))
|
||||
|> withAuthorization (Just token)
|
||||
|> HttpBuilder.toRequest
|
||||
|
||||
|
||||
encodeCommentBody : String -> Value
|
||||
encodeCommentBody body =
|
||||
Encode.object [ ( "comment", Encode.object [ ( "body", Encode.string body ) ] ) ]
|
||||
|
||||
|
||||
|
||||
-- DELETE --
|
||||
|
||||
|
||||
delete : Article.Slug -> CommentId -> AuthToken -> Http.Request ()
|
||||
delete slug commentId token =
|
||||
apiUrl ("/articles/" ++ Article.slugToString slug ++ "/comments/" ++ Comment.idToString commentId)
|
||||
|> HttpBuilder.delete
|
||||
|> withAuthorization (Just token)
|
||||
|> HttpBuilder.toRequest
|
||||
6
finished/src/Request/Helpers.elm
Normal file
6
finished/src/Request/Helpers.elm
Normal file
@@ -0,0 +1,6 @@
|
||||
module Request.Helpers exposing (apiUrl)
|
||||
|
||||
|
||||
apiUrl : String -> String
|
||||
apiUrl str =
|
||||
"http://localhost:3000/api" ++ str
|
||||
57
finished/src/Request/Profile.elm
Normal file
57
finished/src/Request/Profile.elm
Normal file
@@ -0,0 +1,57 @@
|
||||
module Request.Profile exposing (get, toggleFollow)
|
||||
|
||||
import Data.AuthToken exposing (AuthToken, withAuthorization)
|
||||
import Data.Profile as Profile exposing (Profile)
|
||||
import Data.User as User exposing (Username)
|
||||
import Http
|
||||
import HttpBuilder exposing (RequestBuilder, withExpect, withQueryParams)
|
||||
import Json.Decode as Decode
|
||||
import Request.Helpers exposing (apiUrl)
|
||||
|
||||
|
||||
-- GET --
|
||||
|
||||
|
||||
get : Username -> Maybe AuthToken -> Http.Request Profile
|
||||
get username maybeToken =
|
||||
apiUrl ("/profiles/" ++ User.usernameToString username)
|
||||
|> HttpBuilder.get
|
||||
|> HttpBuilder.withExpect (Http.expectJson (Decode.field "profile" Profile.decoder))
|
||||
|> withAuthorization maybeToken
|
||||
|> HttpBuilder.toRequest
|
||||
|
||||
|
||||
|
||||
-- FOLLOWING --
|
||||
|
||||
|
||||
toggleFollow : Username -> Bool -> AuthToken -> Http.Request Profile
|
||||
toggleFollow username following authToken =
|
||||
if following then
|
||||
unfollow username authToken
|
||||
else
|
||||
follow username authToken
|
||||
|
||||
|
||||
follow : Username -> AuthToken -> Http.Request Profile
|
||||
follow =
|
||||
buildFollow HttpBuilder.post
|
||||
|
||||
|
||||
unfollow : Username -> AuthToken -> Http.Request Profile
|
||||
unfollow =
|
||||
buildFollow HttpBuilder.delete
|
||||
|
||||
|
||||
buildFollow :
|
||||
(String -> RequestBuilder a)
|
||||
-> Username
|
||||
-> AuthToken
|
||||
-> Http.Request Profile
|
||||
buildFollow builderFromUrl username token =
|
||||
[ apiUrl "/profiles", User.usernameToString username, "follow" ]
|
||||
|> String.join "/"
|
||||
|> builderFromUrl
|
||||
|> withAuthorization (Just token)
|
||||
|> withExpect (Http.expectJson (Decode.field "profile" Profile.decoder))
|
||||
|> HttpBuilder.toRequest
|
||||
94
finished/src/Request/User.elm
Normal file
94
finished/src/Request/User.elm
Normal file
@@ -0,0 +1,94 @@
|
||||
module Request.User exposing (edit, login, register, storeSession)
|
||||
|
||||
import Data.AuthToken exposing (AuthToken, withAuthorization)
|
||||
import Data.User as User exposing (User)
|
||||
import Http
|
||||
import HttpBuilder exposing (RequestBuilder, withExpect, withQueryParams)
|
||||
import Json.Decode as Decode
|
||||
import Json.Encode as Encode
|
||||
import Json.Encode.Extra as EncodeExtra
|
||||
import Ports
|
||||
import Request.Helpers exposing (apiUrl)
|
||||
|
||||
|
||||
storeSession : User -> Cmd msg
|
||||
storeSession user =
|
||||
User.encode user
|
||||
|> Encode.encode 0
|
||||
|> Just
|
||||
|> Ports.storeSession
|
||||
|
||||
|
||||
login : { r | email : String, password : String } -> Http.Request User
|
||||
login { email, password } =
|
||||
let
|
||||
user =
|
||||
Encode.object
|
||||
[ ( "email", Encode.string email )
|
||||
, ( "password", Encode.string password )
|
||||
]
|
||||
|
||||
body =
|
||||
Encode.object [ ( "user", user ) ]
|
||||
|> Http.jsonBody
|
||||
in
|
||||
Decode.field "user" User.decoder
|
||||
|> Http.post (apiUrl "/users/login") body
|
||||
|
||||
|
||||
register : { r | username : String, email : String, password : String } -> Http.Request User
|
||||
register { username, email, password } =
|
||||
let
|
||||
user =
|
||||
Encode.object
|
||||
[ ( "username", Encode.string username )
|
||||
, ( "email", Encode.string email )
|
||||
, ( "password", Encode.string password )
|
||||
]
|
||||
|
||||
body =
|
||||
Encode.object [ ( "user", user ) ]
|
||||
|> Http.jsonBody
|
||||
in
|
||||
Decode.field "user" User.decoder
|
||||
|> Http.post (apiUrl "/users") body
|
||||
|
||||
|
||||
edit :
|
||||
{ r
|
||||
| username : String
|
||||
, email : String
|
||||
, bio : String
|
||||
, password : Maybe String
|
||||
, image : Maybe String
|
||||
}
|
||||
-> Maybe AuthToken
|
||||
-> Http.Request User
|
||||
edit { username, email, bio, password, image } maybeToken =
|
||||
let
|
||||
updates =
|
||||
[ Just ( "username", Encode.string username )
|
||||
, Just ( "email", Encode.string email )
|
||||
, Just ( "bio", Encode.string bio )
|
||||
, Just ( "image", EncodeExtra.maybe Encode.string image )
|
||||
, Maybe.map (\pass -> ( "password", Encode.string pass )) password
|
||||
]
|
||||
|> List.filterMap identity
|
||||
|
||||
body =
|
||||
( "user", Encode.object updates )
|
||||
|> List.singleton
|
||||
|> Encode.object
|
||||
|> Http.jsonBody
|
||||
|
||||
expect =
|
||||
User.decoder
|
||||
|> Decode.field "user"
|
||||
|> Http.expectJson
|
||||
in
|
||||
apiUrl "/user"
|
||||
|> HttpBuilder.put
|
||||
|> HttpBuilder.withExpect expect
|
||||
|> HttpBuilder.withBody body
|
||||
|> withAuthorization maybeToken
|
||||
|> HttpBuilder.toRequest
|
||||
Reference in New Issue
Block a user