I think we've now hit what one might consider to be a good baseline

This commit is contained in:
Yehowshua Immanuel 2024-12-30 18:04:52 -05:00
parent 36d22a6f1c
commit 38bfd3bf18
9 changed files with 173 additions and 78 deletions

View file

@ -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
View 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

View file

@ -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

View file

@ -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,85 +40,49 @@ 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, Browser.Navigation.pushUrl model.key (Url.toString url)) ( {model | url = url}, Cmd.none )
UrlRequest (Browser.Internal url) ->
( model, Browser.Navigation.pushUrl model.key (Url.toString url) )
_ -> (model, Cmd.none) _ -> (model, Cmd.none)
subscriptions : Model -> Sub Msg 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
View 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
View 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"

View file

@ -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
View 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
View 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"