I think we've now hit what one might consider to be a good baseline
This commit is contained in:
parent
36d22a6f1c
commit
38bfd3bf18
|
@ -15,13 +15,12 @@ make serve
|
||||||
|
|
||||||
Now open `http://localhost:8000` in your browser.
|
Now open `http://localhost:8000` in your browser.
|
||||||
|
|
||||||
# Viewing
|
|
||||||
|
|
||||||
Open index.html in your browser.
|
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
- [x] Add Makefile
|
- [x] Add Makefile
|
||||||
|
- [ ] Determine if `src/Body.elm` or pages in `sr/Page` should have subscription functions
|
||||||
|
- [ ] use actix backend that maps most root requests to serve `actix_file::Files`
|
||||||
|
- [ ] Submit to slack for feedback...
|
||||||
- [ ] Refactor into router page
|
- [ ] Refactor into router page
|
||||||
- [ ] Handle back-navigation
|
- [ ] Handle back-navigation
|
||||||
- [ ] Add `default.nix`
|
- [ ] Add `default.nix`
|
||||||
|
|
66
src/Body.elm
Normal file
66
src/Body.elm
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
module Body exposing (Msg(..), Model(..), init, update, view)
|
||||||
|
|
||||||
|
import Element
|
||||||
|
|
||||||
|
import Page.About
|
||||||
|
import Page.Contact
|
||||||
|
import Page.Landing
|
||||||
|
import Page.Products
|
||||||
|
import Page.Resources
|
||||||
|
|
||||||
|
type Msg
|
||||||
|
= MsgLanding Page.Landing.Msg
|
||||||
|
| MsgProducts Page.Products.Msg
|
||||||
|
| MsgResources Page.Resources.Msg
|
||||||
|
| MsgAbout Page.About.Msg
|
||||||
|
| MsgContact Page.Contact.Msg
|
||||||
|
|
||||||
|
type Model
|
||||||
|
= ModelLanding Page.Landing.Model
|
||||||
|
| ModelProducts Page.Products.Model
|
||||||
|
| ModelResources Page.Resources.Model
|
||||||
|
| ModelAbout Page.About.Model
|
||||||
|
| ModelContact Page.Contact.Model
|
||||||
|
|
||||||
|
init : () -> Model
|
||||||
|
init flags = ModelLanding (Page.Landing.init flags)
|
||||||
|
|
||||||
|
update : Msg -> Model -> (Model, Cmd Msg)
|
||||||
|
update bodyMsg bodyModel =
|
||||||
|
let
|
||||||
|
updatePage msg model updateFn wrapMsg toBodyModel =
|
||||||
|
let
|
||||||
|
(newModel, cmd) = updateFn msg model
|
||||||
|
in
|
||||||
|
(toBodyModel newModel, Cmd.map wrapMsg cmd)
|
||||||
|
in
|
||||||
|
case (bodyMsg, bodyModel) of
|
||||||
|
(MsgLanding msg, ModelLanding m) ->
|
||||||
|
updatePage msg m Page.Landing.update MsgLanding ModelLanding
|
||||||
|
|
||||||
|
(MsgProducts msg, ModelProducts m) ->
|
||||||
|
updatePage msg m Page.Products.update MsgProducts ModelProducts
|
||||||
|
|
||||||
|
(MsgResources msg, ModelResources m) ->
|
||||||
|
updatePage msg m Page.Resources.update MsgResources ModelResources
|
||||||
|
|
||||||
|
(MsgAbout msg, ModelAbout m) ->
|
||||||
|
updatePage msg m Page.About.update MsgAbout ModelAbout
|
||||||
|
|
||||||
|
(MsgContact msg, ModelContact m) ->
|
||||||
|
updatePage msg m Page.Contact.update MsgContact ModelContact
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
(bodyModel, Cmd.none)
|
||||||
|
|
||||||
|
view : Model -> Element.Element Msg
|
||||||
|
view model =
|
||||||
|
let
|
||||||
|
content = case model of
|
||||||
|
ModelLanding m -> Page.Landing.view m |> Element.map MsgLanding
|
||||||
|
ModelProducts m -> Page.Products.view m |> Element.map MsgProducts
|
||||||
|
ModelResources m -> Page.Resources.view m |> Element.map MsgResources
|
||||||
|
ModelAbout m -> Page.About.view m |> Element.map MsgAbout
|
||||||
|
ModelContact m -> Page.Contact.view m |> Element.map MsgContact
|
||||||
|
in
|
||||||
|
Element.el [Element.centerY ,Element.centerX] content
|
|
@ -1,18 +1,17 @@
|
||||||
module Header exposing (Model, Msg(..), view, init)
|
module Header exposing (Model, Msg, view, init, update)
|
||||||
import Element exposing (Element)
|
import Element exposing (Element)
|
||||||
import Element.Events
|
import Element.Events
|
||||||
import Element.Border
|
import Element.Border
|
||||||
|
|
||||||
type alias Model = {}
|
type alias Model = {}
|
||||||
type Msg
|
type alias Msg = {}
|
||||||
= ClickedProducts
|
|
||||||
| ClickedResources
|
|
||||||
| ClickedAbout
|
|
||||||
| ClickedContact
|
|
||||||
|
|
||||||
init : () -> Model
|
init : () -> Model
|
||||||
init flags = {}
|
init flags = {}
|
||||||
|
|
||||||
|
update : Msg -> Model -> (Model, Cmd Msg)
|
||||||
|
update msg model = (model, Cmd.none)
|
||||||
|
|
||||||
view : Model -> Element Msg
|
view : Model -> Element Msg
|
||||||
view model =
|
view model =
|
||||||
let
|
let
|
||||||
|
|
84
src/Main.elm
84
src/Main.elm
|
@ -1,35 +1,35 @@
|
||||||
module Main exposing (main)
|
module Main exposing (main)
|
||||||
|
|
||||||
|
-- external imports
|
||||||
import Browser
|
import Browser
|
||||||
import Url
|
import Url
|
||||||
import Html exposing (Html)
|
import Html exposing (Html)
|
||||||
import Element exposing (Element, el, text, column)
|
import Element exposing (Element, el, text, column)
|
||||||
import String exposing (right)
|
import String exposing (right)
|
||||||
import Browser.Navigation
|
import Browser.Navigation
|
||||||
|
import Browser exposing (UrlRequest)
|
||||||
import Page.Landing
|
|
||||||
import Header
|
|
||||||
import Html exposing (header)
|
import Html exposing (header)
|
||||||
|
|
||||||
|
-- internal imports
|
||||||
|
import Body
|
||||||
|
import Header
|
||||||
|
|
||||||
-- MODEL
|
type Msg
|
||||||
type Page
|
= Header Header.Msg
|
||||||
= Landing Page.Landing.Model
|
| Body Body.Msg
|
||||||
| Products
|
| UrlChanged Url.Url
|
||||||
| Resources
|
| UrlRequest Browser.UrlRequest
|
||||||
| About
|
|
||||||
| Contact
|
|
||||||
|
|
||||||
type alias Model =
|
type alias Model =
|
||||||
{ key : Browser.Navigation.Key
|
{ key : Browser.Navigation.Key
|
||||||
, url : Url.Url
|
, url : Url.Url
|
||||||
, page : Page
|
, page : Body.Model
|
||||||
, header : Header.Model}
|
, header : Header.Model}
|
||||||
|
|
||||||
init : () -> Url.Url -> Browser.Navigation.Key -> ( Model, Cmd Msg )
|
init : () -> Url.Url -> Browser.Navigation.Key -> ( Model, Cmd Msg )
|
||||||
init flags url key =
|
init flags url key =
|
||||||
let
|
let
|
||||||
page = Landing (Page.Landing.init flags)
|
page = Body.init flags
|
||||||
header = Header.init flags
|
header = Header.init flags
|
||||||
model =
|
model =
|
||||||
{ key = key
|
{ key = key
|
||||||
|
@ -40,42 +40,17 @@ init flags url key =
|
||||||
in
|
in
|
||||||
(model, Cmd.none)
|
(model, Cmd.none)
|
||||||
|
|
||||||
toPage : Header.Msg -> Page
|
|
||||||
toPage msg =
|
|
||||||
case msg of
|
|
||||||
Header.ClickedProducts -> Products
|
|
||||||
Header.ClickedResources -> Resources
|
|
||||||
Header.ClickedAbout -> About
|
|
||||||
Header.ClickedContact -> Contact
|
|
||||||
|
|
||||||
-- TODO : move this function to Router.elm
|
|
||||||
toUrl : Url.Url -> Header.Msg -> Url.Url
|
|
||||||
toUrl baseUrl msg =
|
|
||||||
case msg of
|
|
||||||
Header.ClickedProducts -> {baseUrl | path = "/products"}
|
|
||||||
Header.ClickedResources -> {baseUrl | path = "/resources"}
|
|
||||||
Header.ClickedAbout -> {baseUrl | path = "/about"}
|
|
||||||
Header.ClickedContact -> {baseUrl | path = "/contact"}
|
|
||||||
|
|
||||||
-- UPDATE
|
|
||||||
type Msg
|
|
||||||
= NoOp
|
|
||||||
| Header Header.Msg
|
|
||||||
| LandingPage Page.Landing.Msg
|
|
||||||
| UrlChanged Url.Url
|
|
||||||
| UrlRequest Browser.UrlRequest
|
|
||||||
|
|
||||||
|
|
||||||
update : Msg -> Model -> (Model, Cmd Msg)
|
update : Msg -> Model -> (Model, Cmd Msg)
|
||||||
update msg model =
|
update msg model =
|
||||||
case msg of
|
case msg of
|
||||||
Header headerMsg ->
|
Body bodyMsg ->
|
||||||
let
|
let
|
||||||
newUrl = toUrl model.url headerMsg
|
(newPage, cmd) = Body.update bodyMsg model.page
|
||||||
newModel = { model | page = toPage headerMsg }
|
|
||||||
in
|
in
|
||||||
(newModel, Browser.Navigation.pushUrl model.key (Url.toString newUrl))
|
( {model | page = newPage}, cmd |> Cmd.map Body )
|
||||||
UrlChanged url ->
|
UrlChanged url ->
|
||||||
|
( {model | url = url}, Cmd.none )
|
||||||
|
UrlRequest (Browser.Internal url) ->
|
||||||
( model, Browser.Navigation.pushUrl model.key (Url.toString url) )
|
( model, Browser.Navigation.pushUrl model.key (Url.toString url) )
|
||||||
_ -> (model, Cmd.none)
|
_ -> (model, Cmd.none)
|
||||||
|
|
||||||
|
@ -83,42 +58,31 @@ subscriptions : Model -> Sub Msg
|
||||||
subscriptions _ =
|
subscriptions _ =
|
||||||
Sub.none
|
Sub.none
|
||||||
|
|
||||||
viewBody : Model -> Element.Element Msg
|
|
||||||
viewBody model =
|
|
||||||
let
|
|
||||||
content = case model.page of
|
|
||||||
Landing m -> Page.Landing.view m |> Element.map LandingPage
|
|
||||||
Products -> Element.text "Products"
|
|
||||||
Resources -> Element.text "Resources"
|
|
||||||
About -> Element.text "About"
|
|
||||||
Contact -> Element.text "Contact"
|
|
||||||
in
|
|
||||||
Element.el [Element.centerY ,Element.centerX] content
|
|
||||||
|
|
||||||
-- VIEW
|
|
||||||
|
|
||||||
view : Model -> Browser.Document Msg
|
view : Model -> Browser.Document Msg
|
||||||
view model =
|
view model =
|
||||||
let
|
let
|
||||||
|
header = Header.view model.header |> Element.map Header
|
||||||
|
body = Body.view model.page |> Element.map Body
|
||||||
page =
|
page =
|
||||||
Element.column
|
Element.column
|
||||||
[ Element.width Element.fill
|
[ Element.width Element.fill
|
||||||
, Element.height Element.fill
|
, Element.height Element.fill
|
||||||
, Element.centerX]
|
, Element.centerX]
|
||||||
[ Header.view model.header |> Element.map Header
|
[ header
|
||||||
, viewBody model]
|
, body]
|
||||||
in
|
in
|
||||||
{ title = "Example Spa Elm App"
|
{ title = "Example Spa Elm App"
|
||||||
, body = [ Element.layout [] page ]}
|
, body = [ Element.layout [] page ]}
|
||||||
|
|
||||||
-- MAIN
|
|
||||||
|
|
||||||
main =
|
main =
|
||||||
Browser.application {
|
Browser.application {
|
||||||
init = init
|
init = init
|
||||||
,view = view
|
,view = view
|
||||||
,update = update
|
,update = update
|
||||||
,subscriptions = subscriptions
|
,subscriptions = subscriptions
|
||||||
,onUrlChange = UrlChanged
|
-- when a link is clicked, first UrlRequest is issued
|
||||||
,onUrlRequest = UrlRequest
|
,onUrlRequest = UrlRequest
|
||||||
|
-- then UrlChanged is issued
|
||||||
|
,onUrlChange = UrlChanged
|
||||||
}
|
}
|
||||||
|
|
16
src/Page/About.elm
Normal file
16
src/Page/About.elm
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
module Page.About exposing (Model, Msg, view, init, update)
|
||||||
|
import Element exposing (Element)
|
||||||
|
|
||||||
|
type alias Model = {}
|
||||||
|
type alias Msg = {}
|
||||||
|
|
||||||
|
init : () -> Model
|
||||||
|
init flags = {}
|
||||||
|
|
||||||
|
update : Msg -> Model -> (Model, Cmd Msg)
|
||||||
|
update msg model = (model, Cmd.none)
|
||||||
|
|
||||||
|
view : Model -> Element Msg
|
||||||
|
view model =
|
||||||
|
Element.el []
|
||||||
|
<| Element.text "About"
|
16
src/Page/Contact.elm
Normal file
16
src/Page/Contact.elm
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
module Page.Contact exposing (Model, Msg, view, init, update)
|
||||||
|
import Element exposing (Element)
|
||||||
|
|
||||||
|
type alias Model = {}
|
||||||
|
type alias Msg = {}
|
||||||
|
|
||||||
|
init : () -> Model
|
||||||
|
init flags = {}
|
||||||
|
|
||||||
|
update : Msg -> Model -> (Model, Cmd Msg)
|
||||||
|
update msg model = (model, Cmd.none)
|
||||||
|
|
||||||
|
view : Model -> Element Msg
|
||||||
|
view model =
|
||||||
|
Element.el []
|
||||||
|
<| Element.text "Contact"
|
|
@ -1,4 +1,4 @@
|
||||||
module Page.Landing exposing (Model, Msg, view, init)
|
module Page.Landing exposing (Model, Msg, view, init, update)
|
||||||
import Element exposing (Element)
|
import Element exposing (Element)
|
||||||
|
|
||||||
type alias Model = {}
|
type alias Model = {}
|
||||||
|
@ -7,6 +7,9 @@ type alias Msg = {}
|
||||||
init : () -> Model
|
init : () -> Model
|
||||||
init flags = {}
|
init flags = {}
|
||||||
|
|
||||||
|
update : Msg -> Model -> (Model, Cmd Msg)
|
||||||
|
update msg model = (model, Cmd.none)
|
||||||
|
|
||||||
view : Model -> Element Msg
|
view : Model -> Element Msg
|
||||||
view model =
|
view model =
|
||||||
Element.el []
|
Element.el []
|
||||||
|
|
16
src/Page/Products.elm
Normal file
16
src/Page/Products.elm
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
module Page.Products exposing (Model, Msg, view, init, update)
|
||||||
|
import Element exposing (Element)
|
||||||
|
|
||||||
|
type alias Model = {}
|
||||||
|
type alias Msg = {}
|
||||||
|
|
||||||
|
init : () -> Model
|
||||||
|
init flags = {}
|
||||||
|
|
||||||
|
update : Msg -> Model -> (Model, Cmd Msg)
|
||||||
|
update msg model = (model, Cmd.none)
|
||||||
|
|
||||||
|
view : Model -> Element Msg
|
||||||
|
view model =
|
||||||
|
Element.el []
|
||||||
|
<| Element.text "Products"
|
16
src/Page/Resources.elm
Normal file
16
src/Page/Resources.elm
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
module Page.Resources exposing (Model, Msg, view, init, update)
|
||||||
|
import Element exposing (Element)
|
||||||
|
|
||||||
|
type alias Model = {}
|
||||||
|
type alias Msg = {}
|
||||||
|
|
||||||
|
init : () -> Model
|
||||||
|
init flags = {}
|
||||||
|
|
||||||
|
update : Msg -> Model -> (Model, Cmd Msg)
|
||||||
|
update msg model = (model, Cmd.none)
|
||||||
|
|
||||||
|
view : Model -> Element Msg
|
||||||
|
view model =
|
||||||
|
Element.el []
|
||||||
|
<| Element.text "Resources"
|
Loading…
Reference in a new issue