elm-pages-v3-beta/examples/hackernews/app/Route/Stories/Id_.elm
2022-06-29 12:13:34 -07:00

210 lines
5.6 KiB
Elm

module Route.Stories.Id_ exposing (ActionData, Data, Model, Msg, route)
import DataSource exposing (DataSource)
import DataSource.Http
import Effect exposing (Effect)
import ErrorPage exposing (ErrorPage)
import Head
import Head.Seo as Seo
import Html exposing (Html)
import Html.Attributes as Attr
import Html.Keyed
import Json.Decode as Decode
import Json.Encode as Encode
import Pages.Msg
import Pages.PageUrl exposing (PageUrl)
import Pages.Url
import Path exposing (Path)
import RouteBuilder exposing (StatefulRoute, StatelessRoute, StaticPayload)
import Server.Request as Request
import Server.Response as Response exposing (Response)
import Shared
import Story exposing (Entry(..), Item(..))
import View exposing (View)
type alias Model =
{}
type Msg
= NoOp
type alias RouteParams =
{ id : String }
route : StatefulRoute RouteParams Data ActionData Model Msg
route =
RouteBuilder.serverRender
{ head = head
, data = data
, action = \_ -> Request.skip "No action."
}
|> RouteBuilder.buildWithLocalState
{ view = view
, update = update
, subscriptions = subscriptions
, init = init
}
init :
Maybe PageUrl
-> Shared.Model
-> StaticPayload Data ActionData RouteParams
-> ( Model, Effect Msg )
init maybePageUrl sharedModel static =
( {}, Effect.none )
update :
PageUrl
-> Shared.Model
-> StaticPayload Data ActionData RouteParams
-> Msg
-> Model
-> ( Model, Effect Msg )
update pageUrl sharedModel static msg model =
case msg of
NoOp ->
( model, Effect.none )
subscriptions : Maybe PageUrl -> RouteParams -> Path -> Shared.Model -> Model -> Sub Msg
subscriptions maybePageUrl routeParams path sharedModel model =
Sub.none
pages : DataSource (List RouteParams)
pages =
DataSource.succeed []
type alias Data =
{ story : ( Item, String )
}
type alias ActionData =
{}
data : RouteParams -> Request.Parser (DataSource (Response Data ErrorPage))
data routeParams =
Request.succeed
(DataSource.Http.get ("https://node-hnapi.herokuapp.com/item/" ++ routeParams.id)
(Decode.map2 Tuple.pair
Story.decoder
(Decode.field "comments" (Decode.value |> Decode.map (Encode.encode 0)))
)
|> DataSource.map
(\story ->
Response.render
(Data story)
)
)
head :
StaticPayload Data ActionData RouteParams
-> List Head.Tag
head static =
Seo.summary
{ canonicalUrlOverride = Nothing
, siteName = "elm-pages Hacker News"
, image =
{ url = [ "images", "icon-png.png" ] |> Path.join |> Pages.Url.fromPath
, alt = "elm-pages logo"
, dimensions = Nothing
, mimeType = Nothing
}
, description = "A demo of elm-pages 3 server-rendered routes."
, locale = Nothing
, title = static.data.story |> Tuple.first |> (\(Item common _) -> common.title)
}
|> Seo.website
view :
Maybe PageUrl
-> Shared.Model
-> Model
-> StaticPayload Data ActionData RouteParams
-> View (Pages.Msg.Msg Msg)
view maybeUrl sharedModel model static =
{ title = static.data.story |> Tuple.first |> (\(Item common _) -> common.title)
, body =
[ storyView static.data.story
]
}
storyView : ( Item, String ) -> Html msg
storyView ( Item story entry, commentsJson ) =
Html.div
[ Attr.class "item-view"
]
[ Html.div
[ Attr.class "item-view-header"
]
[ Html.a
[ Attr.href story.url
, Attr.target "_blank"
, Attr.rel "noreferrer"
]
[ Html.h1 []
[ Html.text story.title ]
]
, Html.text " "
, Story.domainView story.domain
, Html.p
[ Attr.class "meta"
]
((case entry of
Story { points, user } ->
[ Html.text <| (String.fromInt points ++ " points | ")
, Html.text "by "
, Html.a
[ Attr.href <|
"/users/"
++ user
]
[ Html.text user
]
]
_ ->
[]
)
++ [ Html.text <| " " ++ story.time_ago ++ " ago" ]
)
]
, Html.div
[ Attr.class "item-view-comments"
]
[ Html.p
[ Attr.class "item-view-comments-header"
]
[ if story.comments_count > 0 then
Html.text <| String.fromInt story.comments_count ++ " comments"
else
Html.text "No comments yet."
]
, Html.Keyed.ul
[ Attr.class "comment-children"
]
((commentsJson
|> Decode.decodeString (Decode.list Decode.value)
|> Result.withDefault []
)
|> List.indexedMap
(\index comment ->
( String.fromInt index, Html.node "news-comment" [ Attr.property "commentBody" comment ] [] )
)
)
]
]