elm-pages-v3-beta/examples/pokedex/app/Route/Todos.elm

301 lines
8.1 KiB
Elm
Raw Normal View History

module Route.Todos exposing (Data, Model, Msg, route)
2022-01-25 07:55:07 +03:00
import Api.InputObject
import Api.Mutation
import Api.Object
2022-01-25 07:55:07 +03:00
import Api.Object.Todo
import Api.Object.TodoPage
import Api.Query
import Api.Scalar exposing (Id(..))
import DataSource exposing (DataSource)
2022-03-29 01:11:07 +03:00
import Effect exposing (Effect)
2022-03-29 21:48:04 +03:00
import ErrorPage exposing (ErrorPage)
2022-01-25 07:55:07 +03:00
import Form exposing (Form)
import Form.Value
import Graphql.Operation exposing (RootMutation, RootQuery)
import Graphql.SelectionSet as SelectionSet
import Head
import Head.Seo as Seo
import Html exposing (Html)
import Html.Attributes as Attr
import Pages.PageUrl exposing (PageUrl)
import Pages.Url
import Path exposing (Path)
import Request.Fauna
2022-03-05 20:50:01 +03:00
import RouteBuilder exposing (StatefulRoute, StatelessRoute, StaticPayload)
import Server.Request as Request exposing (Parser)
2022-01-25 07:55:07 +03:00
import Server.Response as Response exposing (Response)
import Shared
import Time
import View exposing (View)
type alias Model =
2022-04-04 19:40:37 +03:00
{ submitting : Bool
}
2022-01-25 07:55:07 +03:00
type Msg
= FormMsg Form.Msg
| NoOp
2022-04-05 00:45:14 +03:00
| FormSubmitted { contentType : String, body : String }
2022-04-04 19:40:37 +03:00
| SubmitComplete
2022-01-25 07:55:07 +03:00
type alias RouteParams =
{}
route : StatefulRoute RouteParams Data Model Msg
route =
2022-03-05 20:50:01 +03:00
RouteBuilder.serverRender
2022-01-25 07:55:07 +03:00
{ head = head
, data = data
}
2022-03-05 20:50:01 +03:00
|> RouteBuilder.buildWithLocalState
2022-01-25 07:55:07 +03:00
{ view = view
, update = update
, subscriptions = subscriptions
, init = init
}
init :
Maybe PageUrl
-> Shared.Model
-> StaticPayload Data RouteParams
2022-03-29 01:11:07 +03:00
-> ( Model, Effect Msg )
2022-01-25 07:55:07 +03:00
init maybePageUrl sharedModel static =
2022-04-05 19:05:26 +03:00
( { submitting = False }
, Effect.none
)
2022-01-25 07:55:07 +03:00
update :
PageUrl
-> Shared.Model
-> StaticPayload Data RouteParams
-> Msg
-> Model
2022-03-29 01:11:07 +03:00
-> ( Model, Effect Msg )
update pageUrl sharedModel static msg model =
2022-01-25 07:55:07 +03:00
case msg of
FormMsg formMsg ->
2022-03-29 01:11:07 +03:00
( model, Effect.none )
2022-01-25 07:55:07 +03:00
NoOp ->
2022-03-29 01:11:07 +03:00
( model, Effect.none )
2022-01-25 07:55:07 +03:00
2022-04-05 00:45:14 +03:00
FormSubmitted info ->
2022-04-04 19:40:37 +03:00
( { model | submitting = True }
2022-04-05 00:45:14 +03:00
, Effect.FetchRouteData
2022-04-04 19:40:37 +03:00
{ body = Just info
, path = Nothing
, toMsg = \_ -> SubmitComplete
}
)
SubmitComplete ->
( { model | submitting = False }, Effect.none )
2022-01-25 07:55:07 +03:00
subscriptions : Maybe PageUrl -> RouteParams -> Path -> Shared.Model -> Model -> Sub Msg
subscriptions maybePageUrl routeParams path sharedModel model =
Sub.none
type alias Data =
{ todos : List Todo
}
type alias Todo =
{ description : String
, id : String
}
type alias TodoInput =
{ description : String }
todos : SelectionSet.SelectionSet (List Todo) RootQuery
todos =
Api.Query.allTodos identity
(Api.Object.TodoPage.data todoSelection
|> SelectionSet.nonNullElementsOrFail
)
createTodo : String -> SelectionSet.SelectionSet Todo RootMutation
createTodo description =
Api.Mutation.createTodo
{ data =
Api.InputObject.buildTodoInput
{ description = description
, completed = False
}
}
todoSelection
deleteTodo : String -> SelectionSet.SelectionSet () RootMutation
deleteTodo id =
Api.Mutation.deleteTodo { id = Id id }
(Api.Object.Todo.id_ |> SelectionSet.map (\_ -> ()))
|> SelectionSet.map (Maybe.withDefault ())
todoSelection : SelectionSet.SelectionSet Todo Api.Object.Todo
2022-01-25 07:55:07 +03:00
todoSelection =
SelectionSet.map2 Todo
Api.Object.Todo.description
(Api.Object.Todo.id_ |> SelectionSet.map (\(Id id) -> id))
2022-03-29 21:48:04 +03:00
data : RouteParams -> Parser (DataSource (Response Data ErrorPage))
2022-01-25 07:55:07 +03:00
data routeParams =
Request.oneOf
[ Form.submitHandlers2 (deleteItemForm "")
(\model decoded ->
case decoded of
Ok id ->
Request.Fauna.mutationDataSource "" (deleteTodo id)
|> DataSource.map
(\_ ->
Response.temporaryRedirect "/todos"
)
Err error ->
2022-03-31 19:50:45 +03:00
{ todos = [] }
2022-01-25 07:55:07 +03:00
|> Response.render
|> DataSource.succeed
)
2022-04-04 19:40:37 +03:00
, Form.submitHandlers2 (newItemForm False)
2022-01-25 07:55:07 +03:00
(\model decoded ->
case decoded of
Ok okItem ->
Request.Fauna.mutationDataSource "" (createTodo okItem.description)
|> DataSource.map
(\_ ->
Response.temporaryRedirect "/todos"
)
Err error ->
2022-03-31 19:50:45 +03:00
{ todos = []
2022-01-25 07:55:07 +03:00
}
|> Response.render
|> DataSource.succeed
)
, Request.requestTime
|> Request.map
(\time ->
Request.Fauna.dataSource (time |> Time.posixToMillis |> String.fromInt) todos
|> DataSource.map Data
|> DataSource.map Response.render
)
]
head :
StaticPayload Data RouteParams
-> List Head.Tag
head static =
Seo.summary
{ canonicalUrlOverride = Nothing
, siteName = "Full-stack elm-pages"
, image =
{ url = Pages.Url.external "TODO"
, alt = "elm-pages logo"
, dimensions = Nothing
, mimeType = Nothing
}
, description = "Full-stack elm-pages Todo App demo"
, locale = Nothing
, title = "elm-pages Todo App"
}
|> Seo.website
view :
Maybe PageUrl
-> Shared.Model
-> Model
-> StaticPayload Data RouteParams
-> View Msg
view maybeUrl sharedModel model static =
{ title = "Todos"
, body =
[ Html.ul []
(static.data.todos
|> List.map
(\item ->
Html.li []
[ Html.text item.description
, deleteItemForm item.id
|> Form.toHtml2
2022-04-05 00:45:14 +03:00
{ onSubmit = FormSubmitted }
2022-01-25 07:55:07 +03:00
Html.form
(Form.init (deleteItemForm item.id))
]
)
)
2022-04-04 19:40:37 +03:00
, newItemForm model.submitting
|> Form.toHtml2
2022-04-05 00:45:14 +03:00
{ onSubmit = FormSubmitted }
2022-01-25 07:55:07 +03:00
Html.form
2022-04-04 19:40:37 +03:00
(Form.init (newItemForm model.submitting))
2022-01-25 07:55:07 +03:00
]
}
2022-04-04 19:40:37 +03:00
newItemForm : Bool -> Form String TodoInput (Html Msg)
newItemForm submitting =
2022-01-25 07:55:07 +03:00
Form.succeed (\description () -> TodoInput description)
|> Form.with
(Form.text "description"
(\{ toInput } ->
Html.input (Attr.autofocus True :: toInput) []
|> Html.map (\_ -> NoOp)
2022-01-25 07:55:07 +03:00
)
|> Form.required "Required"
)
|> Form.with
(Form.submit
(\{ attrs } ->
2022-04-04 19:40:37 +03:00
Html.button attrs
[ Html.text
(if submitting then
"Submitting..."
else
"Submit"
)
]
|> Html.map (\_ -> NoOp)
)
)
2022-01-25 07:55:07 +03:00
deleteItemForm : String -> Form String String (Html Msg)
deleteItemForm id =
Form.succeed
(\id_ _ -> id_)
|> Form.with
(Form.hidden "id"
id
(\attrs ->
Html.input attrs []
|> Html.map (\_ -> NoOp)
)
|> Form.withInitialValue (Form.Value.string id)
)
|> Form.with
(Form.submit
(\{ attrs } ->
Html.button attrs
[ Html.text "X" ]
|> Html.map (\_ -> NoOp)
)
)