doglinks/client/src/CreatePage.elm

131 lines
3.4 KiB
Elm

module CreatePage exposing (Model, Msg, init, update, view)
import Browser.Navigation as Nav
import Css
import Css.Media as Media
import Html.Styled exposing (..)
import Html.Styled.Attributes as Attr
import Html.Styled.Events as Events
import Http
import Input
import Json.Decode as Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (required)
import Json.Encode as Encode
type alias Model =
{ link : String
, error : Maybe String
}
init : Model
init =
{ link = ""
, error = Nothing
}
descriptionStyles : Css.Style
descriptionStyles =
Css.marginTop (Css.px 0)
inputLineStyles : Css.Style
inputLineStyles =
Css.batch
[ Css.displayFlex
, Media.withMedia
[ Media.only Media.screen [ Media.maxWidth (Css.px 500) ] ]
[ Css.display Css.block ]
]
view : Model -> Html Msg
view model =
div []
[ form [ Events.onSubmit (ClickedCreate model.link) ]
[ p [ Attr.css [ descriptionStyles ] ]
[ text "A Doglink is just an alias, or a redirect for an existing link. Paste a link you want to redirect to into the field below!"
]
, div [ Attr.css [ inputLineStyles ] ]
[ Input.text
[ Attr.placeholder "https://example.com"
, Events.onInput LinkUpdated
]
[]
, Input.submitButton [] [ text "Create doglink" ]
]
]
, case model.error of
Just error ->
viewError error
Nothing ->
text ""
]
viewError : String -> Html msg
viewError error =
div []
[ h3 [] [ text "Couldn't create doglink" ]
, p [] [ text error ]
]
type Msg
= ClickedCreate String
| LinkUpdated String
| GotUuid (Result Http.Error String)
update : String -> Nav.Key -> Msg -> Model -> ( Model, Cmd Msg )
update origin key msg model =
case msg of
ClickedCreate _ ->
( model, createLink origin model )
LinkUpdated link ->
( { model | link = link }, Cmd.none )
GotUuid (Ok uuid) ->
( model, Nav.pushUrl key ("/" ++ uuid) )
GotUuid (Err error) ->
case error of
Http.BadUrl url ->
( { model | error = Just ("Bad url: " ++ url) }, Cmd.none )
Http.Timeout ->
( { model | error = Just "Request timed out" }, Cmd.none )
Http.NetworkError ->
( { model | error = Just "Couldn't talk to server" }, Cmd.none )
Http.BadStatus int ->
( { model | error = Just ("Server responded with invalid status: " ++ String.fromInt int) }, Cmd.none )
Http.BadBody body ->
( { model | error = Just ("Server responed with unexpected data: " ++ body) }, Cmd.none )
createLink : String -> Model -> Cmd Msg
createLink origin model =
Http.post
{ url = origin ++ "/link"
, body = Http.jsonBody (encodeLink model.link)
, expect = Http.expectJson GotUuid uuidDecoder
}
uuidDecoder : Decoder String
uuidDecoder =
Decode.succeed identity
|> required "uuid" Decode.string
encodeLink : String -> Encode.Value
encodeLink link =
Encode.object [ ( "url", Encode.string link ) ]