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.
|
||||
|
||||
# Viewing
|
||||
|
||||
Open index.html in your browser.
|
||||
|
||||
# TODO
|
||||
|
||||
- [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
|
||||
- [ ] Handle back-navigation
|
||||
- [ ] 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.Events
|
||||
import Element.Border
|
||||
|
||||
type alias Model = {}
|
||||
type Msg
|
||||
= ClickedProducts
|
||||
| ClickedResources
|
||||
| ClickedAbout
|
||||
| ClickedContact
|
||||
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 =
|
||||
let
|
||||
|
|
98
src/Main.elm
98
src/Main.elm
|
@ -1,35 +1,35 @@
|
|||
module Main exposing (main)
|
||||
|
||||
-- external imports
|
||||
import Browser
|
||||
import Url
|
||||
import Html exposing (Html)
|
||||
import Element exposing (Element, el, text, column)
|
||||
import String exposing (right)
|
||||
import Browser.Navigation
|
||||
|
||||
import Page.Landing
|
||||
import Header
|
||||
import Browser exposing (UrlRequest)
|
||||
import Html exposing (header)
|
||||
|
||||
-- internal imports
|
||||
import Body
|
||||
import Header
|
||||
|
||||
-- MODEL
|
||||
type Page
|
||||
= Landing Page.Landing.Model
|
||||
| Products
|
||||
| Resources
|
||||
| About
|
||||
| Contact
|
||||
type Msg
|
||||
= Header Header.Msg
|
||||
| Body Body.Msg
|
||||
| UrlChanged Url.Url
|
||||
| UrlRequest Browser.UrlRequest
|
||||
|
||||
type alias Model =
|
||||
{ key : Browser.Navigation.Key
|
||||
, url : Url.Url
|
||||
, page : Page
|
||||
, page : Body.Model
|
||||
, header : Header.Model}
|
||||
|
||||
init : () -> Url.Url -> Browser.Navigation.Key -> ( Model, Cmd Msg )
|
||||
init flags url key =
|
||||
let
|
||||
page = Landing (Page.Landing.init flags)
|
||||
page = Body.init flags
|
||||
header = Header.init flags
|
||||
model =
|
||||
{ key = key
|
||||
|
@ -40,85 +40,49 @@ init flags url key =
|
|||
in
|
||||
(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 =
|
||||
case msg of
|
||||
Header headerMsg ->
|
||||
Body bodyMsg ->
|
||||
let
|
||||
newUrl = toUrl model.url headerMsg
|
||||
newModel = { model | page = toPage headerMsg }
|
||||
(newPage, cmd) = Body.update bodyMsg model.page
|
||||
in
|
||||
(newModel, Browser.Navigation.pushUrl model.key (Url.toString newUrl))
|
||||
UrlChanged url ->
|
||||
(model, Browser.Navigation.pushUrl model.key (Url.toString url))
|
||||
( {model | page = newPage}, cmd |> Cmd.map Body )
|
||||
UrlChanged url ->
|
||||
( {model | url = url}, Cmd.none )
|
||||
UrlRequest (Browser.Internal url) ->
|
||||
( model, Browser.Navigation.pushUrl model.key (Url.toString url) )
|
||||
_ -> (model, Cmd.none)
|
||||
|
||||
subscriptions : Model -> Sub Msg
|
||||
subscriptions _ =
|
||||
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 =
|
||||
let
|
||||
header = Header.view model.header |> Element.map Header
|
||||
body = Body.view model.page |> Element.map Body
|
||||
page =
|
||||
Element.column
|
||||
[ Element.width Element.fill
|
||||
, Element.height Element.fill
|
||||
, Element.centerX]
|
||||
[ Header.view model.header |> Element.map Header
|
||||
, viewBody model]
|
||||
[ header
|
||||
, body]
|
||||
in
|
||||
{ title = "Example Spa Elm App"
|
||||
, body = [ Element.layout [] page ]}
|
||||
|
||||
-- MAIN
|
||||
|
||||
main =
|
||||
Browser.application {
|
||||
init = init
|
||||
,view = view
|
||||
,update = update
|
||||
,subscriptions = subscriptions
|
||||
,onUrlChange = UrlChanged
|
||||
,onUrlRequest = UrlRequest
|
||||
init = init
|
||||
,view = view
|
||||
,update = update
|
||||
,subscriptions = subscriptions
|
||||
-- when a link is clicked, first UrlRequest is issued
|
||||
,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)
|
||||
|
||||
type alias Model = {}
|
||||
|
@ -7,6 +7,9 @@ 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 []
|
||||
|
|
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