Add part5
This commit is contained in:
193
part5/src/Page/Profile.elm
Normal file
193
part5/src/Page/Profile.elm
Normal file
@@ -0,0 +1,193 @@
|
||||
module Page.Profile exposing (Model, Msg, init, update, view)
|
||||
|
||||
{-| Viewing a user's profile.
|
||||
-}
|
||||
|
||||
import Data.Profile exposing (Profile)
|
||||
import Data.Session exposing (Session)
|
||||
import Data.User as User exposing (Username)
|
||||
import Data.UserPhoto as UserPhoto exposing (UserPhoto)
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Http
|
||||
import Page.Errored exposing (PageLoadError, pageLoadError)
|
||||
import Request.Article exposing (ListConfig, defaultListConfig)
|
||||
import Request.Profile
|
||||
import SelectList exposing (SelectList)
|
||||
import Task exposing (Task)
|
||||
import Util exposing (pair, viewIf)
|
||||
import Views.Article.Feed as Feed exposing (FeedSource, authorFeed, favoritedFeed)
|
||||
import Views.Errors as Errors
|
||||
import Views.Page as Page
|
||||
import Views.User.Follow as Follow
|
||||
|
||||
|
||||
-- MODEL --
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ errors : List String
|
||||
, profile : Profile
|
||||
, feed : Feed.Model
|
||||
}
|
||||
|
||||
|
||||
init : Session -> Username -> Task PageLoadError Model
|
||||
init session username =
|
||||
let
|
||||
config : ListConfig
|
||||
config =
|
||||
{ defaultListConfig | limit = 5, author = Just username }
|
||||
|
||||
maybeAuthToken =
|
||||
session.user
|
||||
|> Maybe.map .token
|
||||
|
||||
loadProfile =
|
||||
Request.Profile.get username maybeAuthToken
|
||||
|> Http.toTask
|
||||
|
||||
loadFeedSources =
|
||||
Feed.init session (defaultFeedSources username)
|
||||
|
||||
handleLoadError _ =
|
||||
"Profile is currently unavailable."
|
||||
|> pageLoadError (Page.Profile username)
|
||||
in
|
||||
Task.map2 (Model []) loadProfile loadFeedSources
|
||||
|> Task.mapError handleLoadError
|
||||
|
||||
|
||||
|
||||
-- VIEW --
|
||||
|
||||
|
||||
view : Session -> Model -> Html Msg
|
||||
view session model =
|
||||
let
|
||||
profile =
|
||||
model.profile
|
||||
|
||||
isMyProfile =
|
||||
session.user
|
||||
|> Maybe.map (\{ username } -> username == profile.username)
|
||||
|> Maybe.withDefault False
|
||||
in
|
||||
div [ class "profile-page" ]
|
||||
[ Errors.view DismissErrors model.errors
|
||||
, div [ class "user-info" ]
|
||||
[ div [ class "container" ]
|
||||
[ div [ class "row" ]
|
||||
[ viewProfileInfo isMyProfile profile ]
|
||||
]
|
||||
]
|
||||
, div [ class "container" ]
|
||||
[ div [ class "row" ] [ viewFeed model.feed ] ]
|
||||
]
|
||||
|
||||
|
||||
viewProfileInfo : Bool -> Profile -> Html Msg
|
||||
viewProfileInfo isMyProfile profile =
|
||||
div [ class "col-xs-12 col-md-10 offset-md-1" ]
|
||||
[ img [ class "user-img", UserPhoto.src profile.image ] []
|
||||
, h4 [] [ User.usernameToHtml profile.username ]
|
||||
, p [] [ text (Maybe.withDefault "" profile.bio) ]
|
||||
, viewIf (not isMyProfile) (followButton profile)
|
||||
]
|
||||
|
||||
|
||||
viewFeed : Feed.Model -> Html Msg
|
||||
viewFeed feed =
|
||||
div [ class "col-xs-12 col-md-10 offset-md-1" ] <|
|
||||
div [ class "articles-toggle" ]
|
||||
[ Feed.viewFeedSources feed |> Html.map FeedMsg ]
|
||||
:: (Feed.viewArticles feed |> List.map (Html.map FeedMsg))
|
||||
|
||||
|
||||
|
||||
-- UPDATE --
|
||||
|
||||
|
||||
type Msg
|
||||
= DismissErrors
|
||||
| ToggleFollow
|
||||
| FollowCompleted (Result Http.Error Profile)
|
||||
| FeedMsg Feed.Msg
|
||||
|
||||
|
||||
update : Session -> Msg -> Model -> ( Model, Cmd Msg )
|
||||
update session msg model =
|
||||
let
|
||||
profile =
|
||||
model.profile
|
||||
in
|
||||
case msg of
|
||||
DismissErrors ->
|
||||
( { model | errors = [] }, Cmd.none )
|
||||
|
||||
ToggleFollow ->
|
||||
case session.user of
|
||||
Nothing ->
|
||||
( { model | errors = model.errors ++ [ "You are currently signed out. You must be signed in to follow people." ] }
|
||||
, Cmd.none
|
||||
)
|
||||
|
||||
Just user ->
|
||||
let
|
||||
-- TODO
|
||||
-- 1) head over to the Request.Profile module and look up
|
||||
-- what arguments the `toggleFollow` function takes.
|
||||
--
|
||||
-- 2) call Request.Profile.toggleFollow here,
|
||||
-- to get back a Request.
|
||||
--
|
||||
-- 3) pass that Request to Http.send to get a Cmd.
|
||||
-- Use that Cmd here.
|
||||
--
|
||||
-- Here's the documentation for Http.send:
|
||||
-- http://package.elm-lang.org/packages/elm-lang/http/1.0.0/Http#send
|
||||
--
|
||||
-- Here are some hepful values that are in scope:
|
||||
--
|
||||
-- user.token : Maybe AuthToken
|
||||
--
|
||||
-- profile : Profile [look in the Data.Profile module!]
|
||||
--
|
||||
-- FollowCompleted : Result Http.Error Profile -> Msg
|
||||
--
|
||||
cmd : Cmd Msg
|
||||
cmd =
|
||||
Request.Profile.toggleFollow
|
||||
profile.username
|
||||
profile.following
|
||||
user.token
|
||||
|> Http.send FollowCompleted
|
||||
in
|
||||
( model, cmd )
|
||||
|
||||
FollowCompleted (Ok newProfile) ->
|
||||
( { model | profile = newProfile }, Cmd.none )
|
||||
|
||||
FollowCompleted (Err error) ->
|
||||
( model, Cmd.none )
|
||||
|
||||
FeedMsg subMsg ->
|
||||
let
|
||||
( newFeed, subCmd ) =
|
||||
Feed.update session subMsg model.feed
|
||||
in
|
||||
( { model | feed = newFeed }, Cmd.map FeedMsg subCmd )
|
||||
|
||||
|
||||
followButton : Profile -> Html Msg
|
||||
followButton =
|
||||
Follow.button (\_ -> ToggleFollow)
|
||||
|
||||
|
||||
|
||||
-- INTERNAL --
|
||||
|
||||
|
||||
defaultFeedSources : Username -> SelectList FeedSource
|
||||
defaultFeedSources username =
|
||||
SelectList.fromLists [] (authorFeed username) [ favoritedFeed username ]
|
||||
Reference in New Issue
Block a user