mirror of
https://github.com/dillonkearns/elm-pages-v3-beta.git
synced 2024-12-26 21:31:32 +03:00
Replace New route with Admin/Slug.
This commit is contained in:
parent
b0d5a3c2e1
commit
d140be0f73
@ -1,4 +1,4 @@
|
||||
module Route.Posts.Slug_.Edit exposing (ActionData, Data, route, RouteParams, Msg, Model)
|
||||
module Route.Admin.Slug_ exposing (ActionData, Data, route, RouteParams, Msg, Model)
|
||||
|
||||
{-|
|
||||
|
||||
@ -9,7 +9,6 @@ module Route.Posts.Slug_.Edit exposing (ActionData, Data, route, RouteParams, Ms
|
||||
import BackendTask
|
||||
import BackendTask.Custom
|
||||
import Date exposing (Date)
|
||||
import Debug
|
||||
import Effect
|
||||
import ErrorPage
|
||||
import FatalError
|
||||
@ -116,21 +115,33 @@ data :
|
||||
-> Server.Request.Parser (BackendTask.BackendTask FatalError.FatalError (Server.Response.Response Data ErrorPage.ErrorPage))
|
||||
data routeParams =
|
||||
Server.Request.succeed
|
||||
(BackendTask.Custom.run "getPost"
|
||||
(Encode.string routeParams.slug)
|
||||
(Decode.nullable Post.decoder)
|
||||
|> BackendTask.allowFatal
|
||||
|> BackendTask.map
|
||||
(\maybePost ->
|
||||
case maybePost of
|
||||
Just post ->
|
||||
Server.Response.render
|
||||
{ post = post
|
||||
}
|
||||
(if routeParams.slug == "new" then
|
||||
Server.Response.render
|
||||
{ post =
|
||||
{ slug = ""
|
||||
, title = ""
|
||||
, body = ""
|
||||
, publish = Nothing
|
||||
}
|
||||
}
|
||||
|> BackendTask.succeed
|
||||
|
||||
Nothing ->
|
||||
Route.redirectTo Route.Index
|
||||
)
|
||||
else
|
||||
BackendTask.Custom.run "getPost"
|
||||
(Encode.string routeParams.slug)
|
||||
(Decode.nullable Post.decoder)
|
||||
|> BackendTask.allowFatal
|
||||
|> BackendTask.map
|
||||
(\maybePost ->
|
||||
case maybePost of
|
||||
Just post ->
|
||||
Server.Response.render
|
||||
{ post = post
|
||||
}
|
||||
|
||||
Nothing ->
|
||||
Server.Response.errorPage ErrorPage.NotFound
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@ -167,7 +178,18 @@ action routeParams =
|
||||
(\( formResponse, parsedForm ) ->
|
||||
case parsedForm of
|
||||
Ok okForm ->
|
||||
BackendTask.Custom.run "updatePost"
|
||||
let
|
||||
createPost : Bool
|
||||
createPost =
|
||||
okForm.slug == "new"
|
||||
in
|
||||
BackendTask.Custom.run
|
||||
(if createPost then
|
||||
"createPost"
|
||||
|
||||
else
|
||||
"updatePost"
|
||||
)
|
||||
(Encode.object
|
||||
[ ( "slug", Encode.string okForm.slug )
|
||||
, ( "title", Encode.string okForm.title )
|
||||
@ -183,18 +205,14 @@ action routeParams =
|
||||
|> BackendTask.allowFatal
|
||||
|> BackendTask.map
|
||||
(\() ->
|
||||
Server.Response.render
|
||||
{ errors = formResponse }
|
||||
Route.redirectTo
|
||||
(Route.Admin__Slug_ { slug = okForm.slug })
|
||||
)
|
||||
|
||||
Err invalidForm ->
|
||||
BackendTask.map
|
||||
(\parsed ->
|
||||
Server.Response.render
|
||||
{ errors = formResponse }
|
||||
)
|
||||
(Pages.Script.log
|
||||
(Debug.toString parsedForm)
|
||||
BackendTask.succeed
|
||||
(Server.Response.render
|
||||
{ errors = formResponse }
|
||||
)
|
||||
)
|
||||
(Server.Request.formData (Form.initCombined Basics.identity form))
|
||||
@ -227,7 +245,10 @@ form =
|
||||
, fieldView "body" body
|
||||
, fieldView "publish" publish
|
||||
, if formState.isTransitioning then
|
||||
Html.button [ Html.Attributes.disabled True ]
|
||||
Html.button
|
||||
[ Html.Attributes.disabled True
|
||||
, Html.Attributes.attribute "aria-busy" "true"
|
||||
]
|
||||
[ Html.text "Submitting..." ]
|
||||
|
||||
else
|
||||
@ -247,7 +268,7 @@ form =
|
||||
)
|
||||
|> Form.field "body"
|
||||
(Form.Field.required "Required" Form.Field.text
|
||||
|> Form.Field.textarea { rows = Just 30, cols = Just 80 }
|
||||
|> Form.Field.textarea { rows = Just 10, cols = Just 80 }
|
||||
|> Form.Field.withInitialValue (.body >> Form.Value.string)
|
||||
)
|
||||
|> Form.field "publish"
|
@ -87,7 +87,8 @@ view :
|
||||
view maybeUrl sharedModel app =
|
||||
{ title = "Index page"
|
||||
, body =
|
||||
[ app.data.posts
|
||||
[ Html.h1 [] [ Html.text "Posts" ]
|
||||
, app.data.posts
|
||||
|> List.map postView
|
||||
|> Html.ul []
|
||||
]
|
||||
@ -97,7 +98,7 @@ view maybeUrl sharedModel app =
|
||||
postView : Post -> Html.Html msg
|
||||
postView post =
|
||||
Html.li []
|
||||
[ Route.Posts__Slug___Edit { slug = post.slug }
|
||||
[ Route.Admin__Slug_ { slug = post.slug }
|
||||
|> Route.link []
|
||||
[ Html.text post.title
|
||||
]
|
||||
|
@ -1,324 +0,0 @@
|
||||
module Route.Posts.New exposing (ActionData, Data, route, RouteParams, Msg, Model)
|
||||
|
||||
{-|
|
||||
|
||||
@docs ActionData, Data, route, RouteParams, Msg, Model
|
||||
|
||||
-}
|
||||
|
||||
import BackendTask exposing (BackendTask)
|
||||
import BackendTask.Custom
|
||||
import Date exposing (Date)
|
||||
import Dict
|
||||
import Effect
|
||||
import ErrorPage
|
||||
import FatalError
|
||||
import Form
|
||||
import Form.Field
|
||||
import Form.FieldView
|
||||
import Form.Validation
|
||||
import Head
|
||||
import Html exposing (Html)
|
||||
import Html.Attributes as Attr
|
||||
import Json.Decode as Decode
|
||||
import Json.Encode as Encode
|
||||
import Markdown.Parser
|
||||
import Markdown.Renderer
|
||||
import Pages.Msg
|
||||
import Pages.PageUrl
|
||||
import Path
|
||||
import Platform.Sub
|
||||
import Route
|
||||
import RouteBuilder
|
||||
import Server.Request
|
||||
import Server.Response
|
||||
import Shared
|
||||
import View
|
||||
|
||||
|
||||
type alias Model =
|
||||
{}
|
||||
|
||||
|
||||
type Msg
|
||||
= NoOp
|
||||
|
||||
|
||||
type alias RouteParams =
|
||||
{}
|
||||
|
||||
|
||||
route : RouteBuilder.StatefulRoute RouteParams Data ActionData Model Msg
|
||||
route =
|
||||
RouteBuilder.buildWithLocalState
|
||||
{ view = view
|
||||
, init = init
|
||||
, update = update
|
||||
, subscriptions = subscriptions
|
||||
}
|
||||
(RouteBuilder.serverRender { data = data, action = action, head = head })
|
||||
|
||||
|
||||
init :
|
||||
Maybe Pages.PageUrl.PageUrl
|
||||
-> Shared.Model
|
||||
-> RouteBuilder.StaticPayload Data ActionData RouteParams
|
||||
-> ( Model, Effect.Effect Msg )
|
||||
init pageUrl sharedModel app =
|
||||
( {}, Effect.none )
|
||||
|
||||
|
||||
update :
|
||||
Pages.PageUrl.PageUrl
|
||||
-> Shared.Model
|
||||
-> RouteBuilder.StaticPayload Data ActionData RouteParams
|
||||
-> Msg
|
||||
-> Model
|
||||
-> ( Model, Effect.Effect msg )
|
||||
update pageUrl sharedModel app msg model =
|
||||
case msg of
|
||||
NoOp ->
|
||||
( model, Effect.none )
|
||||
|
||||
|
||||
subscriptions :
|
||||
Maybe Pages.PageUrl.PageUrl
|
||||
-> RouteParams
|
||||
-> Path.Path
|
||||
-> Shared.Model
|
||||
-> Model
|
||||
-> Sub Msg
|
||||
subscriptions maybePageUrl routeParams path sharedModel model =
|
||||
Platform.Sub.none
|
||||
|
||||
|
||||
type alias Data =
|
||||
{}
|
||||
|
||||
|
||||
type alias ActionData =
|
||||
{ errors : Form.Response String
|
||||
, errorMessage : Maybe String
|
||||
}
|
||||
|
||||
|
||||
data :
|
||||
RouteParams
|
||||
-> Server.Request.Parser (BackendTask.BackendTask FatalError.FatalError (Server.Response.Response Data ErrorPage.ErrorPage))
|
||||
data routeParams =
|
||||
Server.Request.succeed (BackendTask.succeed (Server.Response.render {}))
|
||||
|
||||
|
||||
head : RouteBuilder.StaticPayload Data ActionData RouteParams -> List Head.Tag
|
||||
head app =
|
||||
[]
|
||||
|
||||
|
||||
view :
|
||||
Maybe Pages.PageUrl.PageUrl
|
||||
-> Shared.Model
|
||||
-> Model
|
||||
-> RouteBuilder.StaticPayload Data ActionData RouteParams
|
||||
-> View.View (Pages.Msg.Msg Msg)
|
||||
view maybeUrl sharedModel model app =
|
||||
{ title = "Posts.New"
|
||||
, body =
|
||||
[ Html.div
|
||||
[ Attr.style "display" "flex"
|
||||
, Attr.style "flex" "row"
|
||||
, Attr.class "hmmm"
|
||||
]
|
||||
[ Html.div []
|
||||
[ Html.h2
|
||||
[]
|
||||
[ Html.text "Form" ]
|
||||
, app.action
|
||||
|> Maybe.andThen .errorMessage
|
||||
|> Maybe.map
|
||||
(\errorMessage ->
|
||||
Html.p [ Attr.style "color" "red" ] [ Html.text errorMessage ]
|
||||
)
|
||||
|> Maybe.withDefault (Html.text "")
|
||||
, Form.renderHtml
|
||||
[]
|
||||
(\renderStyledHtmlUnpack -> Just renderStyledHtmlUnpack.errors)
|
||||
app
|
||||
()
|
||||
(Form.toDynamicTransition "form" form)
|
||||
]
|
||||
, postPreview app
|
||||
]
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
postPreview app =
|
||||
Html.div []
|
||||
[ Html.h1 []
|
||||
[ app.pageFormState
|
||||
|> Dict.get "form"
|
||||
|> Maybe.andThen (.fields >> Dict.get "title")
|
||||
|> Maybe.map .value
|
||||
|> Maybe.withDefault ""
|
||||
|> Html.text
|
||||
]
|
||||
, app.pageFormState
|
||||
|> Dict.get "form"
|
||||
|> Maybe.andThen (.fields >> Dict.get "body")
|
||||
|> Maybe.map .value
|
||||
|> Maybe.withDefault ""
|
||||
|> renderMarkdown
|
||||
]
|
||||
|
||||
|
||||
renderMarkdown : String -> Html msg
|
||||
renderMarkdown markdown =
|
||||
markdown
|
||||
|> Markdown.Parser.parse
|
||||
|> Result.withDefault []
|
||||
|> Markdown.Renderer.render Markdown.Renderer.defaultHtmlRenderer
|
||||
|> Result.withDefault []
|
||||
|> Html.div []
|
||||
|
||||
|
||||
action :
|
||||
RouteParams
|
||||
-> Server.Request.Parser (BackendTask.BackendTask FatalError.FatalError (Server.Response.Response ActionData ErrorPage.ErrorPage))
|
||||
action routeParams =
|
||||
Server.Request.map
|
||||
(\formData ->
|
||||
case formData of
|
||||
( formResponse, parsedForm ) ->
|
||||
case parsedForm of
|
||||
Ok okForm ->
|
||||
BackendTask.Custom.run "createPost"
|
||||
(Encode.object
|
||||
[ ( "slug", Encode.string okForm.slug )
|
||||
, ( "title", Encode.string okForm.title )
|
||||
, ( "body", Encode.string okForm.body )
|
||||
, ( "publish"
|
||||
, okForm.publish
|
||||
|> Maybe.map (Date.toIsoString >> Encode.string)
|
||||
|> Maybe.withDefault Encode.null
|
||||
)
|
||||
]
|
||||
)
|
||||
(Decode.oneOf
|
||||
[ Decode.field "errorMessage" (Decode.string |> Decode.map Err)
|
||||
, Decode.succeed (Ok ())
|
||||
]
|
||||
)
|
||||
|> BackendTask.allowFatal
|
||||
|> BackendTask.map
|
||||
(\result ->
|
||||
case result of
|
||||
Ok () ->
|
||||
Route.redirectTo (Route.Posts__Slug___Edit { slug = okForm.slug })
|
||||
|
||||
Err errorMessage ->
|
||||
Server.Response.render { errors = formResponse, errorMessage = Just errorMessage }
|
||||
)
|
||||
|
||||
Err errors ->
|
||||
Server.Response.render { errors = formResponse, errorMessage = Nothing }
|
||||
|> BackendTask.succeed
|
||||
)
|
||||
(Server.Request.formData (Form.initCombined Basics.identity form))
|
||||
|
||||
|
||||
form : Form.DoneForm String ParsedForm () (List (Html.Html (Pages.Msg.Msg Msg)))
|
||||
form =
|
||||
Form.field
|
||||
"publish"
|
||||
(Form.Field.date { invalid = \_ -> "" })
|
||||
((\title slug body publish ->
|
||||
{ combine =
|
||||
ParsedForm
|
||||
|> Form.Validation.succeed
|
||||
|> Form.Validation.andMap title
|
||||
|> Form.Validation.andMap
|
||||
(slug
|
||||
|> Form.Validation.andThen
|
||||
(\slugValue ->
|
||||
if slugValue |> String.contains " " then
|
||||
Form.Validation.withError slug
|
||||
"Cannot contain spaces"
|
||||
(Form.Validation.mapWithNever identity slug)
|
||||
|
||||
else
|
||||
Form.Validation.mapWithNever identity slug
|
||||
)
|
||||
)
|
||||
|> Form.Validation.andMap body
|
||||
|> Form.Validation.andMap publish
|
||||
, view =
|
||||
\formState ->
|
||||
let
|
||||
fieldView label field =
|
||||
Html.div
|
||||
[]
|
||||
[ Html.label
|
||||
[]
|
||||
[ Html.text (label ++ " ")
|
||||
, Form.FieldView.input [] field
|
||||
, errorsView
|
||||
formState.errors
|
||||
field
|
||||
]
|
||||
]
|
||||
in
|
||||
[ fieldView "title" title
|
||||
, fieldView "slug" slug
|
||||
, fieldView "body" body
|
||||
, fieldView "publish" publish
|
||||
, if formState.isTransitioning then
|
||||
Html.button [ Attr.disabled True ]
|
||||
[ Html.text "Submitting..."
|
||||
]
|
||||
|
||||
else
|
||||
Html.button []
|
||||
[ Html.text "Submit"
|
||||
]
|
||||
]
|
||||
}
|
||||
)
|
||||
|> Form.init
|
||||
|> Form.field "title" (Form.Field.required "Required" Form.Field.text)
|
||||
|> Form.field "slug" (Form.Field.required "Required" Form.Field.text)
|
||||
|> Form.field "body"
|
||||
(Form.Field.required "Required" Form.Field.text
|
||||
|> Form.Field.textarea
|
||||
{ rows = Just 30, cols = Just 80 }
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
type alias ParsedForm =
|
||||
{ title : String
|
||||
, slug : String
|
||||
, body : String
|
||||
, publish : Maybe Date
|
||||
}
|
||||
|
||||
|
||||
errorsView :
|
||||
Form.Errors String
|
||||
-> Form.Validation.Field String parsed kind
|
||||
-> Html.Html (Pages.Msg.Msg Msg)
|
||||
errorsView errors field =
|
||||
if List.isEmpty (Form.errorsForField field errors) then
|
||||
Html.div [] []
|
||||
|
||||
else
|
||||
Html.div []
|
||||
[ Html.ul []
|
||||
(List.map
|
||||
(\error ->
|
||||
Html.li
|
||||
[ Attr.style "color" "red" ]
|
||||
[ Html.text error ]
|
||||
)
|
||||
(Form.errorsForField field errors)
|
||||
)
|
||||
]
|
@ -4,6 +4,7 @@ import BackendTask exposing (BackendTask)
|
||||
import Effect exposing (Effect)
|
||||
import FatalError exposing (FatalError)
|
||||
import Html exposing (Html)
|
||||
import Html.Attributes as Attr
|
||||
import Pages.Flags
|
||||
import Pages.PageUrl exposing (PageUrl)
|
||||
import Path exposing (Path)
|
||||
@ -92,7 +93,10 @@ view :
|
||||
-> { body : List (Html msg), title : String }
|
||||
view stars page model toMsg pageView =
|
||||
{ body =
|
||||
[ Html.div [] pageView.body
|
||||
[ Html.div
|
||||
[ Attr.class "container"
|
||||
]
|
||||
pageView.body
|
||||
]
|
||||
, title = pageView.title
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
@import "https://unpkg.com/@picocss/pico@1.5.7/css/pico.min.css";
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
|
||||
sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
|
||||
|
Loading…
Reference in New Issue
Block a user