Update part1
This commit is contained in:
@@ -19,7 +19,7 @@
|
|||||||
"evancz/url-parser": "2.0.1 <= v < 3.0.0",
|
"evancz/url-parser": "2.0.1 <= v < 3.0.0",
|
||||||
"lukewestby/elm-http-builder": "5.1.0 <= v < 6.0.0",
|
"lukewestby/elm-http-builder": "5.1.0 <= v < 6.0.0",
|
||||||
"mgold/elm-date-format": "1.3.0 <= v < 2.0.0",
|
"mgold/elm-date-format": "1.3.0 <= v < 2.0.0",
|
||||||
"rtfeldman/elm-validate": "2.0.0 <= v < 3.0.0",
|
"rtfeldman/elm-validate": "3.0.0 <= v < 4.0.0",
|
||||||
"rtfeldman/selectlist": "1.0.0 <= v < 2.0.0"
|
"rtfeldman/selectlist": "1.0.0 <= v < 2.0.0"
|
||||||
},
|
},
|
||||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"rtfeldman/elm-validate": "2.0.0",
|
"rtfeldman/elm-validate": "3.0.0",
|
||||||
"rtfeldman/selectlist": "1.0.0",
|
"rtfeldman/selectlist": "1.0.0",
|
||||||
"elm-lang/navigation": "2.1.0",
|
"elm-lang/navigation": "2.1.0",
|
||||||
"elm-lang/virtual-dom": "2.0.4",
|
"elm-lang/virtual-dom": "2.0.4",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ module Data.Article.Author exposing (Author, decoder)
|
|||||||
import Data.User as User exposing (Username)
|
import Data.User as User exposing (Username)
|
||||||
import Data.UserPhoto as UserPhoto exposing (UserPhoto)
|
import Data.UserPhoto as UserPhoto exposing (UserPhoto)
|
||||||
import Json.Decode as Decode exposing (Decoder)
|
import Json.Decode as Decode exposing (Decoder)
|
||||||
import Json.Decode.Pipeline exposing (custom, decode, required)
|
import Json.Decode.Pipeline exposing (custom, decode, optional, required)
|
||||||
|
|
||||||
|
|
||||||
decoder : Decoder Author
|
decoder : Decoder Author
|
||||||
@@ -12,7 +12,7 @@ decoder =
|
|||||||
|> required "username" User.usernameDecoder
|
|> required "username" User.usernameDecoder
|
||||||
|> required "bio" (Decode.nullable Decode.string)
|
|> required "bio" (Decode.nullable Decode.string)
|
||||||
|> required "image" UserPhoto.decoder
|
|> required "image" UserPhoto.decoder
|
||||||
|> required "following" Decode.bool
|
|> optional "following" Decode.bool False
|
||||||
|
|
||||||
|
|
||||||
type alias Author =
|
type alias Author =
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Data.AuthToken as AuthToken exposing (AuthToken)
|
|||||||
import Data.UserPhoto as UserPhoto exposing (UserPhoto)
|
import Data.UserPhoto as UserPhoto exposing (UserPhoto)
|
||||||
import Html exposing (Html)
|
import Html exposing (Html)
|
||||||
import Json.Decode as Decode exposing (Decoder)
|
import Json.Decode as Decode exposing (Decoder)
|
||||||
import Json.Decode.Pipeline exposing (decode, required)
|
import Json.Decode.Pipeline exposing (decode, optional, required)
|
||||||
import Json.Encode as Encode exposing (Value)
|
import Json.Encode as Encode exposing (Value)
|
||||||
import Json.Encode.Extra as EncodeExtra
|
import Json.Encode.Extra as EncodeExtra
|
||||||
import UrlParser
|
import UrlParser
|
||||||
@@ -16,8 +16,6 @@ type alias User =
|
|||||||
, username : Username
|
, username : Username
|
||||||
, bio : Maybe String
|
, bio : Maybe String
|
||||||
, image : UserPhoto
|
, image : UserPhoto
|
||||||
, createdAt : String
|
|
||||||
, updatedAt : String
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -33,8 +31,6 @@ decoder =
|
|||||||
|> required "username" usernameDecoder
|
|> required "username" usernameDecoder
|
||||||
|> required "bio" (Decode.nullable Decode.string)
|
|> required "bio" (Decode.nullable Decode.string)
|
||||||
|> required "image" UserPhoto.decoder
|
|> required "image" UserPhoto.decoder
|
||||||
|> required "createdAt" Decode.string
|
|
||||||
|> required "updatedAt" Decode.string
|
|
||||||
|
|
||||||
|
|
||||||
encode : User -> Value
|
encode : User -> Value
|
||||||
@@ -45,8 +41,6 @@ encode user =
|
|||||||
, ( "username", encodeUsername user.username )
|
, ( "username", encodeUsername user.username )
|
||||||
, ( "bio", EncodeExtra.maybe Encode.string user.bio )
|
, ( "bio", EncodeExtra.maybe Encode.string user.bio )
|
||||||
, ( "image", UserPhoto.encode user.image )
|
, ( "image", UserPhoto.encode user.image )
|
||||||
, ( "createdAt", Encode.string user.createdAt )
|
|
||||||
, ( "updatedAt", Encode.string user.updatedAt )
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,15 @@ photoToUrl : UserPhoto -> String
|
|||||||
photoToUrl (UserPhoto maybeUrl) =
|
photoToUrl (UserPhoto maybeUrl) =
|
||||||
case maybeUrl of
|
case maybeUrl of
|
||||||
Nothing ->
|
Nothing ->
|
||||||
"https://static.productionready.io/images/smiley-cyrus.jpg"
|
defaultPhotoUrl
|
||||||
|
|
||||||
|
Just "" ->
|
||||||
|
defaultPhotoUrl
|
||||||
|
|
||||||
Just url ->
|
Just url ->
|
||||||
url
|
url
|
||||||
|
|
||||||
|
|
||||||
|
defaultPhotoUrl : String
|
||||||
|
defaultPhotoUrl =
|
||||||
|
"/assets/images/smiley-cyrus.jpg"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Data.Article as Article exposing (Article, Body)
|
|||||||
import Data.Session exposing (Session)
|
import Data.Session exposing (Session)
|
||||||
import Data.User exposing (User)
|
import Data.User exposing (User)
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Attributes exposing (attribute, class, disabled, href, id, placeholder, type_, value)
|
import Html.Attributes exposing (attribute, class, defaultValue, disabled, href, id, placeholder, type_)
|
||||||
import Html.Events exposing (onInput, onSubmit)
|
import Html.Events exposing (onInput, onSubmit)
|
||||||
import Http
|
import Http
|
||||||
import Page.Errored exposing (PageLoadError, pageLoadError)
|
import Page.Errored exposing (PageLoadError, pageLoadError)
|
||||||
@@ -102,26 +102,26 @@ viewForm model =
|
|||||||
[ class "form-control-lg"
|
[ class "form-control-lg"
|
||||||
, placeholder "Article Title"
|
, placeholder "Article Title"
|
||||||
, onInput SetTitle
|
, onInput SetTitle
|
||||||
, value model.title
|
, defaultValue model.title
|
||||||
]
|
]
|
||||||
[]
|
[]
|
||||||
, Form.input
|
, Form.input
|
||||||
[ placeholder "What's this article about?"
|
[ placeholder "What's this article about?"
|
||||||
, onInput SetDescription
|
, onInput SetDescription
|
||||||
, value model.description
|
, defaultValue model.description
|
||||||
]
|
]
|
||||||
[]
|
[]
|
||||||
, Form.textarea
|
, Form.textarea
|
||||||
[ placeholder "Write your article (in markdown)"
|
[ placeholder "Write your article (in markdown)"
|
||||||
, attribute "rows" "8"
|
, attribute "rows" "8"
|
||||||
, onInput SetBody
|
, onInput SetBody
|
||||||
, value model.body
|
, defaultValue model.body
|
||||||
]
|
]
|
||||||
[]
|
[]
|
||||||
, Form.input
|
, Form.input
|
||||||
[ placeholder "Enter tags"
|
[ placeholder "Enter tags"
|
||||||
, onInput SetTags
|
, onInput SetTags
|
||||||
, value (String.join " " model.tags)
|
, defaultValue (String.join " " model.tags)
|
||||||
]
|
]
|
||||||
[]
|
[]
|
||||||
, button [ class "btn btn-lg pull-xs-right btn-primary", disabled model.isSaving ]
|
, button [ class "btn btn-lg pull-xs-right btn-primary", disabled model.isSaving ]
|
||||||
|
|||||||
@@ -186,10 +186,23 @@ modelValidator =
|
|||||||
Validate.all
|
Validate.all
|
||||||
[ ifBlank .username ( Username, "username can't be blank." )
|
[ ifBlank .username ( Username, "username can't be blank." )
|
||||||
, ifBlank .email ( Email, "email can't be blank." )
|
, ifBlank .email ( Email, "email can't be blank." )
|
||||||
, ifBlank .password ( Password, "password can't be blank." )
|
, Validate.fromErrors passwordLength
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
minPasswordChars : Int
|
||||||
|
minPasswordChars =
|
||||||
|
6
|
||||||
|
|
||||||
|
|
||||||
|
passwordLength : Model -> List Error
|
||||||
|
passwordLength { password } =
|
||||||
|
if String.length password < minPasswordChars then
|
||||||
|
[ ( Password, "password must be at least " ++ toString minPasswordChars ++ " characters long." ) ]
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
|
||||||
|
|
||||||
errorsDecoder : Decoder (List String)
|
errorsDecoder : Decoder (List String)
|
||||||
errorsDecoder =
|
errorsDecoder =
|
||||||
decode (\email username password -> List.concat [ email, username, password ])
|
decode (\email username password -> List.concat [ email, username, password ])
|
||||||
|
|||||||
@@ -7,12 +7,22 @@ import Data.Article exposing (Article)
|
|||||||
import Data.UserPhoto as UserPhoto exposing (UserPhoto)
|
import Data.UserPhoto as UserPhoto exposing (UserPhoto)
|
||||||
import Date.Format
|
import Date.Format
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Attributes exposing (attribute, class, classList, href, id, src)
|
import Html.Attributes exposing (attribute, class, classList, href, id, placeholder, src)
|
||||||
import Route exposing (Route)
|
import Route exposing (Route)
|
||||||
import Views.Article.Favorite as Favorite
|
import Views.Article.Favorite as Favorite
|
||||||
import Views.Author
|
import Views.Author
|
||||||
|
|
||||||
|
|
||||||
|
-- VIEWS --
|
||||||
|
|
||||||
|
|
||||||
|
{-| Some pages want to view just the timestamp, not the whole article.
|
||||||
|
-}
|
||||||
|
viewTimestamp : Article a -> Html msg
|
||||||
|
viewTimestamp article =
|
||||||
|
span [ class "date" ] [ text (formattedTimestamp article) ]
|
||||||
|
|
||||||
|
|
||||||
view : (Article a -> msg) -> Article a -> Html msg
|
view : (Article a -> msg) -> Article a -> Html msg
|
||||||
view toggleFavorite article =
|
view toggleFavorite article =
|
||||||
let
|
let
|
||||||
@@ -25,7 +35,7 @@ view toggleFavorite article =
|
|||||||
[ img [ UserPhoto.src author.image ] [] ]
|
[ img [ UserPhoto.src author.image ] [] ]
|
||||||
, div [ class "info" ]
|
, div [ class "info" ]
|
||||||
[ Views.Author.view author.username
|
[ Views.Author.view author.username
|
||||||
, viewTimestamp article
|
, span [ class "date" ] [ text (formattedTimestamp article) ]
|
||||||
]
|
]
|
||||||
, Favorite.button
|
, Favorite.button
|
||||||
toggleFavorite
|
toggleFavorite
|
||||||
@@ -41,9 +51,8 @@ view toggleFavorite article =
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
viewTimestamp : Article a -> Html msg
|
|
||||||
viewTimestamp article =
|
-- INTERNAL --
|
||||||
span [ class "date" ] [ text (formattedTimestamp article) ]
|
|
||||||
|
|
||||||
|
|
||||||
formattedTimestamp : Article a -> String
|
formattedTimestamp : Article a -> String
|
||||||
|
|||||||
Reference in New Issue
Block a user