begin work on nested layouts

This commit is contained in:
Ryan Haskell-Glatz 2019-10-20 14:11:53 -05:00
parent b36bc7cf6e
commit 371765e9ac
15 changed files with 415 additions and 85 deletions

View File

@ -1,6 +1,7 @@
module Generated.Pages exposing (Model, Msg, bundle, init, update)
import Application
import Generated.Pages.Settings as Settings
import Generated.Route as Route exposing (Route)
import Html exposing (Html)
import Pages.Counter as Counter
@ -16,6 +17,7 @@ type Model
| CounterModel Counter.Model
| RandomModel Random.Model
| NotFoundModel NotFound.Model
| SettingsModel Settings.Model
| Users_SlugModel Users_Slug.Model
| Users_Slug_Posts_SlugModel Users_Slug_Posts_Slug.Model
@ -24,6 +26,7 @@ type Msg
= HomepageMsg Homepage.Msg
| CounterMsg Counter.Msg
| RandomMsg Random.Msg
| SettingsMsg Settings.Msg
| NotFoundMsg NotFound.Msg
| Users_SlugMsg Users_Slug.Msg
| Users_Slug_Posts_SlugMsg Users_Slug_Posts_Slug.Msg
@ -53,6 +56,14 @@ random =
}
settings : Application.Recipe Settings.Params Settings.Model Settings.Msg Model Msg
settings =
Settings.page
{ toModel = SettingsModel
, toMsg = SettingsMsg
}
notFound : Application.Recipe NotFound.Params NotFound.Model NotFound.Msg Model Msg
notFound =
NotFound.page
@ -89,6 +100,9 @@ init route =
Route.Random params ->
random.init params
Route.Settings params ->
settings.init params
Route.NotFound params ->
notFound.init params
@ -120,6 +134,12 @@ update appMsg appModel =
( RandomMsg _, _ ) ->
Application.keep appModel
( SettingsMsg msg, SettingsModel model ) ->
settings.update msg model
( SettingsMsg _, _ ) ->
Application.keep appModel
( NotFoundMsg msg, NotFoundModel model ) ->
notFound.update msg model
@ -151,6 +171,9 @@ bundle appModel =
RandomModel model ->
random.bundle model
SettingsModel model ->
settings.bundle model
NotFoundModel model ->
notFound.bundle model

View File

@ -0,0 +1,121 @@
module Generated.Pages.Settings exposing (Model, Msg, Params, page)
import Application
import Generated.Route.Settings as Route exposing (Route)
import Html exposing (..)
import Layouts.Settings
import Pages.Settings.Account as Account
import Pages.Settings.Notifications as Notifications
import Pages.Settings.User as User
-- TODO : Export Application.layout or something for scaling this trash
type Model
= AccountModel Account.Model
| NotificationsModel Notifications.Model
| UserModel User.Model
type Msg
= AccountMsg Account.Msg
| NotificationsMsg Notifications.Msg
| UserMsg User.Msg
type alias Params =
Route
page : Application.Page Params Model Msg model msg
page =
Application.glue glue
glue : Application.Glue Route Model Msg
glue =
{ layout = Layouts.Settings.layout
, pages = pages
}
pages : Application.Pages Route Model Msg
pages =
{ init = init
, update = update
, bundle = bundle
}
account : Application.Recipe Account.Params Account.Model Account.Msg Model Msg
account =
Account.page
{ toModel = AccountModel
, toMsg = AccountMsg
}
notifications : Application.Recipe Notifications.Params Notifications.Model Notifications.Msg Model Msg
notifications =
Notifications.page
{ toModel = NotificationsModel
, toMsg = NotificationsMsg
}
user : Application.Recipe User.Params User.Model User.Msg Model Msg
user =
User.page
{ toModel = UserModel
, toMsg = UserMsg
}
init : Route -> ( Model, Cmd Msg )
init route =
case route of
Route.Account params ->
account.init params
Route.Notifications params ->
notifications.init params
Route.User params ->
user.init params
update : Msg -> Model -> ( Model, Cmd Msg )
update appMsg appModel =
case ( appMsg, appModel ) of
( AccountMsg msg, AccountModel model ) ->
account.update msg model
( AccountMsg _, _ ) ->
Application.keep appModel
( NotificationsMsg msg, NotificationsModel model ) ->
notifications.update msg model
( NotificationsMsg _, _ ) ->
Application.keep appModel
( UserMsg msg, UserModel model ) ->
user.update msg model
( UserMsg _, _ ) ->
Application.keep appModel
bundle : Model -> { view : Html Msg, subscriptions : Sub Msg }
bundle appModel =
case appModel of
AccountModel model ->
account.bundle model
NotificationsModel model ->
notifications.bundle model
UserModel model ->
user.bundle model

View File

@ -1,5 +1,6 @@
module Generated.Route exposing (Route(..), fromUrl, toPath)
import Generated.Route.Settings as Settings
import Url exposing (Url)
import Url.Parser as Parser exposing ((</>), Parser)
@ -8,6 +9,7 @@ type Route
= Homepage ()
| Counter ()
| Random ()
| Settings Settings.Route
| Users_Slug String
| Users_Slug_Posts_Slug UserPostInfo
| NotFound ()
@ -21,19 +23,20 @@ type alias UserPostInfo =
fromUrl : Url -> Route
fromUrl =
Parser.parse
(Parser.oneOf routes)
>> Maybe.withDefault (NotFound ())
Parser.parse parser >> Maybe.withDefault (NotFound ())
routes : List (Parser (Route -> Route) Route)
routes =
parser : Parser (Route -> a) a
parser =
Parser.oneOf
[ Parser.top
|> Parser.map (Homepage ())
, Parser.s "counter"
|> Parser.map (Counter ())
, Parser.s "random"
|> Parser.map (Random ())
, Parser.s "settings"
|> (</>) (Parser.map Settings Settings.parser)
, (Parser.s "users" </> Parser.string)
|> Parser.map Users_Slug
, (Parser.s "users" </> Parser.string </> Parser.s "posts" </> Parser.int)
@ -54,6 +57,9 @@ toPath route =
Random _ ->
"/random"
Settings r ->
"/settings" ++ Settings.toPath r
NotFound _ ->
"/not-found"

View File

@ -0,0 +1,38 @@
module Generated.Route.Settings exposing
( Route(..)
, parser
, toPath
)
import Url.Parser as Parser exposing ((</>), Parser)
type Route
= Account ()
| Notifications ()
| User ()
toPath : Route -> String
toPath route =
case route of
Account _ ->
"/account"
Notifications _ ->
"/notifications"
User _ ->
"/user"
parser : Parser (Route -> a) a
parser =
Parser.oneOf
[ Parser.s "account"
|> Parser.map (Account ())
, Parser.s "notifications"
|> Parser.map (Notifications ())
, Parser.s "user"
|> Parser.map (User ())
]

View File

@ -1,10 +1,17 @@
module Layout exposing (view)
module Layouts.Main exposing (layout)
import Application
import Components.Navbar
import Html exposing (..)
import Html.Attributes as Attr
layout : Application.Layout msg
layout =
{ view = view
}
view : { page : Html msg } -> Html msg
view { page } =
div

View File

@ -0,0 +1,18 @@
module Layouts.Settings exposing (layout)
import Application
import Html exposing (..)
layout : Application.Layout msg
layout =
{ view = view
}
view : { page : Html msg } -> Html msg
view { page } =
div []
[ h1 [] [ text "Settings" ]
, page
]

View File

@ -3,7 +3,7 @@ module Main exposing (main)
import Application exposing (Application)
import Generated.Pages as Pages
import Generated.Route as Route
import Layout as Layout
import Layouts.Main
main : Application () Pages.Model Pages.Msg
@ -14,9 +14,7 @@ main =
, toPath = Route.toPath
, transition = Application.fade 200
}
, layout =
{ view = Layout.view
}
, layout = Layouts.Main.layout
, pages =
{ init = Pages.init
, update = Pages.update

View File

@ -1,27 +0,0 @@
module Pages.Settings exposing (Model, Msg)
import Pages.Settings.Account as Account
import Pages.Settings.Notifications as Notifications
import Pages.Settings.User as User
-- TODO : Export Application.layout or something for scaling this trash
type Route
= Account
| Notifications
| User
type Model
= AccountModel Account.Model
| NotificationsModel Notifications.Model
| UserModel User.Model
type Msg
= AccountMsg Account.Msg
| NotificationsMsg Notifications.Msg
| UserMsg User.Msg

View File

@ -1,9 +1,33 @@
module Pages.Settings.Account exposing (Model, Msg)
module Pages.Settings.Account exposing
( Model
, Msg
, Params
, page
)
import Application
import Html exposing (..)
type Model
= Model
type alias Model =
()
type Msg
= Msg
type alias Msg =
Never
type alias Params =
()
page : Application.Page Params Model Msg model msg
page =
Application.static
{ view = view
}
view : Html Msg
view =
h3 [] [ text "Account" ]

View File

@ -1,9 +1,33 @@
module Pages.Settings.Notifications exposing (Model, Msg)
module Pages.Settings.Notifications exposing
( Model
, Msg
, Params
, page
)
import Application
import Html exposing (..)
type Model
= Model
type alias Model =
()
type Msg
= Msg
type alias Msg =
Never
type alias Params =
()
page : Application.Page Params Model Msg model msg
page =
Application.static
{ view = view
}
view : Html Msg
view =
h3 [] [ text "Notifications" ]

View File

@ -1,9 +1,33 @@
module Pages.Settings.User exposing (Model, Msg)
module Pages.Settings.User exposing
( Model
, Msg
, Params
, page
)
import Application
import Html exposing (..)
type Model
= Model
type alias Model =
()
type Msg
= Msg
type alias Msg =
Never
type alias Params =
()
page : Application.Page Params Model Msg model msg
page =
Application.static
{ view = view
}
view : Html Msg
view =
h3 [] [ text "User" ]

View File

@ -49,4 +49,6 @@ subscriptions model =
view : Model -> Html Msg
view model =
h1 [] [ text ("Post " ++ String.fromInt model.post ++ " for user: " ++ model.user) ]
h1 []
[ text ("Post " ++ String.fromInt model.post ++ " for user: " ++ model.user)
]

View File

@ -1,18 +1,30 @@
module Application exposing
( Application, create
, Layout
, Page, Recipe
, Bundle, keep
, Static, static
, Sandbox, sandbox
, Element, element
, Transition, fade
, none
, Glue, Pages, glue
, Transition, fade, none
)
{-|
## Applications
@docs Application, create
## Layouts
@docs Layout
## Pages
@docs Page, Recipe
@docs Bundle, keep
@ -23,11 +35,12 @@ module Application exposing
@docs Element, element
@docs PageWithParams, RecipeWithParams
@docs Glue, Pages, glue
@docs ElementWithParams, elementWithParams
@docs Transition, fade
## Transitions
@docs Transition, fade, none
-}
@ -35,6 +48,7 @@ import Browser
import Browser.Dom as Dom
import Browser.Navigation as Nav
import Html exposing (Html)
import Internals.Layout as Layout
import Internals.Page as Page
import Internals.Transition as Transition
import Internals.Transitionable as Transitionable exposing (Transitionable)
@ -93,7 +107,7 @@ create config =
, view =
view
{ view = config.pages.bundle >> .view
, layout = config.layout.view
, layout = config.layout
, transition = transition.strategy
}
, onUrlChange = Url
@ -252,7 +266,7 @@ subscriptions config model =
view :
{ view : model -> Html msg
, transition : Transition.Strategy (Html msg)
, layout : { page : Html msg } -> Html msg
, layout : Layout msg
}
-> Model flags model
-> Browser.Document (Msg msg)
@ -263,19 +277,19 @@ view config model =
case model.page of
Transitionable.Ready page ->
config.transition.beforeLoad
{ layout = config.layout
{ layout = config.layout.view
, page = config.view page
}
Transitionable.Transitioning page ->
config.transition.leavingPage
{ layout = config.layout
{ layout = config.layout.view
, page = config.view page
}
Transitionable.Complete page ->
config.transition.enteringPage
{ layout = config.layout
{ layout = config.layout.view
, page = config.view page
}
]
@ -286,6 +300,10 @@ view config model =
-- PAGE API
type alias Layout msg =
Layout.Layout msg
type alias Page params pageModel pageMsg model msg =
Page.Page params pageModel pageMsg model msg
@ -314,28 +332,43 @@ static =
Page.static
type alias Sandbox pageModel pageMsg params =
Page.Sandbox pageModel pageMsg params
type alias Sandbox params pageModel pageMsg =
Page.Sandbox params pageModel pageMsg
sandbox :
Sandbox pageModel pageMsg params
Sandbox params pageModel pageMsg
-> Page params pageModel pageMsg model msg
sandbox =
Page.sandbox
type alias Element pageModel pageMsg params =
Page.Element pageModel pageMsg params
type alias Element params pageModel pageMsg =
Page.Element params pageModel pageMsg
element :
Element pageModel pageMsg params
Element params pageModel pageMsg
-> Page params pageModel pageMsg model msg
element =
Page.element
type alias Glue route layoutModel layoutMsg =
Page.Glue route layoutModel layoutMsg
type alias Pages route layoutModel layoutMsg =
Page.Pages route layoutModel layoutMsg
glue :
Glue route layoutModel layoutMsg
-> Page params layoutModel layoutMsg model msg
glue =
Page.glue
-- TRANSITIONS

8
src/Internals/Layout.elm Normal file
View File

@ -0,0 +1,8 @@
module Internals.Layout exposing (Layout)
import Html exposing (Html)
type alias Layout msg =
{ view : { page : Html msg } -> Html msg
}

View File

@ -4,6 +4,7 @@ module Internals.Page exposing
, Static, static
, Sandbox, sandbox
, Element, element
, Glue, Pages, glue
)
{-|
@ -18,9 +19,12 @@ module Internals.Page exposing
@docs Element, element
@docs Glue, Pages, glue
-}
import Html exposing (Html)
import Internals.Layout exposing (Layout)
type alias Page params pageModel pageMsg model msg =
@ -70,7 +74,7 @@ static page { toModel, toMsg } =
-- SANDBOX
type alias Sandbox pageModel pageMsg params =
type alias Sandbox params pageModel pageMsg =
{ init : params -> pageModel
, update : pageMsg -> pageModel -> pageModel
, view : pageModel -> Html pageMsg
@ -78,7 +82,7 @@ type alias Sandbox pageModel pageMsg params =
sandbox :
Sandbox pageModel pageMsg params
Sandbox params pageModel pageMsg
-> Page params pageModel pageMsg model msg
sandbox page { toModel, toMsg } =
{ init = \params -> ( toModel (page.init params), Cmd.none )
@ -99,7 +103,7 @@ sandbox page { toModel, toMsg } =
-- ELEMENT
type alias Element pageModel pageMsg params =
type alias Element params pageModel pageMsg =
{ init : params -> ( pageModel, Cmd pageMsg )
, update : pageMsg -> pageModel -> ( pageModel, Cmd pageMsg )
, view : pageModel -> Html pageMsg
@ -108,7 +112,7 @@ type alias Element pageModel pageMsg params =
element :
Element pageModel pageMsg params
Element params pageModel pageMsg
-> Page params pageModel pageMsg model msg
element page { toModel, toMsg } =
{ init =
@ -123,3 +127,30 @@ element page { toModel, toMsg } =
, subscriptions = Sub.none
}
}
-- LAYOUT
type alias Glue route model msg =
{ layout : Layout msg
, pages : Pages route model msg
}
type alias Pages route model msg =
{ init : route -> ( model, Cmd msg )
, update : msg -> model -> ( model, Cmd msg )
, bundle : model -> Bundle msg
}
glue :
Glue route layoutModel layoutMsg
-> Page params layoutModel layoutMsg model msg
glue options { toModel, toMsg } =
{ init = Debug.todo "glue.init"
, update = Debug.todo "glue.update"
, bundle = Debug.todo "glue.bundle"
}