diff --git a/examples/trails/app/Route/Search.elm b/examples/trails/app/Route/Search.elm index 3d76ba69..8db404b5 100644 --- a/examples/trails/app/Route/Search.elm +++ b/examples/trails/app/Route/Search.elm @@ -178,7 +178,18 @@ view maybeUrl sharedModel model static = [ Html.text "Query " , Html.input [ Attr.name "q" ] [] ] - , Html.input [ Attr.type_ "submit", Attr.value "Search" ] [] + , case static.transition of + Just _ -> + Html.button + [ Attr.disabled True + ] + [ Html.text "Searching..." + ] + + Nothing -> + Html.button [] + [ Html.text "Search" + ] ] , static.data.results |> Maybe.map resultsView diff --git a/generator/src/RouteBuilder.elm b/generator/src/RouteBuilder.elm index 18c65782..16265b63 100644 --- a/generator/src/RouteBuilder.elm +++ b/generator/src/RouteBuilder.elm @@ -97,6 +97,7 @@ import Pages.Internal.NotFoundReason exposing (NotFoundReason) import Pages.Internal.RoutePattern exposing (RoutePattern) import Pages.Msg import Pages.PageUrl exposing (PageUrl) +import Pages.Transition import Path exposing (Path) import Server.Request import Server.Response @@ -142,6 +143,7 @@ type alias StaticPayload data action routeParams = , submit : { fields : List ( String, String ), headers : List ( String, String ) } -> Pages.Fetcher.Fetcher (Result Http.Error action) + , transition : Maybe Pages.Transition.Transition } diff --git a/generator/src/generate-template-module-connector.js b/generator/src/generate-template-module-connector.js index 871629ed..7acdde34 100644 --- a/generator/src/generate-template-module-connector.js +++ b/generator/src/generate-template-module-connector.js @@ -71,6 +71,7 @@ import Site import Head import Html exposing (Html) import Pages.Internal.NotFoundReason +import Pages.Transition import Pages.PageUrl exposing (PageUrl) import Path exposing (Path) import Pages.Internal.RoutePattern @@ -158,7 +159,8 @@ type ActionData view : - { path : Path + Maybe Pages.Transition.Transition + -> { path : Path , route : Maybe Route } -> Maybe PageUrl @@ -169,7 +171,7 @@ view : { view : Model -> { title : String, body : Html (Pages.Msg.Msg Msg) } , head : List Head.Tag } -view page maybePageUrl globalData pageData actionData = +view transition page maybePageUrl globalData pageData actionData = case ( page.route, pageData ) of ( _, DataErrorPage____ data ) -> { view = @@ -229,6 +231,7 @@ view page maybePageUrl globalData pageData actionData = , submit = Pages.Fetcher.submit Route.${moduleName( name )}.w3_decode_ActionData + , transition = transition } |> View.map (Pages.Msg.map Msg${pathNormalizedName( name @@ -249,6 +252,7 @@ view page maybePageUrl globalData pageData actionData = , submit = Pages.Fetcher.submit Route.${moduleName( name )}.w3_decode_ActionData + , transition = Nothing -- TODO is this safe? } ` } @@ -328,6 +332,7 @@ init currentGlobalModel userFlags sharedData pageData actionData navigationKey m , submit = Pages.Fetcher.submit Route.${moduleName( name )}.w3_decode_ActionData + , transition = Nothing -- TODO is this safe, will this always be Nothing? } |> Tuple.mapBoth Model${pathNormalizedName( name @@ -358,8 +363,8 @@ init currentGlobalModel userFlags sharedData pageData actionData navigationKey m -update : Shared.Data -> PageData -> Maybe Browser.Navigation.Key -> Msg -> Model -> ( Model, Effect Msg ) -update sharedData pageData navigationKey msg model = +update : Maybe Pages.Transition.Transition -> Shared.Data -> PageData -> Maybe Browser.Navigation.Key -> Msg -> Model -> ( Model, Effect Msg ) +update transition sharedData pageData navigationKey msg model = case msg of MsgErrorPage____ msg_ -> let @@ -469,6 +474,7 @@ update sharedData pageData navigationKey msg model = , submit = Pages.Fetcher.submit Route.${moduleName( name )}.w3_decode_ActionData + , transition = transition } msg_ pageModel diff --git a/src/Pages/Internal/Platform.elm b/src/Pages/Internal/Platform.elm index 992014c7..19bf880c 100644 --- a/src/Pages/Internal/Platform.elm +++ b/src/Pages/Internal/Platform.elm @@ -33,19 +33,16 @@ import Pages.Internal.String as String import Pages.Msg import Pages.ProgramConfig exposing (ProgramConfig) import Pages.StaticHttpRequest as StaticHttpRequest +import Pages.Transition import Path exposing (Path) import QueryParams import Task import Url exposing (Url) -type Payload - = Payload - - type Transition = Loading Int Path - | Submitting Path Payload + | Submitting FormDecoder.FormData {-| -} @@ -76,7 +73,7 @@ mainView config model = currentUrl = model.url in - (config.view + (config.view (model.transition |> Maybe.map Tuple.second) { path = ContentCache.pathForUrl urls |> Path.join , route = config.urlToRoute { currentUrl | path = model.currentPath } } @@ -324,7 +321,7 @@ type alias Model userModel pageData actionData sharedData = } , notFound : Maybe { reason : NotFoundReason, path : Path } , userFlags : Decode.Value - , transition : Maybe Transition + , transition : Maybe ( Int, Pages.Transition.Transition ) , nextTransitionKey : Int , inFlightFetchers : Dict Int FormDecoder.FormData } @@ -415,7 +412,16 @@ update config appMsg model = |> performUserMsg userMsg config Pages.Msg.Submit fields -> - ( model, Submit fields ) + ( { model + | transition = + Just + ( -- TODO remove hardcoded number + -1 + , Pages.Transition.Submitting fields + ) + } + , Submit fields + ) UpdateCacheAndUrlNew fromLinkClick urlWithoutRedirectResolution maybeUserMsg updateResult -> case @@ -459,7 +465,7 @@ update config appMsg model = -- TODO if urlWithoutRedirectResolution is different from the url with redirect resolution, then -- instead of calling update, call pushUrl (I think?) -- TODO include user Cmd - config.update + config.update (model.transition |> Maybe.map Tuple.second) newSharedData newPageData model.key @@ -480,6 +486,7 @@ update config appMsg model = { model | url = newUrl , pageData = Ok updatedPageData + , transition = Nothing } onActionMsg : Maybe userMsg @@ -600,7 +607,7 @@ performUserMsg userMsg config ( model, effect ) = Ok pageData -> let ( userModel, userCmd ) = - config.update pageData.sharedData pageData.pageData model.key userMsg pageData.userModel + config.update (model.transition |> Maybe.map Tuple.second) pageData.sharedData pageData.pageData model.key userMsg pageData.userModel updatedPageData : Result error { userModel : userModel, pageData : pageData, actionData : Maybe actionData, sharedData : sharedData } updatedPageData = @@ -830,7 +837,7 @@ withUserMsg config userMsg ( model, effect ) = Ok pageData -> let ( userModel, userCmd ) = - config.update pageData.sharedData pageData.pageData model.key userMsg pageData.userModel + config.update (model.transition |> Maybe.map Tuple.second) pageData.sharedData pageData.pageData model.key userMsg pageData.userModel updatedPageData : Result error { userModel : userModel, pageData : pageData, actionData : Maybe actionData, sharedData : sharedData } updatedPageData = @@ -983,7 +990,7 @@ startNewGetLoad pathToGet toMsg ( model, effect ) = cancelIfStale : Effect userMsg pageData actionData sharedData userEffect errorPage cancelIfStale = case model.transition of - Just (Loading transitionKey path) -> + Just ( transitionKey, Pages.Transition.Loading path loadingKind ) -> CancelRequest transitionKey _ -> @@ -992,9 +999,11 @@ startNewGetLoad pathToGet toMsg ( model, effect ) = ( { model | nextTransitionKey = model.nextTransitionKey + 1 , transition = - pathToGet - |> Path.fromString - |> Loading model.nextTransitionKey + ( model.nextTransitionKey + , Pages.Transition.Loading + (pathToGet |> Path.fromString) + Pages.Transition.Load + ) |> Just } , Batch diff --git a/src/Pages/Internal/Platform/Cli.elm b/src/Pages/Internal/Platform/Cli.elm index 1328deba..2c81946b 100644 --- a/src/Pages/Internal/Platform/Cli.elm +++ b/src/Pages/Internal/Platform/Cli.elm @@ -841,10 +841,10 @@ sendSinglePageProgress site contentJson config model info = viewValue : { title : String, body : Html (Pages.Msg.Msg userMsg) } viewValue = - (config.view currentPage Nothing sharedData pageData maybeActionData |> .view) pageModel + (config.view Nothing currentPage Nothing sharedData pageData maybeActionData |> .view) pageModel in PageServerResponse.RenderPage responseInfo - { head = config.view currentPage Nothing sharedData pageData maybeActionData |> .head + { head = config.view Nothing currentPage Nothing sharedData pageData maybeActionData |> .head , view = viewValue.body |> HtmlPrinter.htmlToString , title = viewValue.title } @@ -884,13 +884,13 @@ sendSinglePageProgress site contentJson config model info = viewValue : { title : String, body : Html (Pages.Msg.Msg userMsg) } viewValue = - (config.view currentPage Nothing sharedData pageData Nothing |> .view) pageModel + (config.view Nothing currentPage Nothing sharedData pageData Nothing |> .view) pageModel in PageServerResponse.RenderPage { statusCode = config.errorStatusCode error , headers = record.headers } - { head = config.view currentPage Nothing sharedData pageData Nothing |> .head + { head = config.view Nothing currentPage Nothing sharedData pageData Nothing |> .head , view = viewValue.body |> HtmlPrinter.htmlToString , title = viewValue.title } @@ -1154,7 +1154,8 @@ render404Page config sharedData model path notFoundReason = viewValue : { title : String, body : Html (Pages.Msg.Msg userMsg) } viewValue = - (config.view pathAndRoute + (config.view Nothing + pathAndRoute Nothing justSharedData pageData @@ -1167,7 +1168,7 @@ render404Page config sharedData model path notFoundReason = , contentJson = Dict.empty , html = viewValue.body |> HtmlPrinter.htmlToString , errors = [] - , head = config.view pathAndRoute Nothing justSharedData pageData Nothing |> .head + , head = config.view Nothing pathAndRoute Nothing justSharedData pageData Nothing |> .head , title = viewValue.title , staticHttpCache = Dict.empty , is404 = True diff --git a/src/Pages/ProgramConfig.elm b/src/Pages/ProgramConfig.elm index 37e3651d..5e8fe7db 100644 --- a/src/Pages/ProgramConfig.elm +++ b/src/Pages/ProgramConfig.elm @@ -22,6 +22,7 @@ import Pages.Internal.RoutePattern exposing (RoutePattern) import Pages.Msg import Pages.PageUrl exposing (PageUrl) import Pages.SiteConfig exposing (SiteConfig) +import Pages.Transition import Path exposing (Path) import Url exposing (Url) @@ -44,16 +45,18 @@ type alias ProgramConfig userMsg userModel route pageData actionData sharedData , pageUrl : Maybe PageUrl } -> ( userModel, effect ) - , update : sharedData -> pageData -> Maybe Browser.Navigation.Key -> userMsg -> userModel -> ( userModel, effect ) + , update : Maybe Pages.Transition.Transition -> sharedData -> pageData -> Maybe Browser.Navigation.Key -> userMsg -> userModel -> ( userModel, effect ) , subscriptions : route -> Path -> userModel -> Sub userMsg , sharedData : DataSource sharedData , data : route -> DataSource (PageServerResponse pageData errorPage) , action : route -> DataSource (PageServerResponse actionData errorPage) , onActionData : actionData -> Maybe userMsg , view : - { path : Path - , route : route - } + Maybe Pages.Transition.Transition + -> + { path : Path + , route : route + } -> Maybe PageUrl -> sharedData -> pageData diff --git a/src/Pages/Transition.elm b/src/Pages/Transition.elm index a13cf73f..12e76dd0 100644 --- a/src/Pages/Transition.elm +++ b/src/Pages/Transition.elm @@ -1,12 +1,22 @@ -module Pages.Transition exposing (..) +module Pages.Transition exposing (Transition(..), LoadingState(..)) + +{-| + +@docs Transition, LoadingState + +-} + +import FormDecoder +import Path exposing (Path) +{-| -} type Transition - = Idle - | Submitting - | Loading + = Submitting FormDecoder.FormData + | Loading Path LoadingState +{-| -} type LoadingState = Redirecting | Load