Skip to content

Commit

Permalink
Feature: Following
Browse files Browse the repository at this point in the history
  • Loading branch information
supermario committed Jun 2, 2021
1 parent 17ecacc commit 723d4b6
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 39 deletions.
14 changes: 14 additions & 0 deletions src/Api/Article/Filters.elm
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,17 @@ byAuthor mAuthor articles =

Nothing ->
articles


byFavorite mUsername users articles =
case mUsername of
Just username ->
case users |> Dict.get username of
Just user ->
articles |> Dict.filter (\slug a -> List.member slug user.favorites)

Nothing ->
articles

Nothing ->
articles
6 changes: 1 addition & 5 deletions src/Api/Data.elm
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
module Api.Data exposing
( Data(..)
, map
, toMaybe
)
module Api.Data exposing (Data(..), map, toMaybe)

import Http

Expand Down
1 change: 1 addition & 0 deletions src/Api/User.elm
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type alias UserFull =
, image : String
, password : String
, favorites : List String -- Slugs
, following : List Email
}


Expand Down
163 changes: 130 additions & 33 deletions src/Backend.elm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ module Backend exposing (..)
import Api.Article exposing (Article, Slug)
import Api.Article.Filters as Filters exposing (Filters(..))
import Api.Data exposing (Data(..))
import Api.User exposing (User, UserFull)
import Api.Profile exposing (Profile)
import Api.User exposing (Email, User, UserFull)
import Bridge exposing (..)
import Dict
import Gen.Msg
Expand Down Expand Up @@ -46,7 +47,7 @@ init =
|> Dict.fromList
in
( { sessions = Dict.empty
, users = Dict.fromList [ ( stubUserFull.email, stubUserFull ) ]
, users = stubUsersFull |> List.map (\u -> ( u.email, u )) |> Dict.fromList
, articles = articles
, comments =
articles
Expand Down Expand Up @@ -151,7 +152,7 @@ updateFromFrontend sessionId clientId msg model =
onlyWhenArticleOwner_ slug fn =
let
res =
model |> findArticleBySlug slug
model |> loadArticleBySlug slug sessionId

userM =
model |> getSessionUser sessionId
Expand Down Expand Up @@ -188,8 +189,33 @@ updateFromFrontend sessionId clientId msg model =

ArticleFeed_Home_ { page } ->
let
userM =
model |> getSessionUser sessionId

articleList =
getListing model sessionId Filters.create page
case userM of
Just user ->
let
filtered =
model.articles
|> Dict.filter (\slug article -> List.member article.author.username user.following)

enriched =
filtered |> Dict.map (\slug article -> { article | favorited = user.favorites |> List.member slug })

grouped =
enriched |> Dict.values |> List.greedyGroupsOf Api.Article.itemsPerPage

articles =
grouped |> List.getAt (page - 1) |> Maybe.withDefault []
in
{ articles = articles
, page = page
, totalPages = grouped |> List.length
}

Nothing ->
{ articles = [], page = 0, totalPages = 0 }
in
send (PageMsg (Gen.Msg.Home_ (Pages.Home_.GotArticles (Success articleList))))

Expand Down Expand Up @@ -224,7 +250,7 @@ updateFromFrontend sessionId clientId msg model =
ArticleGet_Article__Slug_ { slug } ->
let
res =
model |> findArticleBySlug slug
model |> loadArticleBySlug slug sessionId
in
send (PageMsg (Gen.Msg.Article__Slug_ (Pages.Article.Slug_.GotArticle res)))

Expand Down Expand Up @@ -310,19 +336,39 @@ updateFromFrontend sessionId clientId msg model =
)

ProfileGet_Profile__Username_ { username } ->
send (PageMsg (Gen.Msg.Profile__Username_ (Pages.Profile.Username_.GotProfile (Success stubProfile))))
let
res =
model.users
|> Dict.get username
|> Maybe.map Api.User.toProfile
|> Maybe.map Success
|> Maybe.withDefault (Failure [ "user not found" ])
in
send (PageMsg (Gen.Msg.Profile__Username_ (Pages.Profile.Username_.GotProfile res)))

ProfileFollow_Profile__Username_ { username } ->
send (PageMsg (Gen.Msg.Profile__Username_ (Pages.Profile.Username_.GotProfile (Success stubProfile))))
followUser sessionId
username
model
(\r -> send_ (PageMsg (Gen.Msg.Profile__Username_ (Pages.Profile.Username_.GotProfile r))))

ProfileUnfollow_Profile__Username_ { username } ->
send (PageMsg (Gen.Msg.Profile__Username_ (Pages.Profile.Username_.GotProfile (Success stubProfile))))
unfollowUser sessionId
username
model
(\r -> send_ (PageMsg (Gen.Msg.Profile__Username_ (Pages.Profile.Username_.GotProfile r))))

ProfileFollow_Article__Slug_ { username } ->
send (PageMsg (Gen.Msg.Article__Slug_ (Pages.Article.Slug_.GotAuthor (Success stubProfile))))
followUser sessionId
username
model
(\r -> send_ (PageMsg (Gen.Msg.Article__Slug_ (Pages.Article.Slug_.GotAuthor r))))

ProfileUnfollow_Article__Slug_ { username } ->
send (PageMsg (Gen.Msg.Article__Slug_ (Pages.Article.Slug_.GotAuthor (Success stubProfile))))
unfollowUser sessionId
username
model
(\r -> send_ (PageMsg (Gen.Msg.Article__Slug_ (Pages.Article.Slug_.GotAuthor r))))

UserAuthentication_Login { user } ->
let
Expand Down Expand Up @@ -367,7 +413,7 @@ getListing model sessionId (Filters { tag, author, favorited }) page =
let
filtered =
model.articles
-- |> Filters.byFavorited favorited
|> Filters.byFavorite favorited model.users
|> Filters.byTag tag
|> Filters.byAuthor author

Expand All @@ -391,12 +437,29 @@ getListing model sessionId (Filters { tag, author, favorited }) page =
}


findArticleBySlug : String -> Model -> Data Article
findArticleBySlug slug model =
model.articles
|> Dict.get slug
|> Maybe.map Success
|> Maybe.withDefault (Failure [ "no article with slug: " ++ slug ])
loadArticleBySlug : String -> SessionId -> Model -> Data Article
loadArticleBySlug slug sid model =
let
res =
model.articles
|> Dict.get slug
|> Maybe.map Success
|> Maybe.withDefault (Failure [ "no article with slug: " ++ slug ])
in
case model |> getSessionUser sid of
Just user ->
res
|> Api.Data.map
(\article ->
let
author_ =
article.author |> (\a -> { a | following = List.member article.author.username user.following })
in
{ article | author = author_ }
)

Nothing ->
res


uniqueSlug : Model -> String -> Int -> String
Expand All @@ -420,12 +483,16 @@ favoriteArticle sessionId slug model toResponseCmd =
let
res =
model
|> findArticleBySlug slug
|> loadArticleBySlug slug sessionId
|> Api.Data.map (\a -> { a | favorited = True })
in
case model |> getSessionUser sessionId of
Just user ->
( model |> addToFavorites slug user
( if model.articles |> Dict.member slug then
model |> updateUser { user | favorites = (slug :: user.favorites) |> List.unique }

else
model
, toResponseCmd res
)

Expand All @@ -438,33 +505,63 @@ unfavoriteArticle sessionId slug model toResponseCmd =
let
res =
model
|> findArticleBySlug slug
|> loadArticleBySlug slug sessionId
|> Api.Data.map (\a -> { a | favorited = False })
in
case model |> getSessionUser sessionId of
Just user ->
( model |> removeFromFavorites slug user
( model |> updateUser { user | favorites = user.favorites |> List.remove slug }
, toResponseCmd res
)

Nothing ->
( model, toResponseCmd <| Failure [ "invalid session" ] )


addToFavorites : Slug -> UserFull -> Model -> Model
addToFavorites slug user model =
if model.articles |> Dict.member slug then
model |> updateUser user (\user_ -> { user_ | favorites = (slug :: user_.favorites) |> List.unique })
followUser : SessionId -> Email -> Model -> (Data Profile -> Cmd msg) -> ( Model, Cmd msg )
followUser sessionId email model toResponseCmd =
let
res =
model.users
|> Dict.get email
|> Maybe.map Api.User.toProfile
|> Maybe.map (\a -> Success { a | following = True })
|> Maybe.withDefault (Failure [ "invalid user" ])
in
case model |> getSessionUser sessionId of
Just user ->
( if model.users |> Dict.member email then
model |> updateUser { user | following = (email :: user.following) |> List.unique }

else
model
else
model
, toResponseCmd res
)

Nothing ->
( model, toResponseCmd <| Failure [ "invalid session" ] )

removeFromFavorites : Slug -> UserFull -> Model -> Model
removeFromFavorites slug user model =
model |> updateUser user (\user_ -> { user_ | favorites = user_.favorites |> List.remove slug })

unfollowUser : SessionId -> Email -> Model -> (Data Profile -> Cmd msg) -> ( Model, Cmd msg )
unfollowUser sessionId email model toResponseCmd =
let
res =
model.users
|> Dict.get email
|> Maybe.map Api.User.toProfile
|> Maybe.map (\a -> Success { a | following = False })
|> Maybe.withDefault (Failure [ "invalid user" ])
in
case model |> getSessionUser sessionId of
Just user ->
( model |> updateUser { user | following = user.following |> List.remove email }
, toResponseCmd res
)

Nothing ->
( model, toResponseCmd <| Failure [ "invalid session" ] )


updateUser : UserFull -> (UserFull -> UserFull) -> Model -> Model
updateUser user fn model =
{ model | users = model.users |> Dict.update user.username (Maybe.map fn) }
updateUser : UserFull -> Model -> Model
updateUser user model =
{ model | users = model.users |> Dict.update user.username (Maybe.map (always user)) }
20 changes: 20 additions & 0 deletions src/Stubs.elm
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,29 @@ stubUserFull =
, image = "https://static.productionready.io/images/smiley-cyrus.jpg"
, password = "test"
, favorites = []
, following = []
}


stubUserFull2 : UserFull
stubUserFull2 =
{ email = "[email protected]"
, username = "[email protected]"
, bio = Just "just bob"
, image = "https://static.productionready.io/images/smiley-cyrus.jpg"
, password = "bob"
, favorites = []
, following = []
}


stubUsersFull : List UserFull
stubUsersFull =
[ stubUserFull
, stubUserFull2
]


stubComment : Comment
stubComment =
{ id = 0
Expand Down
1 change: 0 additions & 1 deletion src/Types.elm
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import Browser.Navigation exposing (Key)
import Dict exposing (Dict)
import Gen.Pages as Pages
import Lamdera exposing (ClientId, SessionId)
import SerialDict exposing (SerialDict)
import Shared
import Time
import Url exposing (Url)
Expand Down

0 comments on commit 723d4b6

Please sign in to comment.