Files
elm-0.19-workshop/intro/part7/src/Page.elm
Richard Feldman 7208ff4557 Add part7
2018-08-12 00:03:39 -04:00

160 lines
4.5 KiB
Elm
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
module Page exposing (Page(..), view, viewErrors)
import Avatar
import Browser exposing (Document)
import Html exposing (Html, a, button, div, footer, i, img, li, nav, p, span, text, ul)
import Html.Attributes exposing (class, classList, href, style)
import Html.Events exposing (onClick)
import Profile
import Route exposing (Route)
import Session exposing (Session)
import Username exposing (Username)
import Viewer exposing (Viewer)
import Viewer.Cred as Cred exposing (Cred)
{-| Determines which navbar link (if any) will be rendered as active.
Note that we don't enumerate every page here, because the navbar doesn't
have links for every page. Anything that's not part of the navbar falls
under Other.
-}
type Page
= Other
| Home
| Login
| Register
| Settings
| Profile Username
| NewArticle
{-| Take a page's Html and frames it with a header and footer.
The caller provides the current user, so we can display in either
"signed in" (rendering username) or "signed out" mode.
isLoading is for determining whether we should show a loading spinner
in the header. (This comes up during slow page transitions.)
-}
view : Maybe Viewer -> Page -> { title : String, content : Html msg } -> Document msg
view maybeViewer page { title, content } =
{ title = title ++ " - Conduit"
, body = viewHeader page maybeViewer :: content :: [ viewFooter ]
}
viewHeader : Page -> Maybe Viewer -> Html msg
viewHeader page maybeViewer =
nav [ class "navbar navbar-light" ]
[ div [ class "container" ]
[ a [ class "navbar-brand", Route.href Route.Home ]
[ text "conduit" ]
, ul [ class "nav navbar-nav pull-xs-right" ] <|
navbarLink page Route.Home [ text "Home" ]
:: viewMenu page maybeViewer
]
]
viewMenu : Page -> Maybe Viewer -> List (Html msg)
viewMenu page maybeViewer =
let
linkTo =
navbarLink page
in
case maybeViewer of
Just viewer ->
let
cred =
Viewer.cred viewer
username =
Cred.username cred
avatar =
Profile.avatar (Viewer.profile viewer)
in
[ linkTo Route.NewArticle [ i [ class "ion-compose" ] [], text " New Post" ]
, linkTo Route.Settings [ i [ class "ion-gear-a" ] [], text " Settings" ]
, linkTo
(Route.Profile username)
[ img [ class "user-pic", Avatar.src avatar ] []
, Username.toHtml username
]
, linkTo Route.Logout [ text "Sign out" ]
]
Nothing ->
[ linkTo Route.Login [ text "Sign in" ]
, linkTo Route.Register [ text "Sign up" ]
]
viewFooter : Html msg
viewFooter =
footer []
[ div [ class "container" ]
[ a [ class "logo-font", href "/" ] [ text "conduit" ]
, span [ class "attribution" ]
[ text "An interactive learning project from "
, a [ href "https://thinkster.io" ] [ text "Thinkster" ]
, text ". Code & design licensed under MIT."
]
]
]
navbarLink : Page -> Route -> List (Html msg) -> Html msg
navbarLink page route linkContent =
li [ classList [ ( "nav-item", True ), ( "active", isActive page route ) ] ]
[ a [ class "nav-link", Route.href route ] linkContent ]
isActive : Page -> Route -> Bool
isActive page route =
case ( page, route ) of
( Home, Route.Home ) ->
True
( Login, Route.Login ) ->
True
( Register, Route.Register ) ->
True
( Settings, Route.Settings ) ->
True
( Profile pageUsername, Route.Profile routeUsername ) ->
pageUsername == routeUsername
( NewArticle, Route.NewArticle ) ->
True
_ ->
False
{-| Render dismissable errors. We use this all over the place!
-}
viewErrors : msg -> List String -> Html msg
viewErrors dismissErrors errors =
if List.isEmpty errors then
Html.text ""
else
div
[ class "error-messages"
, style "position" "fixed"
, style "top" "0"
, style "background" "rgb(250, 250, 250)"
, style "padding" "20px"
, style "border" "1px solid"
]
<|
List.map (\error -> p [] [ text error ]) errors
++ [ button [ onClick dismissErrors ] [ text "Ok" ] ]