From fdd9a223dc29f91581a81920821cd8e966faf179 Mon Sep 17 00:00:00 2001 From: Dillon Kearns Date: Wed, 1 Feb 2023 12:07:04 -0800 Subject: [PATCH] Update starter scaffolding. --- generator/template/app/Api.elm | 7 +- generator/template/app/Effect.elm | 123 +++++++++++++++++++++++++ generator/template/app/ErrorPage.elm | 43 +++++++-- generator/template/app/Route/Index.elm | 21 +++-- generator/template/app/Shared.elm | 69 +++++--------- generator/template/app/Site.elm | 14 ++- generator/template/elm-tooling.json | 3 - generator/template/elm.json | 59 +++++++----- generator/template/package.json | 14 ++- 9 files changed, 256 insertions(+), 97 deletions(-) create mode 100644 generator/template/app/Effect.elm diff --git a/generator/template/app/Api.elm b/generator/template/app/Api.elm index e27040ea..75bc7da1 100644 --- a/generator/template/app/Api.elm +++ b/generator/template/app/Api.elm @@ -1,16 +1,17 @@ module Api exposing (routes) -import ApiRoute exposing (ApiRoute) +import ApiRoute import BackendTask exposing (BackendTask) +import FatalError exposing (FatalError) import Html exposing (Html) import Pages.Manifest as Manifest import Route exposing (Route) routes : - BackendTask (List Route) + BackendTask FatalError (List Route) -> (Maybe { indent : Int, newLines : Bool } -> Html Never -> String) - -> List (ApiRoute ApiRoute.Response) + -> List (ApiRoute.ApiRoute ApiRoute.Response) routes getStaticRoutes htmlToString = [] diff --git a/generator/template/app/Effect.elm b/generator/template/app/Effect.elm new file mode 100644 index 00000000..ee89c0a1 --- /dev/null +++ b/generator/template/app/Effect.elm @@ -0,0 +1,123 @@ +module Effect exposing (Effect(..), batch, fromCmd, map, none, perform) + +import Browser.Navigation +import Form.FormData exposing (FormData) +import Http +import Json.Decode as Decode +import Pages.Fetcher +import Url exposing (Url) + + +type Effect msg + = None + | Cmd (Cmd msg) + | Batch (List (Effect msg)) + | SetField { formId : String, name : String, value : String } + | FetchRouteData + { data : Maybe FormData + , toMsg : Result Http.Error Url -> msg + } + | Submit + { values : FormData + , toMsg : Result Http.Error Url -> msg + } + | SubmitFetcher (Pages.Fetcher.Fetcher msg) + + +type alias RequestInfo = + { contentType : String + , body : String + } + + +none : Effect msg +none = + None + + +batch : List (Effect msg) -> Effect msg +batch = + Batch + + +fromCmd : Cmd msg -> Effect msg +fromCmd = + Cmd + + +map : (a -> b) -> Effect a -> Effect b +map fn effect = + case effect of + None -> + None + + Cmd cmd -> + Cmd (Cmd.map fn cmd) + + Batch list -> + Batch (List.map (map fn) list) + + FetchRouteData fetchInfo -> + FetchRouteData + { data = fetchInfo.data + , toMsg = fetchInfo.toMsg >> fn + } + + Submit fetchInfo -> + Submit + { values = fetchInfo.values + , toMsg = fetchInfo.toMsg >> fn + } + + SetField info -> + SetField info + + SubmitFetcher fetcher -> + fetcher + |> Pages.Fetcher.map fn + |> SubmitFetcher + + +perform : + { fetchRouteData : + { data : Maybe FormData + , toMsg : Result Http.Error Url -> pageMsg + } + -> Cmd msg + , submit : + { values : FormData + , toMsg : Result Http.Error Url -> pageMsg + } + -> Cmd msg + , runFetcher : + Pages.Fetcher.Fetcher pageMsg + -> Cmd msg + , fromPageMsg : pageMsg -> msg + , key : Browser.Navigation.Key + , setField : { formId : String, name : String, value : String } -> Cmd msg + } + -> Effect pageMsg + -> Cmd msg +perform ({ fromPageMsg, key } as helpers) effect = + case effect of + None -> + Cmd.none + + Cmd cmd -> + Cmd.map fromPageMsg cmd + + SetField info -> + helpers.setField info + + Batch list -> + Cmd.batch (List.map (perform helpers) list) + + FetchRouteData fetchInfo -> + helpers.fetchRouteData + fetchInfo + + Submit record -> + helpers.submit record + + SubmitFetcher record -> + helpers.runFetcher record diff --git a/generator/template/app/ErrorPage.elm b/generator/template/app/ErrorPage.elm index 33fd455c..38ad1681 100644 --- a/generator/template/app/ErrorPage.elm +++ b/generator/template/app/ErrorPage.elm @@ -1,6 +1,36 @@ -module ErrorPage exposing (ErrorPage(..), internalError, notFound, statusCode, view) +module ErrorPage exposing (ErrorPage(..), Model, Msg, head, init, internalError, notFound, statusCode, update, view) +import Effect exposing (Effect) +import Head import Html exposing (Html) +import View exposing (View) + + +type Msg + = NoOp + + +type alias Model = + {} + + +init : ErrorPage -> ( Model, Effect Msg ) +init errorPage = + ( {} + , Effect.none + ) + + +update : ErrorPage -> Msg -> Model -> ( Model, Effect Msg ) +update errorPage msg model = + case msg of + NoOp -> + ( {}, Effect.none ) + + +head : ErrorPage -> List Head.Tag +head errorPage = + [] type ErrorPage @@ -18,13 +48,14 @@ internalError = InternalError -view : ErrorPage -> { body : Html msg, title : String } -view error = +view : ErrorPage -> Model -> View Msg +view error model = { body = - Html.div [] - [ Html.text "Hi! This is a NotFound error" + [ Html.div [] + [ Html.p [] [ Html.text "Page not found. Maybe try another URL?" ] ] - , title = "Error" + ] + , title = "Page Not Found" } diff --git a/generator/template/app/Route/Index.elm b/generator/template/app/Route/Index.elm index 567b2d0d..04e09f3c 100644 --- a/generator/template/app/Route/Index.elm +++ b/generator/template/app/Route/Index.elm @@ -1,14 +1,17 @@ -module Route.Index exposing (Data, Model, Msg, route) +module Route.Index exposing (ActionData, Data, Model, Msg, route) import BackendTask exposing (BackendTask) +import FatalError exposing (FatalError) import Head import Head.Seo as Seo import Html -import Html.Attributes as Attr +import Html.Styled.Attributes as Attr +import Pages.Msg import Pages.PageUrl exposing (PageUrl) import Pages.Url import Path -import RouteBuilder exposing (StatelessRoute, StaticPayload) +import Route +import RouteBuilder exposing (StatefulRoute, StatelessRoute, StaticPayload) import Shared import View exposing (View) @@ -25,7 +28,7 @@ type alias RouteParams = {} -type alias Data = +type alias ActionData = {} @@ -38,9 +41,13 @@ route = |> RouteBuilder.buildNoState { view = view } -data : BackendTask Data +type alias Data = + () + + +data : BackendTask FatalError Data data = - BackendTask.succeed Data + BackendTask.succeed () head : @@ -67,7 +74,7 @@ view : Maybe PageUrl -> Shared.Model -> StaticPayload Data ActionData RouteParams - -> View Msg + -> View (Pages.Msg.Msg Msg) view maybeUrl sharedModel static = { title = "elm-pages is running" , body = diff --git a/generator/template/app/Shared.elm b/generator/template/app/Shared.elm index f494bcfb..7af1052e 100644 --- a/generator/template/app/Shared.elm +++ b/generator/template/app/Shared.elm @@ -1,9 +1,9 @@ module Shared exposing (Data, Model, Msg(..), SharedMsg(..), template) -import Browser.Navigation -import BackendTask +import BackendTask exposing (BackendTask) +import Effect exposing (Effect) +import FatalError exposing (FatalError) import Html exposing (Html) -import Html.Events import Pages.Flags import Pages.PageUrl exposing (PageUrl) import Path exposing (Path) @@ -19,13 +19,16 @@ template = , view = view , data = data , subscriptions = subscriptions - , onPageChange = Nothing + , onPageChange = Just OnPageChange } type Msg - = SharedMsg SharedMsg - | MenuClicked + = OnPageChange + { path : Path + , query : Maybe String + , fragment : Maybe String + } type alias Data = @@ -37,13 +40,12 @@ type SharedMsg type alias Model = - { showMenu : Bool + { showMobileMenu : Bool } init : - Maybe Browser.Navigation.Key - -> Pages.Flags.Flags + Pages.Flags.Flags -> Maybe { path : @@ -54,21 +56,18 @@ init : , metadata : route , pageUrl : Maybe PageUrl } - -> ( Model, Cmd Msg ) -init navigationKey flags maybePagePath = - ( { showMenu = False } - , Cmd.none + -> ( Model, Effect Msg ) +init flags maybePagePath = + ( { showMobileMenu = False } + , Effect.none ) -update : Msg -> Model -> ( Model, Cmd Msg ) +update : Msg -> Model -> ( Model, Effect Msg ) update msg model = case msg of - SharedMsg globalMsg -> - ( model, Cmd.none ) - - MenuClicked -> - ( { model | showMenu = not model.showMenu }, Cmd.none ) + OnPageChange _ -> + ( { model | showMobileMenu = False }, Effect.none ) subscriptions : Path -> Model -> Sub Msg @@ -76,7 +75,7 @@ subscriptions _ _ = Sub.none -data : BackendTask.BackendTask Data +data : BackendTask FatalError Data data = BackendTask.succeed () @@ -90,32 +89,10 @@ view : -> Model -> (Msg -> msg) -> View msg - -> { body : Html msg, title : String } -view sharedData page model toMsg pageView = + -> { body : List (Html msg), title : String } +view stars page model toMsg pageView = { body = - Html.div [] - [ Html.nav [] - [ Html.button - [ Html.Events.onClick MenuClicked ] - [ Html.text - (if model.showMenu then - "Close Menu" - - else - "Open Menu" - ) - ] - , if model.showMenu then - Html.ul [] - [ Html.li [] [ Html.text "Menu item 1" ] - , Html.li [] [ Html.text "Menu item 2" ] - ] - - else - Html.text "" - ] - |> Html.map toMsg - , Html.main_ [] pageView.body - ] + [ Html.div [] pageView.body + ] , title = pageView.title } diff --git a/generator/template/app/Site.elm b/generator/template/app/Site.elm index d303664d..f7fb734d 100644 --- a/generator/template/app/Site.elm +++ b/generator/template/app/Site.elm @@ -1,18 +1,21 @@ -module Site exposing (config) +module Site exposing (canonicalUrl, config) import BackendTask exposing (BackendTask) +import FatalError exposing (FatalError) import Head +import MimeType +import Pages.Url import SiteConfig exposing (SiteConfig) config : SiteConfig config = - { canonicalUrl = "https://elm-pages.com" + { canonicalUrl = canonicalUrl , head = head } -head : BackendTask (List Head.Tag) +head : BackendTask FatalError (List Head.Tag) head = [ Head.metaName "viewport" (Head.raw "width=device-width,initial-scale=1") , Head.metaName "mobile-web-app-capable" (Head.raw "yes") @@ -22,3 +25,8 @@ head = , Head.sitemapLink "/sitemap.xml" ] |> BackendTask.succeed + + +canonicalUrl : String +canonicalUrl = + "https://elm-pages.com" diff --git a/generator/template/elm-tooling.json b/generator/template/elm-tooling.json index f26d0b8e..e97de009 100644 --- a/generator/template/elm-tooling.json +++ b/generator/template/elm-tooling.json @@ -1,7 +1,4 @@ { - "entrypoints": [ - "./src/Main.elm" - ], "tools": { "elm": "0.19.1", "elm-format": "0.8.5" diff --git a/generator/template/elm.json b/generator/template/elm.json index 9c0a5e26..c77d8139 100644 --- a/generator/template/elm.json +++ b/generator/template/elm.json @@ -8,49 +8,58 @@ "elm-version": "0.19.1", "dependencies": { "direct": { - "dillonkearns/elm-pages": "9.0.0", - "elm/browser": "1.0.2", - "elm/core": "1.0.5", - "elm/html": "1.0.0", - "elm/json": "1.1.3", - "elm/url": "1.0.0" - }, - "indirect": { - "MartinSStewart/elm-serialize": "1.2.6", "avh4/elm-color": "1.0.0", - "bburdette/toop": "1.2.0", "danfishgold/base64-bytes": "1.1.0", "danyx23/elm-mimetype": "4.0.1", "dillonkearns/elm-bcp47-language-tag": "1.0.1", + "dillonkearns/elm-markdown": "7.0.1", + "dillonkearns/elm-pages-v3-beta": "12.0.0", + "elm/browser": "1.0.2", "elm/bytes": "1.0.8", - "elm/file": "1.0.5", + "elm/core": "1.0.5", + "elm/html": "1.0.0", "elm/http": "2.0.0", + "elm/json": "1.1.3", "elm/parser": "1.1.0", - "elm/project-metadata-utils": "1.0.2", - "elm/random": "1.0.0", "elm/regex": "1.0.0", "elm/time": "1.0.0", - "elm/virtual-dom": "1.0.2", + "elm/url": "1.0.0", + "elm/virtual-dom": "1.0.3", "elm-community/dict-extra": "2.4.0", - "elm-community/list-extra": "8.5.1", - "elm-explorations/test": "1.2.2", - "fredcy/elm-parseint": "2.0.1", - "jfmengels/elm-review": "2.6.1", - "mgold/elm-nonempty-list": "4.2.0", + "elm-community/list-extra": "8.7.0", + "elm-community/result-extra": "2.4.0", + "jluckyiv/elm-utc-date-strings": "1.0.0", + "justinmimbs/date": "4.0.1", + "lamdera/codecs": "1.0.0", + "mdgriffith/elm-codegen": "2.0.0", "miniBill/elm-codec": "2.0.0", - "miniBill/elm-unicode": "1.0.2", "noahzgordon/elm-color-extra": "1.0.2", + "robinheghan/fnv1a": "1.0.0", + "rtfeldman/elm-css": "18.0.0", + "the-sett/elm-syntax-dsl": "6.0.2", + "turboMaCk/non-empty-list-alias": "1.3.1", + "vito/elm-ansi": "10.0.1" + }, + "indirect": { + "Chadtech/elm-bool-extra": "2.4.2", + "dillonkearns/elm-cli-options-parser": "3.2.0", + "dillonkearns/elm-date-or-date-time": "2.0.0", + "elm/file": "1.0.5", + "elm/random": "1.0.0", + "elm-community/basics-extra": "4.1.0", + "elm-community/maybe-extra": "5.3.0", + "fredcy/elm-parseint": "2.0.1", + "miniBill/elm-unicode": "1.0.3", "robinheghan/murmur3": "1.0.0", "rtfeldman/elm-hex": "1.0.0", - "stil4m/elm-syntax": "7.2.8", + "rtfeldman/elm-iso8601-date-strings": "1.1.4", + "stil4m/elm-syntax": "7.2.9", "stil4m/structured-writer": "1.0.3", - "tripokey/elm-fuzzy": "5.2.1", - "vito/elm-ansi": "10.0.1", - "zwilias/json-decode-exploration": "6.0.0" + "the-sett/elm-pretty-printer": "3.0.0" } }, "test-dependencies": { "direct": {}, "indirect": {} } -} \ No newline at end of file +} diff --git a/generator/template/package.json b/generator/template/package.json index 6fd260e7..5436ca03 100644 --- a/generator/template/package.json +++ b/generator/template/package.json @@ -1,14 +1,20 @@ { "name": "elm-pages-app", + "type": "module", "scripts": { "postinstall": "elm-tooling install", "start": "elm-pages dev", "build": "elm-pages build" }, "devDependencies": { - "elm-optimize-level-2": "0.3.4", - "elm-pages": "2.1.10", - "elm-review": "^2.7.0", - "elm-tooling": "^1.7.0" + "elm-codegen": "^0.2.0", + "elm-optimize-level-2": "^0.3.5", + "elm-pages": "^3.0.0-beta.20", + "elm-review": "2.8.5", + "elm-tooling": "^1.10.0", + "vite": "^3.1.8" + }, + "dependencies": { + "@netlify/functions": "^1.2.0" } }