Skip to content

Instantly share code, notes, and snippets.

@zacck-zz
Last active October 28, 2018 22:18
Show Gist options
  • Save zacck-zz/883333830211d7a08024b9bfbc693085 to your computer and use it in GitHub Desktop.
Save zacck-zz/883333830211d7a08024b9bfbc693085 to your computer and use it in GitHub Desktop.
import Browser
import Browser.Navigation as Nav
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick)
import Url
import Route exposing(Route)
import Session exposing(Session)
import Page exposing(Page)
import Page.Landing as Landing
import Page.Blank as Blank
import Page.NotFound as NotFound
-- MAIN
main : Program () Model Msg
main =
Browser.application
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
, onUrlChange = UrlChanged
, onUrlRequest = LinkClicked
}
-- MODEL
type Model
= Redirect Session
| NotFound Session
| Landing Landing.Model
init : () -> Url.Url -> Nav.Key -> ( Model, Cmd Msg )
init flags url key =
changeRouteTo (Route.fromUrl url)
(Redirect (Session.decode key))
-- UPDATE
type Msg
= LinkClicked Browser.UrlRequest
| UrlChanged Url.Url
| Ignored
| GotLandingMsg Landing.Msg
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case (msg, model) of
(Ignored, _ ) ->
(model, Cmd.none)
(GotLandingMsg subMsg, Landing landing) ->
Landing.update subMsg landing
|> updateWith Landing GotLandingMsg model
(LinkClicked urlRequest, _ ) ->
case urlRequest of
Browser.Internal url ->
( model
, Nav.pushUrl (Session.navKey (toSession model)) (Url.toString url)
)
Browser.External href ->
( model, Nav.load href )
(UrlChanged url, _ ) ->
changeRouteTo (Route.fromUrl url) model
(_, _) ->
(model, Cmd.none)
changeRouteTo : Maybe Route -> Model -> (Model, Cmd Msg)
changeRouteTo maybeRoute model =
let
session =
toSession model
in
case maybeRoute of
Nothing ->
(NotFound session, Cmd.none)
Just Route.Landing ->
( model, Route.replaceUrl (Session.navKey session) Route.Landing )
Just Route.Register ->
( model, Route.replaceUrl (Session.navKey session) Route.Register )
Just Route.Login ->
( model, Route.replaceUrl (Session.navKey session) Route.Login )
toSession : Model -> Session
toSession page =
case page of
NotFound session ->
session
Landing landing ->
Landing.toSession landing
Redirect session ->
session
updateWith : (subModel -> Model) -> (subMsg -> Msg) -> Model -> ( subModel, Cmd subMsg ) -> (Model, Cmd Msg)
updateWith toModel toMsg model ( subModel, subCmd ) =
( toModel subModel
, Cmd.map toMsg subCmd
)
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions model =
case model of
NotFound _ ->
Sub.none
Redirect _ ->
Sub.none
Landing landing ->
Sub.none
-- VIEW
view : Model -> Browser.Document Msg
view model =
let
viewPage page toMsg config =
let
{title, body} =
Page.view page config
in
{ title = title
, body = List.map (Html.map toMsg) body
}
in
case model of
Redirect _ ->
viewPage Page.Other (\_ -> Ignored) Blank.view
NotFound _ ->
viewPage Page.Other (\_ -> Ignored) NotFound.view
Landing landingModel ->
viewPage Page.Landing GotLandingMsg (Landing.view landingModel)
module Page exposing (Page (..), view)
import Browser exposing (Document)
import Html exposing (..)
import Html.Attributes exposing (class, src)
{-| Nav Links -}
type Page
= Other
| Landing
{-| Accept a Page's Html and add a header above it and a footer below it -}
view : Page -> { title : String, content : Html msg } -> Document msg
view page {title, content} =
{ title = title
, body = viewHeader page :: content :: [ viewFooter ]
}
viewHeader : Page -> Html msg
viewHeader page =
case page of
Landing ->
landingHeader
Other ->
otherHeader
otherHeader : Html msg
otherHeader =
div [ class "header bar" ]
[ text ""]
landingHeader : Html msg
landingHeader =
div [ class "home-bar header-bar"]
(List.map headerIcon welcomeIcons)
viewFooter : Html msg
viewFooter =
div [ class "footer"]
[ text ""]
welcomeIcons: List String
welcomeIcons =
["images/level_z.png", "images/level_a.png", "images/completed_task.png", "images/prolonged.png"]
headerIcon : String -> Html msg
headerIcon imgSrc =
img [ src imgSrc, class "nav-icon"] []
module Route exposing (Route(..), fromUrl, replaceUrl)
import Url exposing (Url)
import Browser.Navigation as Nav
import Url.Parser as Parser exposing (Parser, oneOf, s)
type Route =
Landing
|Register
|Login
parser : Parser (Route -> a) a
parser =
oneOf
[ Parser.map Landing Parser.top
, Parser.map Register (s "register")
, Parser.map Login (s "login")
]
fromUrl : Url -> Maybe Route
fromUrl url =
Parser.parse parser url
replaceUrl : Nav.Key -> Route -> Cmd msg
replaceUrl key route =
Nav.replaceUrl key (toPath route)
toPath: Route -> String
toPath route =
case route of
Landing ->
"/"
Register ->
"/register"
Login ->
"/login"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment