Rename more stuff
This commit is contained in:
266
intro/part8/src/Page/Settings.elm
Normal file
266
intro/part8/src/Page/Settings.elm
Normal file
@@ -0,0 +1,266 @@
|
||||
module Page.Settings exposing (ExternalMsg(..), Model, Msg, init, update, view)
|
||||
|
||||
import Data.Session exposing (Session)
|
||||
import Data.User as User exposing (User)
|
||||
import Data.UserPhoto as UserPhoto
|
||||
import Html exposing (Html, button, div, fieldset, h1, input, text, textarea)
|
||||
import Html.Attributes exposing (attribute, class, value, placeholder, type_)
|
||||
import Html.Events exposing (onInput, onSubmit)
|
||||
import Http
|
||||
import Json.Decode as Decode exposing (Decoder, decodeString, field, list, string)
|
||||
import Json.Decode.Pipeline exposing (decode, optional)
|
||||
import Request.User exposing (storeSession)
|
||||
import Route
|
||||
import Util exposing (pair)
|
||||
import Validate exposing (Validator, ifBlank, validate)
|
||||
import Views.Form as Form
|
||||
|
||||
|
||||
-- MODEL --
|
||||
|
||||
|
||||
type alias Model =
|
||||
{ errors : List Error
|
||||
, image : Maybe String
|
||||
, email : String
|
||||
, bio : String
|
||||
, username : String
|
||||
, password : Maybe String
|
||||
}
|
||||
|
||||
|
||||
init : User -> Model
|
||||
init user =
|
||||
{ errors = []
|
||||
, image = UserPhoto.toMaybeString user.image
|
||||
, email = user.email
|
||||
, bio = Maybe.withDefault "" user.bio
|
||||
, username = User.usernameToString user.username
|
||||
, password = Nothing
|
||||
}
|
||||
|
||||
|
||||
|
||||
-- VIEW --
|
||||
|
||||
|
||||
view : Session -> Model -> Html Msg
|
||||
view session model =
|
||||
div [ class "settings-page" ]
|
||||
[ div [ class "container page" ]
|
||||
[ div [ class "row" ]
|
||||
[ div [ class "col-md-6 offset-md-3 col-xs-12" ]
|
||||
[ h1 [ class "text-xs-center" ] [ text "Your Settings" ]
|
||||
, Form.viewErrors model.errors
|
||||
, viewForm model
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
viewForm : Model -> Html Msg
|
||||
viewForm model =
|
||||
Html.form [ onSubmit SubmitForm ]
|
||||
[ fieldset []
|
||||
[ Form.input
|
||||
[ placeholder "URL of profile picture"
|
||||
, value (Maybe.withDefault "" model.image)
|
||||
, onInput SetImage
|
||||
]
|
||||
[]
|
||||
, Form.input
|
||||
[ class "form-control-lg"
|
||||
, placeholder "Username"
|
||||
, value model.username
|
||||
, onInput SetUsername
|
||||
]
|
||||
[]
|
||||
, Form.textarea
|
||||
[ class "form-control-lg"
|
||||
, placeholder "Short bio about you"
|
||||
, attribute "rows" "8"
|
||||
, value model.bio
|
||||
, onInput SetBio
|
||||
]
|
||||
[]
|
||||
, Form.input
|
||||
[ class "form-control-lg"
|
||||
, placeholder "Email"
|
||||
, value model.email
|
||||
, onInput SetEmail
|
||||
]
|
||||
[]
|
||||
, Form.password
|
||||
[ class "form-control-lg"
|
||||
, placeholder "Password"
|
||||
, value (Maybe.withDefault "" model.password)
|
||||
, onInput SetPassword
|
||||
]
|
||||
[]
|
||||
, button
|
||||
[ class "btn btn-lg btn-primary pull-xs-right" ]
|
||||
[ text "Update Settings" ]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
|
||||
-- UPDATE --
|
||||
|
||||
|
||||
type Msg
|
||||
= SubmitForm
|
||||
| SetEmail String
|
||||
| SetUsername String
|
||||
| SetPassword String
|
||||
| SetBio String
|
||||
| SetImage String
|
||||
| SaveCompleted (Result Http.Error User)
|
||||
|
||||
|
||||
type ExternalMsg
|
||||
= NoOp
|
||||
| SetUser User
|
||||
|
||||
|
||||
update : Session -> Msg -> Model -> ( ( Model, Cmd Msg ), ExternalMsg )
|
||||
update session msg model =
|
||||
case msg of
|
||||
SubmitForm ->
|
||||
case validate modelValidator model of
|
||||
[] ->
|
||||
( session.user
|
||||
|> Maybe.map .token
|
||||
|> Request.User.edit model
|
||||
|> Http.send SaveCompleted
|
||||
|> pair { model | errors = [] }
|
||||
, NoOp
|
||||
)
|
||||
|
||||
errors ->
|
||||
( ( { model | errors = errors }
|
||||
, Cmd.none
|
||||
)
|
||||
, NoOp
|
||||
)
|
||||
|
||||
SetEmail email ->
|
||||
( ( { model | email = email }
|
||||
, Cmd.none
|
||||
)
|
||||
, NoOp
|
||||
)
|
||||
|
||||
SetUsername username ->
|
||||
( ( { model | username = username }
|
||||
, Cmd.none
|
||||
)
|
||||
, NoOp
|
||||
)
|
||||
|
||||
SetPassword passwordStr ->
|
||||
let
|
||||
password =
|
||||
if String.isEmpty passwordStr then
|
||||
Nothing
|
||||
else
|
||||
Just passwordStr
|
||||
in
|
||||
( ( { model | password = password }
|
||||
, Cmd.none
|
||||
)
|
||||
, NoOp
|
||||
)
|
||||
|
||||
SetBio bio ->
|
||||
( ( { model | bio = bio }
|
||||
, Cmd.none
|
||||
)
|
||||
, NoOp
|
||||
)
|
||||
|
||||
SetImage imageStr ->
|
||||
let
|
||||
image =
|
||||
if String.isEmpty imageStr then
|
||||
Nothing
|
||||
else
|
||||
Just imageStr
|
||||
in
|
||||
( ( { model | image = image }
|
||||
, Cmd.none
|
||||
)
|
||||
, NoOp
|
||||
)
|
||||
|
||||
SaveCompleted (Err error) ->
|
||||
let
|
||||
errorMessages =
|
||||
case error of
|
||||
Http.BadStatus response ->
|
||||
response.body
|
||||
|> decodeString (field "errors" errorsDecoder)
|
||||
|> Result.withDefault []
|
||||
|
||||
_ ->
|
||||
[ "unable to save changes" ]
|
||||
|
||||
errors =
|
||||
errorMessages
|
||||
|> List.map (\errorMessage -> ( Form, errorMessage ))
|
||||
in
|
||||
( ( { model | errors = errors }
|
||||
, Cmd.none
|
||||
)
|
||||
, NoOp
|
||||
)
|
||||
|
||||
SaveCompleted (Ok user) ->
|
||||
( ( model
|
||||
, Cmd.batch [ storeSession user, Route.modifyUrl Route.Home ]
|
||||
)
|
||||
, SetUser user
|
||||
)
|
||||
|
||||
|
||||
|
||||
-- VALIDATION --
|
||||
|
||||
|
||||
type Field
|
||||
= Form
|
||||
| Username
|
||||
| Email
|
||||
| Password
|
||||
| ImageUrl
|
||||
| Bio
|
||||
|
||||
|
||||
type alias Error =
|
||||
( Field, String )
|
||||
|
||||
|
||||
modelValidator : Validator Error Model
|
||||
modelValidator =
|
||||
Validate.all
|
||||
[ ifBlank .username ( Username, "username can't be blank." )
|
||||
, ifBlank .email ( Email, "email can't be blank." )
|
||||
]
|
||||
|
||||
|
||||
errorsDecoder : Decoder (List String)
|
||||
errorsDecoder =
|
||||
decode (\email username password -> List.concat [ email, username, password ])
|
||||
|> optionalError "email"
|
||||
|> optionalError "username"
|
||||
|> optionalError "password"
|
||||
|
||||
|
||||
optionalError : String -> Decoder (List String -> a) -> Decoder a
|
||||
optionalError fieldName =
|
||||
let
|
||||
errorToString errorMessage =
|
||||
String.join " " [ fieldName, errorMessage ]
|
||||
in
|
||||
optional fieldName (list (Decode.map errorToString string)) []
|
||||
Reference in New Issue
Block a user