i am so happy about the monster ive become

This commit is contained in:
Ryan Haskell-Glatz 2019-10-15 22:08:10 -05:00
parent 0bb507eac3
commit 778881da3a
28 changed files with 240 additions and 1771 deletions

View File

@ -0,0 +1,93 @@
module Application exposing
( Application, create
, Page, Bundle, keep
, Static, static
, Sandbox, sandbox
)
{-|
@docs Application, create
@docs Page, Bundle, keep
@docs Static, static
@docs Sandbox, sandbox
-}
import Browser
import Internals.Page as Page
-- APPLICATION
type alias Application model msg =
Platform.Program () model msg
create :
{ route : route
, pages :
{ init : route -> model
, update : msg -> model -> model
, bundle : model -> Page.Bundle msg
}
}
-> Application model msg
create config =
Browser.sandbox
{ init = config.pages.init config.route
, update = config.pages.update
, view = config.pages.bundle >> .view
}
-- PAGE
type alias Page pageModel pageMsg model msg =
Page.Page pageModel pageMsg model msg
type alias Bundle msg =
Page.Bundle msg
keep : model -> model
keep =
identity
type alias Static =
Page.Static
type alias Sandbox pageModel pageMsg =
Page.Sandbox pageModel pageMsg
static :
Static
->
{ toModel : () -> model
, toMsg : Never -> msg
}
-> Page () Never model msg
static =
Page.static
sandbox :
Sandbox pageModel pageMsg
->
{ toModel : pageModel -> model
, toMsg : pageMsg -> msg
}
-> Page pageModel pageMsg model msg
sandbox =
Page.sandbox

View File

@ -1,188 +0,0 @@
module Application.Element exposing
( Application, create
, Page
, Static, static
, Sandbox, sandbox
, Element, element
, Init, init
, Update, update, keep
, Bundle, bundle
)
{-|
@docs Application, create
@docs Page
@docs Static, static
@docs Sandbox, sandbox
@docs Element, element
@docs Init, init
@docs Update, update, keep
@docs Bundle, bundle
-}
import Application.Internals.Element.Bundle as Bundle
import Application.Internals.Element.Init as Init
import Application.Internals.Element.Page as Page
import Application.Internals.Element.Routing as Routing
import Application.Internals.Element.Update as Update
import Browser
-- APPLICATION
type alias Application route flags model msg =
Platform.Program flags (Routing.Model route model msg) (Routing.Msg route msg)
create :
{ routing :
{ initial : route
, routes : List ( String, route )
}
, pages :
{ init : route -> Init flags model msg
, update : msg -> model -> Update model msg
, bundle : model -> Bundle model msg
}
}
-> Application route flags model msg
create config =
Browser.element
{ init =
Routing.init
{ init = Init.create config.pages.init
, route = config.routing.initial
}
, update =
Routing.update
{ update = Update.create config.pages.update
}
, view =
Routing.view
{ view = Bundle.createView config.pages.bundle
, routes = config.routing.routes
}
, subscriptions =
Routing.subscriptions
{ subscriptions = Bundle.createSubscriptions config.pages.bundle
}
}
-- INIT
type alias Init flags model msg =
Init.Init flags model msg
init :
Page flags pageModel pageMsg model msg
-> Init flags model msg
init =
Init.init
-- UPDATE
type alias Update model msg =
Update.Update model msg
update :
{ page : Page flags pageModel pageMsg model msg
, model : pageModel
, msg : pageMsg
}
-> Update model msg
update =
Update.update
keep : model -> Update model msg
keep =
Update.keep
-- BUNDLE
type alias Bundle model msg =
Bundle.Bundle model msg
bundle :
{ page : Page flags pageModel pageMsg model msg
, model : pageModel
}
-> Bundle model msg
bundle =
Bundle.bundle
-- PAGE
type alias Page flags pageModel pageMsg model msg =
Page.Page flags pageModel pageMsg model msg
type alias Static =
Page.Static
type alias Sandbox pageModel pageMsg =
Page.Sandbox pageModel pageMsg
type alias Element flags pageModel pageMsg =
Page.Element flags pageModel pageMsg
static :
Static
->
{ toModel : () -> model
, toMsg : Never -> msg
}
-> Page flags () Never model msg
static =
Page.static
sandbox :
Sandbox pageModel pageMsg
->
{ toModel : pageModel -> model
, toMsg : pageMsg -> msg
}
-> Page flags pageModel pageMsg model msg
sandbox =
Page.sandbox
element :
Element flags pageModel pageMsg
->
{ toModel : pageModel -> model
, toMsg : pageMsg -> msg
}
-> Page flags pageModel pageMsg model msg
element =
Page.element

View File

@ -1,57 +0,0 @@
module Application.Internals.Element.Bundle exposing
( Bundle
, bundle
, createSubscriptions
, createView
)
import Application.Internals.Element.Page as Page exposing (Page)
import Html exposing (Html)
type Bundle model msg
= Bundle (Bundle_ model msg)
type alias Bundle_ model msg =
{ view : model -> Html msg
, subscriptions : model -> Sub msg
}
createView :
(model -> Bundle model msg)
-> model
-> Html msg
createView fn model =
fn model
|> (\(Bundle { view }) -> view model)
createSubscriptions :
(model -> Bundle model msg)
-> model
-> Sub msg
createSubscriptions fn model =
fn model
|> (\(Bundle { subscriptions }) -> subscriptions model)
bundle :
{ page : Page flags pageModel pageMsg model msg
, model : pageModel
}
-> Bundle model msg
bundle config =
let
p =
Page.unwrap config.page
in
Bundle
{ view =
always (p.page.view config.model)
>> Html.map p.toMsg
, subscriptions =
always (p.page.subscriptions config.model)
>> Sub.map p.toMsg
}

View File

@ -1,39 +0,0 @@
module Application.Internals.Element.Init exposing
( Init
, create
, init
)
import Application.Internals.Element.Page as Page exposing (Page)
type Init flags model msg
= Init (Init_ flags model msg)
type alias Init_ flags model msg =
flags -> ( model, Cmd msg )
init :
Page flags pageModel pageMsg model msg
-> Init flags model msg
init page =
let
p =
Page.unwrap page
in
Init
(\flags ->
p.page.init flags
|> Tuple.mapBoth p.toModel (Cmd.map p.toMsg)
)
create :
(route -> Init flags model msg)
-> route
-> flags
-> ( model, Cmd msg )
create fn route flags =
fn route |> (\(Init g) -> g flags)

View File

@ -1,126 +0,0 @@
module Application.Internals.Element.Page exposing
( Page
, Static, static
, Sandbox, sandbox
, Element, element
, unwrap
)
{-|
@docs Page
@docs Static, static
@docs Sandbox, sandbox
@docs Element, element
@docs unwrap
-}
import Html exposing (Html)
type Page flags pageModel pageMsg model msg
= Page (Page_ flags pageModel pageMsg model msg)
type alias Page_ flags pageModel pageMsg model msg =
{ toModel : pageModel -> model
, toMsg : pageMsg -> msg
, page : Element flags pageModel pageMsg
}
unwrap :
Page flags pageModel pageMsg model msg
-> Page_ flags pageModel pageMsg model msg
unwrap (Page page) =
page
-- STATIC
type alias Static =
{ view : Html Never
}
static :
Static
->
{ toModel : () -> model
, toMsg : Never -> msg
}
-> Page flags () Never model msg
static page { toModel, toMsg } =
Page
{ toModel = toModel
, toMsg = toMsg
, page =
{ init = \_ -> ( (), Cmd.none )
, update = \_ model -> ( model, Cmd.none )
, view = \_ -> Html.map never page.view
, subscriptions = \_ -> Sub.none
}
}
-- SANDBOX
type alias Sandbox pageModel pageMsg =
{ init : pageModel
, update : pageMsg -> pageModel -> pageModel
, view : pageModel -> Html pageMsg
}
sandbox :
Sandbox pageModel pageMsg
->
{ toModel : pageModel -> model
, toMsg : pageMsg -> msg
}
-> Page flags pageModel pageMsg model msg
sandbox page { toModel, toMsg } =
Page
{ toModel = toModel
, toMsg = toMsg
, page =
{ init = \_ -> ( page.init, Cmd.none )
, update = \msg model -> ( page.update msg model, Cmd.none )
, view = page.view
, subscriptions = \_ -> Sub.none
}
}
-- ELEMENT
type alias Element flags pageModel pageMsg =
{ init : flags -> ( pageModel, Cmd pageMsg )
, update : pageMsg -> pageModel -> ( pageModel, Cmd pageMsg )
, view : pageModel -> Html pageMsg
, subscriptions : pageModel -> Sub pageMsg
}
element :
Element flags pageModel pageMsg
->
{ toModel : pageModel -> model
, toMsg : pageMsg -> msg
}
-> Page flags pageModel pageMsg model msg
element page { toModel, toMsg } =
Page
{ toModel = toModel
, toMsg = toMsg
, page = page
}

View File

@ -1,101 +0,0 @@
module Application.Internals.Element.Routing exposing
( Model
, Msg
, init
, subscriptions
, update
, view
)
import Html exposing (..)
import Html.Events as Events
type alias Model route model msg =
{ init : route -> ( model, Cmd msg )
, page : model
}
type Msg route msg
= RouteChange route
| PageMsg msg
-- INIT
init :
{ init : route -> flags -> ( model, Cmd msg )
, route : route
}
-> flags
-> ( Model route model msg, Cmd (Msg route msg) )
init config flags =
let
( model, cmd ) =
config.init config.route flags
in
( { init = \r -> config.init r flags
, page = model
}
, Cmd.map PageMsg cmd
)
-- UPDATE
update :
{ update : msg -> model -> ( model, Cmd msg ) }
-> Msg route msg
-> Model route model msg
-> ( Model route model msg, Cmd (Msg route msg) )
update config msg model =
case msg of
RouteChange route ->
Tuple.mapBoth
(\page -> { model | page = page })
(Cmd.map PageMsg)
(model.init route)
PageMsg pageMsg ->
Tuple.mapBoth
(\page -> { model | page = page })
(Cmd.map PageMsg)
(config.update pageMsg model.page)
-- VIEW
view :
{ routes : List ( String, route ), view : model -> Html msg }
-> Model route model msg
-> Html (Msg route msg)
view config model =
div []
[ p []
(List.map
(\( label, route ) ->
button [ Events.onClick (RouteChange route) ] [ text label ]
)
config.routes
)
, Html.map PageMsg (config.view model.page)
]
-- SUBSCRIPTIONS
subscriptions :
{ subscriptions : model -> Sub msg }
-> Model route model msg
-> Sub (Msg route msg)
subscriptions config model =
Sub.map PageMsg (config.subscriptions model.page)

View File

@ -1,48 +0,0 @@
module Application.Internals.Element.Update exposing
( Update
, create
, keep
, update
)
import Application.Internals.Element.Page as Page exposing (Page)
type Update model msg
= Update (Update_ model msg)
type alias Update_ model msg =
( model, Cmd msg )
create :
(msg -> model -> Update model msg)
-> msg
-> model
-> ( model, Cmd msg )
create fn msg model =
fn msg model
|> (\(Update result) -> result)
update :
{ page : Page flags pageModel pageMsg model msg
, model : pageModel
, msg : pageMsg
}
-> Update model msg
update config =
let
p =
Page.unwrap config.page
in
Update
(p.page.update config.msg config.model
|> Tuple.mapBoth p.toModel (Cmd.map p.toMsg)
)
keep : model -> Update model msg
keep model =
Update ( model, Cmd.none )

View File

@ -1,43 +0,0 @@
module Application.Internals.Sandbox.Bundle exposing
( Bundle
, bundle
, createView
)
import Application.Internals.Sandbox.Page as Page exposing (Page)
import Html exposing (Html)
type Bundle model msg
= Bundle (Bundle_ model msg)
type alias Bundle_ model msg =
{ view : model -> Html msg
}
createView :
(model -> Bundle model msg)
-> model
-> Html msg
createView fn model =
fn model
|> (\(Bundle { view }) -> view model)
bundle :
{ page : Page pageModel pageMsg model msg
, model : pageModel
}
-> Bundle model msg
bundle config =
let
p =
Page.unwrap config.page
in
Bundle
{ view =
always (p.page.view config.model)
>> Html.map p.toMsg
}

View File

@ -1,29 +0,0 @@
module Application.Internals.Sandbox.Init exposing
( Init
, create
, init
)
import Application.Internals.Sandbox.Page as Page exposing (Page)
type Init model
= Init model
init :
Page pageModel pageMsg model msg
-> Init model
init page =
let
p =
Page.unwrap page
in
Init (p.page.init |> p.toModel)
create :
Init model
-> model
create (Init value) =
value

View File

@ -1,44 +0,0 @@
module Application.Internals.Sandbox.Update exposing
( Update
, create
, keep
, update
)
import Application.Internals.Sandbox.Page as Page exposing (Page)
type Update model
= Update model
create :
(msg -> model -> Update model)
-> msg
-> model
-> model
create fn msg model =
fn msg model
|> (\(Update result) -> result)
update :
{ page : Page pageModel pageMsg model msg
, model : pageModel
, msg : pageMsg
}
-> Update model
update config =
let
p =
Page.unwrap config.page
in
Update
(p.page.update config.msg config.model
|> p.toModel
)
keep : model -> Update model
keep =
Update

View File

@ -1,151 +0,0 @@
module Application.Sandbox exposing
( Application, create
, Page
, Static, static
, Sandbox, sandbox
, Init, init
, Update, update, keep
, Bundle, bundle
)
{-|
@docs Application, create
@docs Page
@docs Static, static
@docs Sandbox, sandbox
@docs Init, init
@docs Update, update, keep
@docs Bundle, bundle
-}
import Application.Internals.Sandbox.Bundle as Bundle
import Application.Internals.Sandbox.Init as Init
import Application.Internals.Sandbox.Page as Page
import Application.Internals.Sandbox.Update as Update
import Browser
-- APPLICATION
type alias Application model msg =
Platform.Program () model msg
create :
{ route : route
, pages :
{ init : route -> Init model
, update : msg -> model -> Update model
, bundle : model -> Bundle model msg
}
}
-> Application model msg
create config =
Browser.sandbox
{ init = Init.create (config.pages.init config.route)
, update = Update.create config.pages.update
, view = Bundle.createView config.pages.bundle
}
-- INIT
type alias Init model =
Init.Init model
init :
Page pageModel pageMsg model msg
-> Init model
init =
Init.init
-- UPDATE
type alias Update model =
Update.Update model
update :
{ page : Page pageModel pageMsg model msg
, model : pageModel
, msg : pageMsg
}
-> Update model
update =
Update.update
keep : model -> Update model
keep =
Update.keep
-- BUNDLE
type alias Bundle model msg =
Bundle.Bundle model msg
bundle :
{ page : Page pageModel pageMsg model msg
, model : pageModel
}
-> Bundle model msg
bundle =
Bundle.bundle
-- PAGE
type alias Page pageModel pageMsg model msg =
Page.Page pageModel pageMsg model msg
type alias Static =
Page.Static
type alias Sandbox pageModel pageMsg =
Page.Sandbox pageModel pageMsg
static :
Static
->
{ toModel : () -> model
, toMsg : Never -> msg
}
-> Page () Never model msg
static =
Page.static
sandbox :
Sandbox pageModel pageMsg
->
{ toModel : pageModel -> model
, toMsg : pageMsg -> msg
}
-> Page pageModel pageMsg model msg
sandbox =
Page.sandbox

View File

@ -1,41 +1,33 @@
module Application.Internals.Sandbox.Page exposing
( Page
module Internals.Page exposing
( Page, Bundle
, Static, static
, Sandbox, sandbox
, unwrap
)
{-|
@docs Page
@docs Page, Bundle
@docs Static, static
@docs Sandbox, sandbox
@docs unwrap
-}
import Html exposing (Html)
type Page pageModel pageMsg model msg
= Page (Page_ pageModel pageMsg model msg)
type alias Page_ pageModel pageMsg model msg =
{ toModel : pageModel -> model
, toMsg : pageMsg -> msg
, page : Sandbox pageModel pageMsg
type alias Page pageModel pageMsg model msg =
{ init : model
, update : pageMsg -> pageModel -> model
, keep : model -> model
, bundle : pageModel -> Bundle msg
}
unwrap :
Page pageModel pageMsg model msg
-> Page_ pageModel pageMsg model msg
unwrap (Page page) =
page
type alias Bundle msg =
{ view : Html msg
}
@ -55,15 +47,14 @@ static :
}
-> Page () Never model msg
static page { toModel, toMsg } =
Page
{ toModel = toModel
, toMsg = toMsg
, page =
{ init = ()
, update = always identity
, view = \_ -> Html.map never page.view
{ init = toModel ()
, update = always toModel
, keep = identity
, bundle =
always
{ view = Html.map toMsg page.view
}
}
}
@ -85,8 +76,11 @@ sandbox :
}
-> Page pageModel pageMsg model msg
sandbox page { toModel, toMsg } =
Page
{ toModel = toModel
, toMsg = toMsg
, page = page
}
{ init = toModel page.init
, update = \msg model -> page.update msg model |> toModel
, keep = identity
, bundle =
\model ->
{ view = page.view model |> Html.map toMsg
}
}

View File

@ -1,177 +0,0 @@
module Element.Main exposing (main)
import Application.Element as Application exposing (Application)
import Element.Pages.Counter as Counter
import Element.Pages.Homepage as Homepage
import Element.Pages.NotFound as NotFound
import Element.Pages.Random as Random
type Route
= Homepage
| Counter
| Random
| NotFound
type alias Flags =
()
main : Application Route Flags Model Msg
main =
Application.create
{ routing =
{ initial = Random
, routes =
[ ( "Homepage", Homepage )
, ( "Counter", Counter )
, ( "Random", Random )
, ( "Not Found", NotFound )
]
}
, pages =
{ init = init
, update = update
, bundle = bundle
}
}
type Model
= HomepageModel Homepage.Model
| CounterModel Counter.Model
| RandomModel Random.Model
| NotFoundModel NotFound.Model
type Msg
= HomepageMsg Homepage.Msg
| CounterMsg Counter.Msg
| RandomMsg Random.Msg
| NotFoundMsg NotFound.Msg
-- CAN / SHOULD BE GENERATED
type alias Pages =
{ homepage : Application.Page Flags Homepage.Model Homepage.Msg Model Msg
, counter : Application.Page Flags Counter.Model Counter.Msg Model Msg
, random : Application.Page Flags Random.Model Random.Msg Model Msg
, notFound : Application.Page Flags NotFound.Model NotFound.Msg Model Msg
}
pages : Pages
pages =
{ homepage =
Homepage.page
{ toModel = HomepageModel
, toMsg = HomepageMsg
}
, counter =
Counter.page
{ toModel = CounterModel
, toMsg = CounterMsg
}
, random =
Random.page
{ toModel = RandomModel
, toMsg = RandomMsg
}
, notFound =
NotFound.page
{ toModel = NotFoundModel
, toMsg = NotFoundMsg
}
}
init : Route -> Application.Init Flags Model Msg
init route =
case route of
Homepage ->
Application.init pages.homepage
Counter ->
Application.init pages.counter
Random ->
Application.init pages.random
NotFound ->
Application.init pages.notFound
update : Msg -> Model -> Application.Update Model Msg
update appMsg appModel =
case ( appMsg, appModel ) of
( HomepageMsg msg, HomepageModel model ) ->
Application.update
{ page = pages.homepage
, model = model
, msg = msg
}
( HomepageMsg _, _ ) ->
Application.keep appModel
( CounterMsg msg, CounterModel model ) ->
Application.update
{ page = pages.counter
, model = model
, msg = msg
}
( CounterMsg _, _ ) ->
Application.keep appModel
( RandomMsg msg, RandomModel model ) ->
Application.update
{ page = pages.random
, model = model
, msg = msg
}
( RandomMsg _, _ ) ->
Application.keep appModel
( NotFoundMsg msg, NotFoundModel model ) ->
Application.update
{ page = pages.notFound
, model = model
, msg = msg
}
( NotFoundMsg _, _ ) ->
Application.keep appModel
bundle : Model -> Application.Bundle Model Msg
bundle appModel =
case appModel of
HomepageModel model ->
Application.bundle
{ page = pages.homepage
, model = model
}
CounterModel model ->
Application.bundle
{ page = pages.counter
, model = model
}
RandomModel model ->
Application.bundle
{ page = pages.random
, model = model
}
NotFoundModel model ->
Application.bundle
{ page = pages.notFound
, model = model
}

View File

@ -1,26 +0,0 @@
module Element.Pages.NotFound exposing (Model, Msg, page)
import Application.Element as Application
import Html exposing (..)
type alias Model =
()
type alias Msg =
Never
page =
Application.static
{ view = view
}
view : Html Msg
view =
div []
[ h1 [] [ text "Page not found..." ]
, p [] [ text "what a shame!" ]
]

113
examples/basic/src/Main.elm Normal file
View File

@ -0,0 +1,113 @@
module Main exposing (main)
import Application
import Html exposing (Html)
import Pages.Counter as Counter
import Pages.Homepage as Homepage
import Pages.NotFound as NotFound
main : Program () Model Msg
main =
Application.create
{ route = Counter
, pages =
{ init = init
, update = update
, bundle = bundle
}
}
-- CAN / SHOULD BE GENERATED
type Route
= Homepage
| Counter
| NotFound
type Model
= HomepageModel Homepage.Model
| CounterModel Counter.Model
| NotFoundModel NotFound.Model
type Msg
= HomepageMsg Homepage.Msg
| CounterMsg Counter.Msg
| NotFoundMsg NotFound.Msg
homepage : Application.Page Homepage.Model Homepage.Msg Model Msg
homepage =
Homepage.page
{ toModel = HomepageModel
, toMsg = HomepageMsg
}
counter : Application.Page Counter.Model Counter.Msg Model Msg
counter =
Counter.page
{ toModel = CounterModel
, toMsg = CounterMsg
}
notFound : Application.Page NotFound.Model NotFound.Msg Model Msg
notFound =
NotFound.page
{ toModel = NotFoundModel
, toMsg = NotFoundMsg
}
init : Route -> Model
init route =
case route of
Homepage ->
homepage.init
Counter ->
counter.init
NotFound ->
notFound.init
update : Msg -> Model -> Model
update appMsg appModel =
case ( appMsg, appModel ) of
( HomepageMsg msg, HomepageModel model ) ->
homepage.update msg model
( HomepageMsg _, _ ) ->
Application.keep appModel
( CounterMsg msg, CounterModel model ) ->
counter.update msg model
( CounterMsg _, _ ) ->
Application.keep appModel
( NotFoundMsg msg, NotFoundModel model ) ->
notFound.update msg model
( NotFoundMsg _, _ ) ->
Application.keep appModel
bundle : Model -> { view : Html Msg }
bundle appModel =
case appModel of
HomepageModel model ->
homepage.bundle model
CounterModel model ->
counter.bundle model
NotFoundModel model ->
notFound.bundle model

View File

@ -1,6 +1,6 @@
module Element.Pages.Counter exposing (Model, Msg, page)
module Pages.Counter exposing (Model, Msg, page)
import Application.Element as Application
import Application
import Html exposing (..)
import Html.Events as Events

View File

@ -1,6 +1,6 @@
module Element.Pages.Homepage exposing (Model, Msg, page)
module Pages.Homepage exposing (Model, Msg, page)
import Application.Element as Application
import Application
import Html exposing (..)

View File

@ -1,6 +1,6 @@
module Sandbox.Pages.NotFound exposing (Model, Msg, page)
module Pages.NotFound exposing (Model, Msg, page)
import Application.Sandbox as Application
import Application
import Html exposing (..)

View File

@ -1,6 +1,6 @@
module Element.Pages.Random exposing (Model, Msg, page)
module Pages.Random exposing (Model, Msg, page)
import Application.Element as Application
import Application as Application
import Html exposing (..)
import Html.Attributes as Attr
import Html.Events as Events

View File

@ -1,136 +0,0 @@
module Sandbox.Main exposing (main)
import Application.Sandbox as Application
import Sandbox.Pages.Counter as Counter
import Sandbox.Pages.Homepage as Homepage
import Sandbox.Pages.NotFound as NotFound
type Route
= Homepage
| Counter
| NotFound
main : Program () Model Msg
main =
Application.create
{ route = Counter
, pages =
{ init = init
, update = update
, bundle = bundle
}
}
type Model
= HomepageModel Homepage.Model
| CounterModel Counter.Model
| NotFoundModel NotFound.Model
type Msg
= HomepageMsg Homepage.Msg
| CounterMsg Counter.Msg
| NotFoundMsg NotFound.Msg
-- CAN / SHOULD BE GENERATED
type alias Pages =
{ homepage : Application.Page Homepage.Model Homepage.Msg Model Msg
, counter : Application.Page Counter.Model Counter.Msg Model Msg
, notFound : Application.Page NotFound.Model NotFound.Msg Model Msg
}
pages : Pages
pages =
{ homepage =
Homepage.page
{ toModel = HomepageModel
, toMsg = HomepageMsg
}
, counter =
Counter.page
{ toModel = CounterModel
, toMsg = CounterMsg
}
, notFound =
NotFound.page
{ toModel = NotFoundModel
, toMsg = NotFoundMsg
}
}
init : Route -> Application.Init Model
init route =
case route of
Homepage ->
Application.init pages.homepage
Counter ->
Application.init pages.counter
NotFound ->
Application.init pages.notFound
update : Msg -> Model -> Application.Update Model
update appMsg appModel =
case ( appMsg, appModel ) of
( HomepageMsg msg, HomepageModel model ) ->
Application.update
{ page = pages.homepage
, model = model
, msg = msg
}
( HomepageMsg _, _ ) ->
Application.keep appModel
( CounterMsg msg, CounterModel model ) ->
Application.update
{ page = pages.counter
, model = model
, msg = msg
}
( CounterMsg _, _ ) ->
Application.keep appModel
( NotFoundMsg msg, NotFoundModel model ) ->
Application.update
{ page = pages.notFound
, model = model
, msg = msg
}
( NotFoundMsg _, _ ) ->
Application.keep appModel
bundle : Model -> Application.Bundle Model Msg
bundle appModel =
case appModel of
HomepageModel model ->
Application.bundle
{ page = pages.homepage
, model = model
}
CounterModel model ->
Application.bundle
{ page = pages.counter
, model = model
}
NotFoundModel model ->
Application.bundle
{ page = pages.notFound
, model = model
}

View File

@ -1,50 +0,0 @@
module Sandbox.Pages.Counter exposing (Model, Msg, page)
import Application.Sandbox as Application
import Html exposing (..)
import Html.Events as Events
type alias Model =
{ counter : Int
}
type Msg
= Increment
| Decrement
page =
Application.sandbox
{ init = init
, update = update
, view = view
}
init : Model
init =
{ counter = 0 }
update : Msg -> Model -> Model
update msg model =
case msg of
Increment ->
{ model | counter = model.counter + 1 }
Decrement ->
{ model | counter = model.counter - 1 }
view : Model -> Html Msg
view model =
div []
[ h1 [] [ text "Counter" ]
, div []
[ button [ Events.onClick Decrement ] [ text "-" ]
, p [] [ text (String.fromInt model.counter) ]
, button [ Events.onClick Increment ] [ text "+" ]
]
]

View File

@ -1,26 +0,0 @@
module Sandbox.Pages.Homepage exposing (Model, Msg, page)
import Application.Sandbox as Application
import Html exposing (..)
type alias Model =
()
type alias Msg =
Never
page =
Application.static
{ view = view
}
view : Html Msg
view =
div []
[ h1 [] [ text "Homepage" ]
, p [] [ text "Very boring tho..." ]
]

View File

@ -1,306 +0,0 @@
module Vanilla.Application exposing (main)
import Browser
import Browser.Navigation as Nav
import Html exposing (..)
import Html.Attributes as Attr
import Url exposing (Url)
import Url.Parser as Parser
import Vanilla.Element as Random
import Vanilla.Sandbox as Counter
import Vanilla.Static as Homepage
type alias Model =
{ page : PageModel
, flags : Flags
, url : Url
, key : Nav.Key
}
type Msg
= OnUrlChanged Url
| OnUrlRequested Browser.UrlRequest
| OnPageMsg PageMsg
type Route
= Homepage
| Counter
| Random
| NotFound
type PageModel
= HomepageModel
| CounterModel Counter.Model
| RandomModel Random.Model
| NotFoundModel
type PageMsg
= HomepageMsg
| CounterMsg Counter.Msg
| RandomMsg Random.Msg
type alias Flags =
()
main : Program Flags Model Msg
main =
Browser.application
{ init = init
, update = update
, subscriptions = subscriptions
, view = view
, onUrlChange = OnUrlChanged
, onUrlRequest = OnUrlRequested
}
-- INIT
init : Flags -> Url -> Nav.Key -> ( Model, Cmd Msg )
init flags url key =
let
route : Route
route =
routeFromUrl url
page : { model : PageModel, cmd : Cmd PageMsg }
page =
initPage flags route
in
( { url = url
, flags = flags
, key = key
, page = page.model
}
, Cmd.map OnPageMsg page.cmd
)
routeFromUrl : Url -> Route
routeFromUrl url =
let
routes =
Parser.oneOf
[ Parser.map Homepage Parser.top
, Parser.map Counter (Parser.s "counter")
, Parser.map Random (Parser.s "random")
]
in
Parser.parse routes url |> Maybe.withDefault NotFound
routeToPath : Route -> String
routeToPath route =
case route of
Homepage ->
"/"
Counter ->
"/counter"
Random ->
"/random"
NotFound ->
"/not-found"
initPage : Flags -> Route -> { model : PageModel, cmd : Cmd PageMsg }
initPage flags route =
case route of
Homepage ->
{ model = HomepageModel
, cmd = Cmd.none
}
Counter ->
{ model = CounterModel Counter.init
, cmd = Cmd.none
}
Random ->
let
( model, cmd ) =
Random.init flags
in
{ model = RandomModel model
, cmd = Cmd.map RandomMsg cmd
}
NotFound ->
{ model = NotFoundModel
, cmd = Cmd.none
}
-- UPDATE
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
OnUrlChanged url ->
let
route : Route
route =
routeFromUrl url
page : { model : PageModel, cmd : Cmd PageMsg }
page =
initPage model.flags route
in
( { model
| url = url
, page = page.model
}
, Cmd.map OnPageMsg page.cmd
)
OnUrlRequested (Browser.Internal url) ->
( model
, Nav.pushUrl model.key (Url.toString url)
)
OnUrlRequested (Browser.External url) ->
( model
, Nav.load url
)
OnPageMsg pageMsg ->
let
page : { model : PageModel, cmd : Cmd PageMsg }
page =
updatePage ( model.page, pageMsg )
in
( { model | page = page.model }
, Cmd.map OnPageMsg page.cmd
)
updatePage : ( PageModel, PageMsg ) -> { model : PageModel, cmd : Cmd PageMsg }
updatePage ( pageModel, pageMsg ) =
case ( pageModel, pageMsg ) of
( HomepageModel, _ ) ->
{ model = pageModel
, cmd = Cmd.none
}
( CounterModel model, CounterMsg msg ) ->
{ model = CounterModel (Counter.update msg model)
, cmd = Cmd.none
}
( CounterModel _, _ ) ->
{ model = pageModel
, cmd = Cmd.none
}
( RandomModel model, RandomMsg msg ) ->
let
( updatedModel, updatedCmd ) =
Random.update msg model
in
{ model = RandomModel updatedModel
, cmd = Cmd.map RandomMsg updatedCmd
}
( RandomModel _, _ ) ->
{ model = pageModel
, cmd = Cmd.none
}
( NotFoundModel, _ ) ->
{ model = pageModel
, cmd = Cmd.none
}
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions { page } =
Sub.map OnPageMsg <|
case page of
HomepageModel ->
Sub.none
CounterModel _ ->
Sub.none
RandomModel model ->
Sub.map RandomMsg (Random.subscriptions model)
NotFoundModel ->
Sub.none
view : Model -> Browser.Document Msg
view model =
let
links : List ( String, Route )
links =
[ ( "Homepage", Homepage )
, ( "Counter", Counter )
, ( "Random", Random )
]
{ title, body } =
viewPage model.page
in
{ title = title
, body =
[ div []
[ header [] (List.map viewLink links)
, div [ Attr.class "page" ]
(List.map (Html.map OnPageMsg) body)
]
]
}
viewPage : PageModel -> Browser.Document PageMsg
viewPage pageModel =
case pageModel of
HomepageModel ->
{ title = "Homepage"
, body = [ Html.map never Homepage.view ]
}
CounterModel model ->
{ title = "Counter"
, body = [ Html.map CounterMsg (Counter.view model) ]
}
RandomModel model ->
{ title = "Random"
, body = [ Html.map RandomMsg (Random.view model) ]
}
NotFoundModel ->
{ title = "Not Found"
, body =
[ h1 [] [ text "Page not found" ]
, p [] [ text "Using elm-reactor? Just click a link above!" ]
]
}
viewLink : ( String, Route ) -> Html msg
viewLink ( label, route ) =
a
[ Attr.href (routeToPath route)
, Attr.style "margin-right" "1rem"
]
[ text label ]

View File

@ -1,93 +0,0 @@
module Vanilla.Element exposing
( Model
, Msg
, init
, main
, subscriptions
, update
, view
)
import Browser
import Html exposing (..)
import Html.Attributes as Attr
import Html.Events as Events
import Http
import Json.Decode as Json exposing (Decoder)
type alias Model =
{ url : Maybe String
}
type Msg
= FetchCat
| CatResponded (Result Http.Error String)
main : Program () Model Msg
main =
Browser.element
{ init = init
, update = update
, view = view
, subscriptions = subscriptions
}
init : () -> ( Model, Cmd Msg )
init _ =
( { url = Nothing }
, Cmd.none
)
decoder : Decoder String
decoder =
Json.field "file" Json.string
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
FetchCat ->
( model
, Http.get
{ url = "https://aws.random.cat/meow"
, expect = Http.expectJson CatResponded decoder
}
)
CatResponded (Ok url) ->
( { model | url = Just url }
, Cmd.none
)
CatResponded (Err _) ->
( { model | url = Nothing }
, Cmd.none
)
view : Model -> Html Msg
view model =
div []
[ h1 [] [ text "Cat mode" ]
, div []
[ button [ Events.onClick FetchCat ] [ text "gimme a cat" ]
, case model.url of
Just url ->
p []
[ img [ Attr.style "width" "200px", Attr.src url ] []
]
Nothing ->
text ""
]
]
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none

View File

@ -1,59 +0,0 @@
module Vanilla.Sandbox exposing
( Model
, Msg
, init
, main
, update
, view
)
import Browser
import Html exposing (..)
import Html.Events as Events
main : Program () Model Msg
main =
Browser.sandbox
{ init = init
, view = view
, update = update
}
type alias Model =
{ counter : Int
}
init : Model
init =
{ counter = 0
}
type Msg
= Increment
| Decrement
update : Msg -> Model -> Model
update msg model =
case msg of
Increment ->
{ model | counter = model.counter + 1 }
Decrement ->
{ model | counter = model.counter - 1 }
view : Model -> Html Msg
view model =
div []
[ h1 [] [ text "Counter" ]
, div []
[ button [ Events.onClick Increment ] [ text "+" ]
, p [] [ text (String.fromInt model.counter) ]
, button [ Events.onClick Decrement ] [ text "-" ]
]
]

View File

@ -1,16 +0,0 @@
module Vanilla.Static exposing (main, view)
import Html exposing (..)
main : Html msg
main =
view
view : Html msg
view =
div []
[ h1 [] [ text "Homepage" ]
, p [] [ text "How exciting!" ]
]

View File

@ -1,13 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app"></div>
<script src="./main.js"></script>
</body>
</html>

View File

@ -1,3 +0,0 @@
import { Elm } from './Application.elm'
Elm.Vanilla.Application.init({ node: document.getElementById('app') })