elm-pages 3.0.0-beta.9 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/adapter/netlify.js +207 -0
- package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2731 -2939
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmo +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -1
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1527 -422
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +16840 -13653
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
- package/generator/dead-code-review/elm.json +9 -7
- package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +59 -10
- package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +52 -36
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
- package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
- package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1527 -422
- package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +25118 -21832
- package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
- package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
- package/generator/review/elm.json +10 -10
- package/generator/src/RouteBuilder.elm +93 -128
- package/generator/src/SharedTemplate.elm +8 -7
- package/generator/src/SiteConfig.elm +3 -2
- package/generator/src/basepath-middleware.js +3 -3
- package/generator/src/build.js +143 -59
- package/generator/src/cli.js +292 -88
- package/generator/src/codegen.js +29 -27
- package/generator/src/compatibility-key.js +3 -0
- package/generator/src/compile-elm.js +43 -26
- package/generator/src/config.js +2 -4
- package/generator/src/copy-dir.js +2 -2
- package/generator/src/dev-server.js +160 -102
- package/generator/src/dir-helpers.js +9 -26
- package/generator/src/elm-codegen.js +5 -4
- package/generator/src/elm-file-constants.js +2 -3
- package/generator/src/error-formatter.js +12 -11
- package/generator/src/file-helpers.js +3 -4
- package/generator/src/generate-template-module-connector.js +23 -23
- package/generator/src/init.js +9 -8
- package/generator/src/pre-render-html.js +10 -13
- package/generator/src/render-test.js +109 -0
- package/generator/src/render-worker.js +25 -28
- package/generator/src/render.js +320 -143
- package/generator/src/request-cache.js +265 -162
- package/generator/src/resolve-elm-module.js +64 -0
- package/generator/src/rewrite-client-elm-json.js +6 -5
- package/generator/src/rewrite-elm-json-help.js +56 -0
- package/generator/src/rewrite-elm-json.js +17 -7
- package/generator/src/route-codegen-helpers.js +16 -31
- package/generator/src/seo-renderer.js +1 -3
- package/generator/src/vite-utils.js +1 -2
- package/generator/static-code/elm-pages.js +10 -0
- package/generator/static-code/hmr.js +79 -13
- package/generator/template/app/Api.elm +3 -2
- package/generator/template/app/Effect.elm +155 -0
- package/generator/template/app/ErrorPage.elm +49 -6
- package/generator/template/app/Route/Blog/Slug_.elm +86 -0
- package/generator/template/app/Route/Greet.elm +107 -0
- package/generator/template/app/Route/Hello.elm +119 -0
- package/generator/template/app/Route/Index.elm +26 -25
- package/generator/template/app/Shared.elm +38 -39
- package/generator/template/app/Site.elm +4 -7
- package/generator/template/app/View.elm +9 -8
- package/generator/template/codegen/elm.codegen.json +18 -0
- package/generator/template/custom-backend-task.ts +3 -0
- package/generator/template/elm-pages.config.mjs +13 -0
- package/generator/template/elm-tooling.json +0 -3
- package/generator/template/elm.json +25 -20
- package/generator/template/index.ts +1 -2
- package/generator/template/netlify.toml +4 -1
- package/generator/template/package.json +10 -4
- package/generator/template/script/.elm-pages/compiled-ports/custom-backend-task.mjs +7 -0
- package/generator/template/script/custom-backend-task.ts +3 -0
- package/generator/template/script/elm.json +61 -0
- package/generator/template/script/src/AddRoute.elm +312 -0
- package/generator/template/script/src/Stars.elm +42 -0
- package/package.json +30 -27
- package/src/ApiRoute.elm +249 -82
- package/src/BackendTask/Custom.elm +325 -0
- package/src/BackendTask/Env.elm +90 -0
- package/src/{DataSource → BackendTask}/File.elm +171 -56
- package/src/{DataSource → BackendTask}/Glob.elm +136 -125
- package/src/BackendTask/Http.elm +679 -0
- package/src/{DataSource → BackendTask}/Internal/Glob.elm +1 -1
- package/src/BackendTask/Internal/Request.elm +69 -0
- package/src/BackendTask/Random.elm +79 -0
- package/src/BackendTask/Time.elm +47 -0
- package/src/BackendTask.elm +531 -0
- package/src/FatalError.elm +90 -0
- package/src/FormData.elm +21 -18
- package/src/Head/Seo.elm +4 -4
- package/src/Head.elm +112 -8
- package/src/Internal/ApiRoute.elm +7 -5
- package/src/Internal/Request.elm +84 -4
- package/src/PageServerResponse.elm +6 -1
- package/src/Pages/ConcurrentSubmission.elm +127 -0
- package/src/Pages/Form.elm +340 -0
- package/src/Pages/FormData.elm +19 -0
- package/src/Pages/GeneratorProgramConfig.elm +15 -0
- package/src/Pages/Internal/FatalError.elm +5 -0
- package/src/Pages/Internal/Msg.elm +93 -0
- package/src/Pages/Internal/NotFoundReason.elm +4 -4
- package/src/Pages/Internal/Platform/Cli.elm +586 -768
- package/src/Pages/Internal/Platform/CompatibilityKey.elm +1 -1
- package/src/Pages/Internal/Platform/Effect.elm +1 -2
- package/src/Pages/Internal/Platform/GeneratorApplication.elm +379 -0
- package/src/Pages/Internal/Platform/StaticResponses.elm +65 -276
- package/src/Pages/Internal/Platform/ToJsPayload.elm +6 -9
- package/src/Pages/Internal/Platform.elm +330 -203
- package/src/Pages/Internal/ResponseSketch.elm +2 -2
- package/src/Pages/Internal/Script.elm +17 -0
- package/src/Pages/Internal/StaticHttpBody.elm +35 -1
- package/src/Pages/Manifest.elm +52 -11
- package/src/Pages/Navigation.elm +85 -0
- package/src/Pages/PageUrl.elm +26 -12
- package/src/Pages/ProgramConfig.elm +32 -22
- package/src/Pages/Script.elm +166 -0
- package/src/Pages/SiteConfig.elm +3 -2
- package/src/Pages/StaticHttp/Request.elm +2 -2
- package/src/Pages/StaticHttpRequest.elm +23 -99
- package/src/Pages/Url.elm +3 -3
- package/src/PagesMsg.elm +88 -0
- package/src/QueryParams.elm +21 -172
- package/src/RenderRequest.elm +7 -7
- package/src/RequestsAndPending.elm +37 -20
- package/src/Result/Extra.elm +26 -0
- package/src/Scaffold/Form.elm +569 -0
- package/src/Scaffold/Route.elm +1431 -0
- package/src/Server/Request.elm +476 -1001
- package/src/Server/Response.elm +130 -36
- package/src/Server/Session.elm +181 -111
- package/src/Server/SetCookie.elm +80 -32
- package/src/Stub.elm +53 -0
- package/src/Test/Html/Internal/ElmHtml/ToString.elm +8 -9
- package/src/{Path.elm → UrlPath.elm} +33 -36
- package/generator/template/public/images/icon-png.png +0 -0
- package/src/DataSource/Env.elm +0 -38
- package/src/DataSource/Http.elm +0 -446
- package/src/DataSource/Internal/Request.elm +0 -20
- package/src/DataSource/Port.elm +0 -90
- package/src/DataSource.elm +0 -546
- package/src/Form/Field.elm +0 -717
- package/src/Form/FieldStatus.elm +0 -36
- package/src/Form/FieldView.elm +0 -417
- package/src/Form/FormData.elm +0 -22
- package/src/Form/Validation.elm +0 -391
- package/src/Form/Value.elm +0 -118
- package/src/Form.elm +0 -1683
- package/src/FormDecoder.elm +0 -102
- package/src/Pages/FormState.elm +0 -256
- package/src/Pages/Generate.elm +0 -1242
- package/src/Pages/Internal/Form.elm +0 -17
- package/src/Pages/Internal/Platform/Cli.elm.bak +0 -1276
- package/src/Pages/Msg.elm +0 -79
- package/src/Pages/Transition.elm +0 -70
|
@@ -20,34 +20,29 @@ import BuildError exposing (BuildError)
|
|
|
20
20
|
import Bytes exposing (Bytes)
|
|
21
21
|
import Bytes.Decode
|
|
22
22
|
import Dict exposing (Dict)
|
|
23
|
-
import Form
|
|
24
|
-
import FormDecoder
|
|
23
|
+
import Form
|
|
25
24
|
import Html exposing (Html)
|
|
26
25
|
import Html.Attributes as Attr
|
|
27
26
|
import Http
|
|
28
27
|
import Json.Decode as Decode
|
|
29
28
|
import Json.Encode
|
|
29
|
+
import Pages.ConcurrentSubmission
|
|
30
30
|
import Pages.ContentCache as ContentCache
|
|
31
31
|
import Pages.Fetcher
|
|
32
32
|
import Pages.Flags
|
|
33
|
-
import Pages.
|
|
33
|
+
import Pages.Internal.Msg
|
|
34
34
|
import Pages.Internal.NotFoundReason exposing (NotFoundReason)
|
|
35
35
|
import Pages.Internal.ResponseSketch as ResponseSketch exposing (ResponseSketch)
|
|
36
36
|
import Pages.Internal.String as String
|
|
37
|
-
import Pages.
|
|
37
|
+
import Pages.Navigation
|
|
38
38
|
import Pages.ProgramConfig exposing (ProgramConfig)
|
|
39
39
|
import Pages.StaticHttpRequest as StaticHttpRequest
|
|
40
|
-
import
|
|
41
|
-
import Path exposing (Path)
|
|
40
|
+
import PagesMsg exposing (PagesMsg)
|
|
42
41
|
import QueryParams
|
|
43
42
|
import Task
|
|
44
43
|
import Time
|
|
45
44
|
import Url exposing (Url)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
type Transition
|
|
49
|
-
= Loading Int Path
|
|
50
|
-
| Submitting FormData
|
|
45
|
+
import UrlPath exposing (UrlPath)
|
|
51
46
|
|
|
52
47
|
|
|
53
48
|
{-| -}
|
|
@@ -58,7 +53,7 @@ type alias Program userModel userMsg pageData actionData sharedData errorPage =
|
|
|
58
53
|
mainView :
|
|
59
54
|
ProgramConfig userMsg userModel route pageData actionData sharedData effect (Msg userMsg pageData actionData sharedData errorPage) errorPage
|
|
60
55
|
-> Model userModel pageData actionData sharedData
|
|
61
|
-
-> { title : String, body : List (Html (
|
|
56
|
+
-> { title : String, body : List (Html (PagesMsg userMsg)) }
|
|
62
57
|
mainView config model =
|
|
63
58
|
case model.notFound of
|
|
64
59
|
Just info ->
|
|
@@ -81,7 +76,7 @@ mainView config model =
|
|
|
81
76
|
(config.view model.pageFormState
|
|
82
77
|
(model.inFlightFetchers |> toFetcherState)
|
|
83
78
|
(model.transition |> Maybe.map Tuple.second)
|
|
84
|
-
{ path = ContentCache.pathForUrl urls |>
|
|
79
|
+
{ path = ContentCache.pathForUrl urls |> UrlPath.join
|
|
85
80
|
, route = config.urlToRoute { currentUrl | path = model.currentPath }
|
|
86
81
|
}
|
|
87
82
|
Nothing
|
|
@@ -101,14 +96,14 @@ mainView config model =
|
|
|
101
96
|
|
|
102
97
|
urlsToPagePath :
|
|
103
98
|
{ currentUrl : Url, basePath : List String }
|
|
104
|
-
->
|
|
99
|
+
-> UrlPath
|
|
105
100
|
urlsToPagePath urls =
|
|
106
101
|
urls.currentUrl.path
|
|
107
102
|
|> String.chopForwardSlashes
|
|
108
103
|
|> String.split "/"
|
|
109
104
|
|> List.filter ((/=) "")
|
|
110
105
|
|> List.drop (List.length urls.basePath)
|
|
111
|
-
|>
|
|
106
|
+
|> UrlPath.join
|
|
112
107
|
|
|
113
108
|
|
|
114
109
|
{-| -}
|
|
@@ -150,7 +145,7 @@ type alias Flags =
|
|
|
150
145
|
|
|
151
146
|
type InitKind shared page actionData errorPage
|
|
152
147
|
= OkPage shared page (Maybe actionData)
|
|
153
|
-
| NotFound { reason : NotFoundReason, path :
|
|
148
|
+
| NotFound { reason : NotFoundReason, path : UrlPath }
|
|
154
149
|
|
|
155
150
|
|
|
156
151
|
{-| -}
|
|
@@ -204,7 +199,7 @@ init config flags url key =
|
|
|
204
199
|
, basePath = config.basePath
|
|
205
200
|
}
|
|
206
201
|
|
|
207
|
-
pagePath :
|
|
202
|
+
pagePath : UrlPath
|
|
208
203
|
pagePath =
|
|
209
204
|
urlsToPagePath urls
|
|
210
205
|
|
|
@@ -230,7 +225,7 @@ init config flags url key =
|
|
|
230
225
|
, host = url.host
|
|
231
226
|
, port_ = url.port_
|
|
232
227
|
, path = pagePath
|
|
233
|
-
, query = url.query |> Maybe.map QueryParams.fromString
|
|
228
|
+
, query = url.query |> Maybe.map QueryParams.fromString |> Maybe.withDefault Dict.empty
|
|
234
229
|
, fragment = url.fragment
|
|
235
230
|
}
|
|
236
231
|
}
|
|
@@ -274,7 +269,7 @@ init config flags url key =
|
|
|
274
269
|
, url = url
|
|
275
270
|
, currentPath = url.path
|
|
276
271
|
, pageData = Err "Not found"
|
|
277
|
-
, ariaNavigationAnnouncement = "
|
|
272
|
+
, ariaNavigationAnnouncement = "Page Not Found" -- TODO use error page title for announcement?
|
|
278
273
|
, userFlags = flags
|
|
279
274
|
, notFound = Just info
|
|
280
275
|
, transition = Nothing
|
|
@@ -313,16 +308,23 @@ init config flags url key =
|
|
|
313
308
|
type Msg userMsg pageData actionData sharedData errorPage
|
|
314
309
|
= LinkClicked Browser.UrlRequest
|
|
315
310
|
| UrlChanged Url
|
|
316
|
-
|
|
317
|
-
|
|
|
311
|
+
-- TODO rename to PagesMsg
|
|
312
|
+
| UserMsg (PagesMsg userMsg)
|
|
313
|
+
--| SetField { formId : String, name : String, value : String }
|
|
314
|
+
| FormMsg (Form.Msg (Msg userMsg pageData actionData sharedData errorPage))
|
|
318
315
|
| UpdateCacheAndUrlNew Bool Url (Maybe userMsg) (Result Http.Error ( Url, ResponseSketch pageData actionData sharedData ))
|
|
319
|
-
| FetcherComplete Bool String Int (Result Http.Error ( Maybe userMsg,
|
|
316
|
+
| FetcherComplete Bool String Int (Result Http.Error ( Maybe userMsg, ActionDataOrRedirect actionData ))
|
|
320
317
|
| FetcherStarted String Int FormData Time.Posix
|
|
321
318
|
| PageScrollComplete
|
|
322
319
|
| HotReloadCompleteNew Bytes
|
|
323
320
|
| ProcessFetchResponse Int (Result Http.Error ( Url, ResponseSketch pageData actionData sharedData )) (Result Http.Error ( Url, ResponseSketch pageData actionData sharedData ) -> Msg userMsg pageData actionData sharedData errorPage)
|
|
324
321
|
|
|
325
322
|
|
|
323
|
+
type ActionDataOrRedirect action
|
|
324
|
+
= ActionResponse (Maybe action)
|
|
325
|
+
| RedirectResponse String
|
|
326
|
+
|
|
327
|
+
|
|
326
328
|
{-| -}
|
|
327
329
|
type alias Model userModel pageData actionData sharedData =
|
|
328
330
|
{ key : Maybe Browser.Navigation.Key
|
|
@@ -337,12 +339,12 @@ type alias Model userModel pageData actionData sharedData =
|
|
|
337
339
|
, sharedData : sharedData
|
|
338
340
|
, actionData : Maybe actionData
|
|
339
341
|
}
|
|
340
|
-
, notFound : Maybe { reason : NotFoundReason, path :
|
|
342
|
+
, notFound : Maybe { reason : NotFoundReason, path : UrlPath }
|
|
341
343
|
, userFlags : Decode.Value
|
|
342
|
-
, transition : Maybe ( Int, Pages.
|
|
344
|
+
, transition : Maybe ( Int, Pages.Navigation.Navigation )
|
|
343
345
|
, nextTransitionKey : Int
|
|
344
|
-
, inFlightFetchers : Dict String ( Int, Pages.
|
|
345
|
-
, pageFormState :
|
|
346
|
+
, inFlightFetchers : Dict String ( Int, Pages.ConcurrentSubmission.ConcurrentSubmission actionData )
|
|
347
|
+
, pageFormState : Form.Model
|
|
346
348
|
, pendingRedirect : Bool
|
|
347
349
|
, pendingData : Maybe ( pageData, sharedData, Maybe actionData )
|
|
348
350
|
}
|
|
@@ -361,6 +363,7 @@ type Effect userMsg pageData actionData sharedData userEffect errorPage
|
|
|
361
363
|
| Batch (List (Effect userMsg pageData actionData sharedData userEffect errorPage))
|
|
362
364
|
| UserCmd userEffect
|
|
363
365
|
| CancelRequest Int
|
|
366
|
+
| RunCmd (Cmd (Msg userMsg pageData actionData sharedData errorPage))
|
|
364
367
|
|
|
365
368
|
|
|
366
369
|
{-| -}
|
|
@@ -371,6 +374,18 @@ update :
|
|
|
371
374
|
-> ( Model userModel pageData actionData sharedData, Effect userMsg pageData actionData sharedData userEffect errorPage )
|
|
372
375
|
update config appMsg model =
|
|
373
376
|
case appMsg of
|
|
377
|
+
FormMsg formMsg ->
|
|
378
|
+
let
|
|
379
|
+
-- TODO trigger formCmd
|
|
380
|
+
( newModel, formCmd ) =
|
|
381
|
+
Form.update formMsg model.pageFormState
|
|
382
|
+
in
|
|
383
|
+
( { model
|
|
384
|
+
| pageFormState = newModel
|
|
385
|
+
}
|
|
386
|
+
, RunCmd formCmd
|
|
387
|
+
)
|
|
388
|
+
|
|
374
389
|
LinkClicked urlRequest ->
|
|
375
390
|
case urlRequest of
|
|
376
391
|
Browser.Internal url ->
|
|
@@ -396,11 +411,6 @@ update config appMsg model =
|
|
|
396
411
|
, BrowserLoadUrl href
|
|
397
412
|
)
|
|
398
413
|
|
|
399
|
-
SetField info ->
|
|
400
|
-
( { model | pageFormState = Pages.FormState.setField info model.pageFormState }
|
|
401
|
-
, NoEffect
|
|
402
|
-
)
|
|
403
|
-
|
|
404
414
|
UrlChanged url ->
|
|
405
415
|
case model.pendingData of
|
|
406
416
|
Just ( newPageData, newSharedData, newActionData ) ->
|
|
@@ -414,7 +424,7 @@ update config appMsg model =
|
|
|
414
424
|
model
|
|
415
425
|
|
|
416
426
|
Nothing ->
|
|
417
|
-
if model.url.path == url.path then
|
|
427
|
+
if model.url.path == url.path && model.url.query == url.query then
|
|
418
428
|
( { model
|
|
419
429
|
| -- update the URL in case query params or fragment changed
|
|
420
430
|
url = url
|
|
@@ -430,37 +440,50 @@ update config appMsg model =
|
|
|
430
440
|
-- parallel to the browser behavior
|
|
431
441
|
|> startNewGetLoad url (UpdateCacheAndUrlNew True url Nothing)
|
|
432
442
|
|
|
433
|
-
FetcherComplete
|
|
443
|
+
FetcherComplete _ fetcherKey _ userMsgResult ->
|
|
434
444
|
case userMsgResult of
|
|
435
|
-
Ok ( userMsg,
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
model
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
(
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
445
|
+
Ok ( userMsg, actionOrRedirect ) ->
|
|
446
|
+
case actionOrRedirect of
|
|
447
|
+
ActionResponse maybeFetcherDoneActionData ->
|
|
448
|
+
( { model
|
|
449
|
+
| inFlightFetchers =
|
|
450
|
+
model.inFlightFetchers
|
|
451
|
+
|> Dict.update fetcherKey
|
|
452
|
+
(Maybe.map
|
|
453
|
+
(\( transitionId, fetcherState ) ->
|
|
454
|
+
( transitionId
|
|
455
|
+
, { fetcherState
|
|
456
|
+
| status =
|
|
457
|
+
maybeFetcherDoneActionData
|
|
458
|
+
|> Maybe.map Pages.ConcurrentSubmission.Reloading
|
|
459
|
+
-- TODO remove this bad default, FetcherSubmitting is incorrect
|
|
460
|
+
|> Maybe.withDefault Pages.ConcurrentSubmission.Submitting
|
|
461
|
+
}
|
|
462
|
+
)
|
|
463
|
+
)
|
|
450
464
|
)
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
465
|
+
}
|
|
466
|
+
, NoEffect
|
|
467
|
+
)
|
|
468
|
+
|> (case userMsg of
|
|
469
|
+
Just justUserMsg ->
|
|
470
|
+
performUserMsg justUserMsg config
|
|
471
|
+
|
|
472
|
+
Nothing ->
|
|
473
|
+
identity
|
|
474
|
+
)
|
|
475
|
+
|> startNewGetLoad (currentUrlWithPath model.url.path model) (UpdateCacheAndUrlNew False model.url Nothing)
|
|
476
|
+
|
|
477
|
+
RedirectResponse redirectTo ->
|
|
478
|
+
( { model
|
|
479
|
+
| inFlightFetchers =
|
|
480
|
+
model.inFlightFetchers
|
|
481
|
+
|> Dict.remove fetcherKey
|
|
482
|
+
, pendingRedirect = True
|
|
483
|
+
}
|
|
484
|
+
, NoEffect
|
|
485
|
+
)
|
|
486
|
+
|> startNewGetLoad (currentUrlWithPath redirectTo model) (UpdateCacheAndUrlNew False model.url Nothing)
|
|
464
487
|
|
|
465
488
|
Err _ ->
|
|
466
489
|
-- TODO how to handle error?
|
|
@@ -478,74 +501,70 @@ update config appMsg model =
|
|
|
478
501
|
|
|
479
502
|
UserMsg userMsg_ ->
|
|
480
503
|
case userMsg_ of
|
|
481
|
-
Pages.Msg.UserMsg userMsg ->
|
|
504
|
+
Pages.Internal.Msg.UserMsg userMsg ->
|
|
482
505
|
( model, NoEffect )
|
|
483
506
|
|> performUserMsg userMsg config
|
|
484
507
|
|
|
485
|
-
Pages.Msg.Submit fields ->
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
,
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
( { model | nextTransitionKey = model.nextTransitionKey + 1 }
|
|
524
|
-
, SubmitFetcher fetcherKey model.nextTransitionKey fields
|
|
525
|
-
)
|
|
526
|
-
|> (case maybeUserMsg of
|
|
527
|
-
Just justUserMsg ->
|
|
528
|
-
performUserMsg justUserMsg config
|
|
508
|
+
Pages.Internal.Msg.Submit fields ->
|
|
509
|
+
if fields.valid then
|
|
510
|
+
let
|
|
511
|
+
payload : { fields : List ( String, String ), method : Form.Method, action : String, id : Maybe String }
|
|
512
|
+
payload =
|
|
513
|
+
{ fields = fields.fields
|
|
514
|
+
, method = fields.method
|
|
515
|
+
, action = fields.action
|
|
516
|
+
, id = Just fields.id
|
|
517
|
+
}
|
|
518
|
+
in
|
|
519
|
+
if fields.useFetcher then
|
|
520
|
+
( { model | nextTransitionKey = model.nextTransitionKey + 1 }
|
|
521
|
+
, SubmitFetcher fields.id model.nextTransitionKey payload
|
|
522
|
+
)
|
|
523
|
+
|> (case fields.msg of
|
|
524
|
+
Just justUserMsg ->
|
|
525
|
+
performUserMsg justUserMsg config
|
|
526
|
+
|
|
527
|
+
Nothing ->
|
|
528
|
+
identity
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
else
|
|
532
|
+
( { model
|
|
533
|
+
-- TODO should I setSubmitAttempted here, too?
|
|
534
|
+
| transition =
|
|
535
|
+
Just
|
|
536
|
+
( -- TODO remove hardcoded number
|
|
537
|
+
-1
|
|
538
|
+
, Pages.Navigation.Submitting payload
|
|
539
|
+
)
|
|
540
|
+
}
|
|
541
|
+
, Submit payload
|
|
542
|
+
)
|
|
543
|
+
|> (case fields.msg of
|
|
544
|
+
Just justUserMsg ->
|
|
545
|
+
performUserMsg justUserMsg config
|
|
529
546
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
547
|
+
Nothing ->
|
|
548
|
+
identity
|
|
549
|
+
)
|
|
533
550
|
|
|
534
551
|
else
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
model.pageFormState
|
|
538
|
-
|> Pages.FormState.setSubmitAttempted fetcherKey
|
|
539
|
-
}
|
|
540
|
-
, NoEffect
|
|
541
|
-
)
|
|
552
|
+
-- TODO should the user msg still be run if the form is invalid?
|
|
553
|
+
( model, NoEffect )
|
|
542
554
|
|
|
543
|
-
Pages.Msg.
|
|
555
|
+
Pages.Internal.Msg.FormMsg formMsg ->
|
|
544
556
|
-- TODO when init is called for a new page, also need to clear out client-side `pageFormState`
|
|
545
|
-
|
|
546
|
-
|
|
557
|
+
let
|
|
558
|
+
( formModel, formCmd ) =
|
|
559
|
+
Form.update formMsg model.pageFormState
|
|
560
|
+
in
|
|
561
|
+
( { model | pageFormState = formModel }
|
|
562
|
+
, RunCmd (Cmd.map UserMsg formCmd)
|
|
547
563
|
)
|
|
548
564
|
|
|
565
|
+
Pages.Internal.Msg.NoOp ->
|
|
566
|
+
( model, NoEffect )
|
|
567
|
+
|
|
549
568
|
UpdateCacheAndUrlNew scrollToTopWhenDone urlWithoutRedirectResolution maybeUserMsg updateResult ->
|
|
550
569
|
-- TODO remove all fetchers that are in the state `FetcherReloading` here -- I think that's the right logic?
|
|
551
570
|
case
|
|
@@ -685,10 +704,10 @@ update config appMsg model =
|
|
|
685
704
|
Err _ ->
|
|
686
705
|
{-
|
|
687
706
|
When there is an error loading the content.dat, we are either
|
|
688
|
-
1) in the dev server, and should show the relevant
|
|
707
|
+
1) in the dev server, and should show the relevant BackendTask error for the page
|
|
689
708
|
we're navigating to. This could be done more cleanly, but it's simplest to just
|
|
690
709
|
do a fresh page load and use the code path for presenting an error for a fresh page.
|
|
691
|
-
2) In a production app. That means we had a successful build, so there were no
|
|
710
|
+
2) In a production app. That means we had a successful build, so there were no BackendTask failures,
|
|
692
711
|
so the app must be stale (unless it's in some unexpected state from a bug). In the future,
|
|
693
712
|
it probably makes sense to include some sort of hash of the app version we are fetching, match
|
|
694
713
|
it with the current version that's running, and perform this logic when we see there is a mismatch.
|
|
@@ -751,7 +770,86 @@ update config appMsg model =
|
|
|
751
770
|
_ ->
|
|
752
771
|
( model, NoEffect )
|
|
753
772
|
)
|
|
754
|
-
|> Result.withDefault
|
|
773
|
+
|> Result.withDefault
|
|
774
|
+
(let
|
|
775
|
+
pageDataResult : Maybe (InitKind sharedData pageData actionData errorPage)
|
|
776
|
+
pageDataResult =
|
|
777
|
+
case Bytes.Decode.decode config.decodeResponse pageDataBytes of
|
|
778
|
+
Just (ResponseSketch.RenderPage _ _) ->
|
|
779
|
+
Nothing
|
|
780
|
+
|
|
781
|
+
Just (ResponseSketch.HotUpdate pageData shared actionData) ->
|
|
782
|
+
OkPage shared pageData actionData
|
|
783
|
+
|> Just
|
|
784
|
+
|
|
785
|
+
Just (ResponseSketch.NotFound notFound) ->
|
|
786
|
+
NotFound notFound
|
|
787
|
+
|> Just
|
|
788
|
+
|
|
789
|
+
_ ->
|
|
790
|
+
Nothing
|
|
791
|
+
in
|
|
792
|
+
case pageDataResult of
|
|
793
|
+
Just (OkPage sharedData pageData actionData) ->
|
|
794
|
+
let
|
|
795
|
+
urls : { currentUrl : Url, basePath : List String }
|
|
796
|
+
urls =
|
|
797
|
+
{ currentUrl = model.url
|
|
798
|
+
, basePath = config.basePath
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
pagePath : UrlPath
|
|
802
|
+
pagePath =
|
|
803
|
+
urlsToPagePath urls
|
|
804
|
+
|
|
805
|
+
userFlags : Pages.Flags.Flags
|
|
806
|
+
userFlags =
|
|
807
|
+
model.userFlags
|
|
808
|
+
|> Decode.decodeValue
|
|
809
|
+
(Decode.field "userFlags" Decode.value)
|
|
810
|
+
|> Result.withDefault Json.Encode.null
|
|
811
|
+
|> Pages.Flags.BrowserFlags
|
|
812
|
+
|
|
813
|
+
( userModel, userCmd ) =
|
|
814
|
+
Just
|
|
815
|
+
{ path =
|
|
816
|
+
{ path = pagePath
|
|
817
|
+
, query = model.url.query
|
|
818
|
+
, fragment = model.url.fragment
|
|
819
|
+
}
|
|
820
|
+
, metadata = config.urlToRoute model.url
|
|
821
|
+
, pageUrl =
|
|
822
|
+
Just
|
|
823
|
+
{ protocol = model.url.protocol
|
|
824
|
+
, host = model.url.host
|
|
825
|
+
, port_ = model.url.port_
|
|
826
|
+
, path = pagePath
|
|
827
|
+
, query = model.url.query |> Maybe.map QueryParams.fromString |> Maybe.withDefault Dict.empty
|
|
828
|
+
, fragment = model.url.fragment
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
|> config.init userFlags sharedData pageData actionData
|
|
832
|
+
|
|
833
|
+
cmd : Effect userMsg pageData actionData sharedData userEffect errorPage
|
|
834
|
+
cmd =
|
|
835
|
+
UserCmd userCmd
|
|
836
|
+
in
|
|
837
|
+
( { model
|
|
838
|
+
| pageData =
|
|
839
|
+
Ok
|
|
840
|
+
{ userModel = userModel
|
|
841
|
+
, sharedData = sharedData
|
|
842
|
+
, pageData = pageData
|
|
843
|
+
, actionData = actionData
|
|
844
|
+
}
|
|
845
|
+
, notFound = Nothing
|
|
846
|
+
}
|
|
847
|
+
, cmd
|
|
848
|
+
)
|
|
849
|
+
|
|
850
|
+
_ ->
|
|
851
|
+
( model, NoEffect )
|
|
852
|
+
)
|
|
755
853
|
|
|
756
854
|
FetcherStarted fetcherKey transitionId fetcherData initiatedAt ->
|
|
757
855
|
( { model
|
|
@@ -760,7 +858,7 @@ update config appMsg model =
|
|
|
760
858
|
|> Dict.insert fetcherKey
|
|
761
859
|
( transitionId
|
|
762
860
|
, { payload = fetcherData
|
|
763
|
-
, status = Pages.
|
|
861
|
+
, status = Pages.ConcurrentSubmission.Submitting
|
|
764
862
|
, initiatedAt = initiatedAt
|
|
765
863
|
}
|
|
766
864
|
)
|
|
@@ -769,10 +867,10 @@ update config appMsg model =
|
|
|
769
867
|
)
|
|
770
868
|
|
|
771
869
|
|
|
772
|
-
toFetcherState : Dict String ( Int, Pages.
|
|
870
|
+
toFetcherState : Dict String ( Int, Pages.ConcurrentSubmission.ConcurrentSubmission actionData ) -> Dict String (Pages.ConcurrentSubmission.ConcurrentSubmission actionData)
|
|
773
871
|
toFetcherState inFlightFetchers =
|
|
774
872
|
inFlightFetchers
|
|
775
|
-
|> Dict.map (\_ (
|
|
873
|
+
|> Dict.map (\_ ( _, fetcherState ) -> fetcherState)
|
|
776
874
|
|
|
777
875
|
|
|
778
876
|
performUserMsg :
|
|
@@ -806,6 +904,9 @@ perform config model effect =
|
|
|
806
904
|
NoEffect ->
|
|
807
905
|
Cmd.none
|
|
808
906
|
|
|
907
|
+
RunCmd cmd ->
|
|
908
|
+
cmd
|
|
909
|
+
|
|
809
910
|
Batch effects ->
|
|
810
911
|
effects
|
|
811
912
|
|> List.map (perform config model)
|
|
@@ -834,10 +935,10 @@ perform config model effect =
|
|
|
834
935
|
|> Maybe.withDefault Cmd.none
|
|
835
936
|
|
|
836
937
|
FetchPageData transitionKey maybeRequestInfo url toMsg ->
|
|
837
|
-
fetchRouteData
|
|
938
|
+
fetchRouteData transitionKey toMsg config url maybeRequestInfo
|
|
838
939
|
|
|
839
940
|
Submit fields ->
|
|
840
|
-
if fields.method == Get then
|
|
941
|
+
if fields.method == Form.Get then
|
|
841
942
|
model.key
|
|
842
943
|
|> Maybe.map (\key -> Browser.Navigation.pushUrl key (appendFormQueryParams fields))
|
|
843
944
|
|> Maybe.withDefault Cmd.none
|
|
@@ -849,7 +950,7 @@ perform config model effect =
|
|
|
849
950
|
-- TODO add optional path parameter to Submit variant to allow submitting to other routes
|
|
850
951
|
model.url
|
|
851
952
|
in
|
|
852
|
-
fetchRouteData
|
|
953
|
+
fetchRouteData -1 (UpdateCacheAndUrlNew False model.url Nothing) config urlToSubmitTo (Just fields)
|
|
853
954
|
|
|
854
955
|
SubmitFetcher fetcherKey transitionId formData ->
|
|
855
956
|
startFetcher2 config False fetcherKey transitionId formData model
|
|
@@ -869,7 +970,7 @@ perform config model effect =
|
|
|
869
970
|
|> config.perform
|
|
870
971
|
{ fetchRouteData =
|
|
871
972
|
\fetchInfo ->
|
|
872
|
-
fetchRouteData
|
|
973
|
+
fetchRouteData
|
|
873
974
|
-1
|
|
874
975
|
(prepare fetchInfo.toMsg)
|
|
875
976
|
config
|
|
@@ -879,15 +980,19 @@ perform config model effect =
|
|
|
879
980
|
---- TODO map the Msg with the wrapper type (like in the PR branch)
|
|
880
981
|
, submit =
|
|
881
982
|
\fetchInfo ->
|
|
882
|
-
fetchRouteData
|
|
983
|
+
fetchRouteData -1 (prepare fetchInfo.toMsg) config (fetchInfo.values.action |> Url.fromString |> Maybe.withDefault model.url) (Just fetchInfo.values)
|
|
883
984
|
, runFetcher =
|
|
884
985
|
\(Pages.Fetcher.Fetcher options) ->
|
|
885
986
|
-- TODO need to get the fetcherId here
|
|
886
987
|
-- TODO need to increment and pass in the transitionId
|
|
887
988
|
startFetcher "TODO" -1 options model
|
|
888
|
-
, fromPageMsg = Pages.Msg.UserMsg >> UserMsg
|
|
989
|
+
, fromPageMsg = Pages.Internal.Msg.UserMsg >> UserMsg
|
|
889
990
|
, key = key
|
|
890
|
-
, setField =
|
|
991
|
+
, setField =
|
|
992
|
+
\_ ->
|
|
993
|
+
--Task.succeed (SetField info) |> Task.perform identity
|
|
994
|
+
-- TODO
|
|
995
|
+
Cmd.none
|
|
891
996
|
}
|
|
892
997
|
|
|
893
998
|
Nothing ->
|
|
@@ -902,21 +1007,12 @@ startFetcher fetcherKey transitionId options model =
|
|
|
902
1007
|
let
|
|
903
1008
|
encodedBody : String
|
|
904
1009
|
encodedBody =
|
|
905
|
-
|
|
906
|
-
{ fields = options.fields
|
|
907
|
-
|
|
908
|
-
-- TODO remove hardcoding
|
|
909
|
-
, action = ""
|
|
910
|
-
|
|
911
|
-
-- TODO remove hardcoding
|
|
912
|
-
, method = Post
|
|
913
|
-
, id = Nothing
|
|
914
|
-
}
|
|
1010
|
+
encodeFormData options.fields
|
|
915
1011
|
|
|
916
|
-
formData : { method : Method, action : String, fields : List ( String, String ), id : Maybe String }
|
|
1012
|
+
formData : { method : Form.Method, action : String, fields : List ( String, String ), id : Maybe String }
|
|
917
1013
|
formData =
|
|
918
1014
|
{ -- TODO remove hardcoding
|
|
919
|
-
method = Get
|
|
1015
|
+
method = Form.Get
|
|
920
1016
|
|
|
921
1017
|
-- TODO pass FormData directly
|
|
922
1018
|
, action = options.url |> Maybe.withDefault model.url.path
|
|
@@ -933,10 +1029,10 @@ startFetcher fetcherKey transitionId options model =
|
|
|
933
1029
|
Http.expectBytesResponse (FetcherComplete False fetcherKey model.nextTransitionKey)
|
|
934
1030
|
(\bytes ->
|
|
935
1031
|
case bytes of
|
|
936
|
-
Http.GoodStatus_
|
|
1032
|
+
Http.GoodStatus_ _ bytesBody ->
|
|
937
1033
|
( options.decoder (Ok bytesBody)
|
|
938
1034
|
|> Just
|
|
939
|
-
, Nothing
|
|
1035
|
+
, ActionResponse Nothing
|
|
940
1036
|
)
|
|
941
1037
|
|> Ok
|
|
942
1038
|
|
|
@@ -949,13 +1045,13 @@ startFetcher fetcherKey transitionId options model =
|
|
|
949
1045
|
Http.NetworkError_ ->
|
|
950
1046
|
Err <| Http.NetworkError
|
|
951
1047
|
|
|
952
|
-
Http.BadStatus_ metadata
|
|
1048
|
+
Http.BadStatus_ metadata _ ->
|
|
953
1049
|
Err <| Http.BadStatus metadata.statusCode
|
|
954
1050
|
)
|
|
955
1051
|
, tracker = Nothing
|
|
956
1052
|
, body = Http.stringBody "application/x-www-form-urlencoded" encodedBody
|
|
957
1053
|
, headers = options.headers |> List.map (\( name, value ) -> Http.header name value)
|
|
958
|
-
, url = options.url |> Maybe.withDefault (
|
|
1054
|
+
, url = options.url |> Maybe.withDefault (UrlPath.join [ model.url.path, "content.dat" ] |> UrlPath.toAbsolute)
|
|
959
1055
|
, method = "POST"
|
|
960
1056
|
, timeout = Nothing
|
|
961
1057
|
}
|
|
@@ -974,13 +1070,13 @@ startFetcher2 config fromPageReload fetcherKey transitionId formData model =
|
|
|
974
1070
|
let
|
|
975
1071
|
encodedBody : String
|
|
976
1072
|
encodedBody =
|
|
977
|
-
|
|
1073
|
+
encodeFormData formData.fields
|
|
978
1074
|
in
|
|
979
1075
|
-- TODO make sure that `actionData` isn't updated in Model for fetchers
|
|
980
1076
|
Cmd.batch
|
|
981
1077
|
[ cancelStaleFetchers model
|
|
982
1078
|
, case Dict.get fetcherKey model.inFlightFetchers of
|
|
983
|
-
Just ( inFlightId,
|
|
1079
|
+
Just ( inFlightId, _ ) ->
|
|
984
1080
|
Http.cancel (String.fromInt inFlightId)
|
|
985
1081
|
|
|
986
1082
|
Nothing ->
|
|
@@ -991,22 +1087,26 @@ startFetcher2 config fromPageReload fetcherKey transitionId formData model =
|
|
|
991
1087
|
Http.expectBytesResponse (FetcherComplete fromPageReload fetcherKey model.nextTransitionKey)
|
|
992
1088
|
(\bytes ->
|
|
993
1089
|
case bytes of
|
|
994
|
-
Http.GoodStatus_
|
|
1090
|
+
Http.GoodStatus_ _ bytesBody ->
|
|
995
1091
|
let
|
|
996
|
-
decodedAction :
|
|
1092
|
+
decodedAction : ActionDataOrRedirect actionData
|
|
997
1093
|
decodedAction =
|
|
998
1094
|
case Bytes.Decode.decode config.decodeResponse bytesBody of
|
|
1095
|
+
-- @@@
|
|
1096
|
+
Just (ResponseSketch.Redirect redirectTo) ->
|
|
1097
|
+
RedirectResponse redirectTo
|
|
1098
|
+
|
|
999
1099
|
Just (ResponseSketch.RenderPage _ maybeAction) ->
|
|
1000
|
-
maybeAction
|
|
1100
|
+
ActionResponse maybeAction
|
|
1001
1101
|
|
|
1002
|
-
Just (ResponseSketch.HotUpdate
|
|
1003
|
-
maybeAction
|
|
1102
|
+
Just (ResponseSketch.HotUpdate _ _ maybeAction) ->
|
|
1103
|
+
ActionResponse maybeAction
|
|
1004
1104
|
|
|
1005
|
-
Just (ResponseSketch.NotFound
|
|
1006
|
-
Nothing
|
|
1105
|
+
Just (ResponseSketch.NotFound _) ->
|
|
1106
|
+
ActionResponse Nothing
|
|
1007
1107
|
|
|
1008
1108
|
_ ->
|
|
1009
|
-
Nothing
|
|
1109
|
+
ActionResponse Nothing
|
|
1010
1110
|
in
|
|
1011
1111
|
-- TODO maybe have an optional way to pass the bytes through?
|
|
1012
1112
|
Ok ( Nothing, decodedAction )
|
|
@@ -1020,7 +1120,7 @@ startFetcher2 config fromPageReload fetcherKey transitionId formData model =
|
|
|
1020
1120
|
Http.NetworkError_ ->
|
|
1021
1121
|
Err <| Http.NetworkError
|
|
1022
1122
|
|
|
1023
|
-
Http.BadStatus_ metadata
|
|
1123
|
+
Http.BadStatus_ metadata _ ->
|
|
1024
1124
|
Err <| Http.BadStatus metadata.statusCode
|
|
1025
1125
|
)
|
|
1026
1126
|
, tracker = Just (String.fromInt transitionId)
|
|
@@ -1030,8 +1130,8 @@ startFetcher2 config fromPageReload fetcherKey transitionId formData model =
|
|
|
1030
1130
|
, headers = []
|
|
1031
1131
|
|
|
1032
1132
|
-- TODO use formData.method to do either query params or POST body
|
|
1033
|
-
, url = formData.action |> Url.fromString |> Maybe.map (\{ path } ->
|
|
1034
|
-
, method = formData.method |>
|
|
1133
|
+
, url = formData.action |> Url.fromString |> Maybe.map (\{ path } -> UrlPath.join [ path, "content.dat" ] |> UrlPath.toAbsolute) |> Maybe.withDefault "/"
|
|
1134
|
+
, method = formData.method |> methodToString
|
|
1035
1135
|
, timeout = Nothing
|
|
1036
1136
|
}
|
|
1037
1137
|
]
|
|
@@ -1042,16 +1142,16 @@ cancelStaleFetchers model =
|
|
|
1042
1142
|
model.inFlightFetchers
|
|
1043
1143
|
|> Dict.toList
|
|
1044
1144
|
|> List.filterMap
|
|
1045
|
-
(\(
|
|
1145
|
+
(\( _, ( id, fetcher ) ) ->
|
|
1046
1146
|
case fetcher.status of
|
|
1047
|
-
Pages.
|
|
1147
|
+
Pages.ConcurrentSubmission.Reloading _ ->
|
|
1048
1148
|
Http.cancel (String.fromInt id)
|
|
1049
1149
|
|> Just
|
|
1050
1150
|
|
|
1051
|
-
Pages.
|
|
1151
|
+
Pages.ConcurrentSubmission.Submitting ->
|
|
1052
1152
|
Nothing
|
|
1053
1153
|
|
|
1054
|
-
Pages.
|
|
1154
|
+
Pages.ConcurrentSubmission.Complete _ ->
|
|
1055
1155
|
Nothing
|
|
1056
1156
|
)
|
|
1057
1157
|
|> Cmd.batch
|
|
@@ -1065,10 +1165,10 @@ appendFormQueryParams fields =
|
|
|
1065
1165
|
|> Maybe.withDefault "/"
|
|
1066
1166
|
)
|
|
1067
1167
|
++ (case fields.method of
|
|
1068
|
-
Get ->
|
|
1069
|
-
"?" ++
|
|
1168
|
+
Form.Get ->
|
|
1169
|
+
"?" ++ encodeFormData fields.fields
|
|
1070
1170
|
|
|
1071
|
-
Post ->
|
|
1171
|
+
Form.Post ->
|
|
1072
1172
|
""
|
|
1073
1173
|
)
|
|
1074
1174
|
|
|
@@ -1108,9 +1208,9 @@ application config =
|
|
|
1108
1208
|
in
|
|
1109
1209
|
Sub.batch
|
|
1110
1210
|
[ config.subscriptions (model.url |> config.urlToRoute)
|
|
1111
|
-
(urls.currentUrl |> config.urlToRoute |> config.routeToPath |>
|
|
1211
|
+
(urls.currentUrl |> config.urlToRoute |> config.routeToPath |> UrlPath.join)
|
|
1112
1212
|
pageData.userModel
|
|
1113
|
-
|> Sub.map (Pages.Msg.UserMsg >> UserMsg)
|
|
1213
|
+
|> Sub.map (Pages.Internal.Msg.UserMsg >> UserMsg)
|
|
1114
1214
|
, config.hotReloadData
|
|
1115
1215
|
|> Sub.map HotReloadCompleteNew
|
|
1116
1216
|
]
|
|
@@ -1157,20 +1257,19 @@ withUserMsg config userMsg ( model, effect ) =
|
|
|
1157
1257
|
( model, effect )
|
|
1158
1258
|
|
|
1159
1259
|
|
|
1160
|
-
urlPathToPath : Url ->
|
|
1260
|
+
urlPathToPath : Url -> UrlPath
|
|
1161
1261
|
urlPathToPath urls =
|
|
1162
|
-
urls.path |>
|
|
1262
|
+
urls.path |> UrlPath.fromString
|
|
1163
1263
|
|
|
1164
1264
|
|
|
1165
1265
|
fetchRouteData :
|
|
1166
|
-
|
|
1167
|
-
-> Int
|
|
1266
|
+
Int
|
|
1168
1267
|
-> (Result Http.Error ( Url, ResponseSketch pageData actionData sharedData ) -> Msg userMsg pageData actionData sharedData errorPage)
|
|
1169
1268
|
-> ProgramConfig userMsg userModel route pageData actionData sharedData effect (Msg userMsg pageData actionData sharedData errorPage) errorPage
|
|
1170
1269
|
-> Url
|
|
1171
1270
|
-> Maybe FormData
|
|
1172
1271
|
-> Cmd (Msg userMsg pageData actionData sharedData errorPage)
|
|
1173
|
-
fetchRouteData
|
|
1272
|
+
fetchRouteData transitionKey toMsg config url details =
|
|
1174
1273
|
{-
|
|
1175
1274
|
TODO:
|
|
1176
1275
|
- [X] `toMsg` needs a parameter for the callback Msg so it can pass it on if there is a Redirect response
|
|
@@ -1184,14 +1283,14 @@ fetchRouteData forPageDataReload transitionKey toMsg config url details =
|
|
|
1184
1283
|
|
|
1185
1284
|
-}
|
|
1186
1285
|
let
|
|
1187
|
-
formMethod : Method
|
|
1286
|
+
formMethod : Form.Method
|
|
1188
1287
|
formMethod =
|
|
1189
1288
|
details
|
|
1190
1289
|
|> Maybe.map .method
|
|
1191
|
-
|> Maybe.withDefault Get
|
|
1290
|
+
|> Maybe.withDefault Form.Get
|
|
1192
1291
|
in
|
|
1193
1292
|
Http.request
|
|
1194
|
-
{ method = details |> Maybe.map (.method >>
|
|
1293
|
+
{ method = details |> Maybe.map (.method >> methodToString) |> Maybe.withDefault "GET"
|
|
1195
1294
|
, headers = []
|
|
1196
1295
|
, url =
|
|
1197
1296
|
"/"
|
|
@@ -1209,34 +1308,34 @@ fetchRouteData forPageDataReload transitionKey toMsg config url details =
|
|
|
1209
1308
|
|> String.join "/"
|
|
1210
1309
|
)
|
|
1211
1310
|
++ (case formMethod of
|
|
1212
|
-
Post ->
|
|
1311
|
+
Form.Post ->
|
|
1213
1312
|
"/"
|
|
1214
1313
|
|
|
1215
|
-
Get ->
|
|
1314
|
+
Form.Get ->
|
|
1216
1315
|
details
|
|
1217
|
-
|> Maybe.map
|
|
1316
|
+
|> Maybe.map (.fields >> encodeFormData)
|
|
1218
1317
|
|> Maybe.map (\encoded -> "?" ++ encoded)
|
|
1219
1318
|
|> Maybe.withDefault ""
|
|
1220
1319
|
)
|
|
1221
1320
|
++ (case formMethod of
|
|
1222
1321
|
-- TODO extract this to something unit testable
|
|
1223
1322
|
-- TODO make states mutually exclusive for submissions and direct URL requests (shouldn't be possible to append two query param strings)
|
|
1224
|
-
Post ->
|
|
1323
|
+
Form.Post ->
|
|
1225
1324
|
""
|
|
1226
1325
|
|
|
1227
|
-
Get ->
|
|
1326
|
+
Form.Get ->
|
|
1228
1327
|
url.query
|
|
1229
1328
|
|> Maybe.map (\encoded -> "?" ++ encoded)
|
|
1230
1329
|
|> Maybe.withDefault ""
|
|
1231
1330
|
)
|
|
1232
1331
|
, body =
|
|
1233
1332
|
case formMethod of
|
|
1234
|
-
Post ->
|
|
1333
|
+
Form.Post ->
|
|
1235
1334
|
let
|
|
1236
1335
|
urlEncodedFields : Maybe String
|
|
1237
1336
|
urlEncodedFields =
|
|
1238
1337
|
details
|
|
1239
|
-
|> Maybe.map
|
|
1338
|
+
|> Maybe.map (.fields >> encodeFormData)
|
|
1240
1339
|
in
|
|
1241
1340
|
urlEncodedFields
|
|
1242
1341
|
|> Maybe.map (\encoded -> Http.stringBody "application/x-www-form-urlencoded" encoded)
|
|
@@ -1257,7 +1356,7 @@ fetchRouteData forPageDataReload transitionKey toMsg config url details =
|
|
|
1257
1356
|
Http.NetworkError_ ->
|
|
1258
1357
|
Err Http.NetworkError
|
|
1259
1358
|
|
|
1260
|
-
Http.BadStatus_
|
|
1359
|
+
Http.BadStatus_ _ body ->
|
|
1261
1360
|
body
|
|
1262
1361
|
|> Bytes.Decode.decode config.decodeResponse
|
|
1263
1362
|
|> Result.fromMaybe "Decoding error"
|
|
@@ -1309,7 +1408,7 @@ startNewGetLoad urlToGet toMsg ( model, effect ) =
|
|
|
1309
1408
|
cancelIfStale : Effect userMsg pageData actionData sharedData userEffect errorPage
|
|
1310
1409
|
cancelIfStale =
|
|
1311
1410
|
case model.transition of
|
|
1312
|
-
Just ( transitionKey, Pages.
|
|
1411
|
+
Just ( transitionKey, Pages.Navigation.Loading _ _ ) ->
|
|
1313
1412
|
CancelRequest transitionKey
|
|
1314
1413
|
|
|
1315
1414
|
_ ->
|
|
@@ -1320,22 +1419,22 @@ startNewGetLoad urlToGet toMsg ( model, effect ) =
|
|
|
1320
1419
|
, transition =
|
|
1321
1420
|
( model.nextTransitionKey
|
|
1322
1421
|
, case model.transition of
|
|
1323
|
-
Just (
|
|
1324
|
-
Pages.
|
|
1422
|
+
Just ( _, Pages.Navigation.LoadAfterSubmit submitData _ _ ) ->
|
|
1423
|
+
Pages.Navigation.LoadAfterSubmit
|
|
1325
1424
|
submitData
|
|
1326
|
-
(urlToGet.path |>
|
|
1327
|
-
Pages.
|
|
1425
|
+
(urlToGet.path |> UrlPath.fromString)
|
|
1426
|
+
Pages.Navigation.Load
|
|
1328
1427
|
|
|
1329
|
-
Just (
|
|
1330
|
-
Pages.
|
|
1428
|
+
Just ( _, Pages.Navigation.Submitting submitData ) ->
|
|
1429
|
+
Pages.Navigation.LoadAfterSubmit
|
|
1331
1430
|
submitData
|
|
1332
|
-
(urlToGet.path |>
|
|
1333
|
-
Pages.
|
|
1431
|
+
(urlToGet.path |> UrlPath.fromString)
|
|
1432
|
+
Pages.Navigation.Load
|
|
1334
1433
|
|
|
1335
1434
|
_ ->
|
|
1336
|
-
Pages.
|
|
1337
|
-
(urlToGet.path |>
|
|
1338
|
-
Pages.
|
|
1435
|
+
Pages.Navigation.Loading
|
|
1436
|
+
(urlToGet.path |> UrlPath.fromString)
|
|
1437
|
+
Pages.Navigation.Load
|
|
1339
1438
|
)
|
|
1340
1439
|
|> Just
|
|
1341
1440
|
}
|
|
@@ -1361,9 +1460,9 @@ clearLoadingFetchersAfterDataLoad completedTransitionId model =
|
|
|
1361
1460
|
-- TODO fetchers are never removed from the list. Need to decide how and when to remove them.
|
|
1362
1461
|
--(fetcherState.status /= Pages.Transition.FetcherReloading) || (transitionId > completedTransitionId)
|
|
1363
1462
|
case ( transitionId > completedTransitionId, fetcherState.status ) of
|
|
1364
|
-
( False, Pages.
|
|
1463
|
+
( False, Pages.ConcurrentSubmission.Reloading actionData ) ->
|
|
1365
1464
|
( transitionId
|
|
1366
|
-
, { fetcherState | status = Pages.
|
|
1465
|
+
, { fetcherState | status = Pages.ConcurrentSubmission.Complete actionData }
|
|
1367
1466
|
)
|
|
1368
1467
|
|
|
1369
1468
|
_ ->
|
|
@@ -1399,7 +1498,7 @@ loadDataAndUpdateUrl ( newPageData, newSharedData, newActionData ) maybeUserMsg
|
|
|
1399
1498
|
}
|
|
1400
1499
|
|
|
1401
1500
|
-- TODO use userEffect here?
|
|
1402
|
-
( userModel,
|
|
1501
|
+
( userModel, _ ) =
|
|
1403
1502
|
-- TODO if urlWithoutRedirectResolution is different from the url with redirect resolution, then
|
|
1404
1503
|
-- instead of calling update, call pushUrl (I think?)
|
|
1405
1504
|
-- TODO include user Cmd
|
|
@@ -1474,10 +1573,10 @@ loadDataAndUpdateUrl ( newPageData, newSharedData, newActionData ) maybeUserMsg
|
|
|
1474
1573
|
Err _ ->
|
|
1475
1574
|
{-
|
|
1476
1575
|
When there is an error loading the content.dat, we are either
|
|
1477
|
-
1) in the dev server, and should show the relevant
|
|
1576
|
+
1) in the dev server, and should show the relevant BackendTask error for the page
|
|
1478
1577
|
we're navigating to. This could be done more cleanly, but it's simplest to just
|
|
1479
1578
|
do a fresh page load and use the code path for presenting an error for a fresh page.
|
|
1480
|
-
2) In a production app. That means we had a successful build, so there were no
|
|
1579
|
+
2) In a production app. That means we had a successful build, so there were no BackendTask failures,
|
|
1481
1580
|
so the app must be stale (unless it's in some unexpected state from a bug). In the future,
|
|
1482
1581
|
it probably makes sense to include some sort of hash of the app version we are fetching, match
|
|
1483
1582
|
it with the current version that's running, and perform this logic when we see there is a mismatch.
|
|
@@ -1490,3 +1589,31 @@ loadDataAndUpdateUrl ( newPageData, newSharedData, newActionData ) maybeUserMsg
|
|
|
1490
1589
|
|> Url.toString
|
|
1491
1590
|
|> BrowserLoadUrl
|
|
1492
1591
|
)
|
|
1592
|
+
|
|
1593
|
+
|
|
1594
|
+
methodToString : Form.Method -> String
|
|
1595
|
+
methodToString method =
|
|
1596
|
+
case method of
|
|
1597
|
+
Form.Get ->
|
|
1598
|
+
"GET"
|
|
1599
|
+
|
|
1600
|
+
Form.Post ->
|
|
1601
|
+
"POST"
|
|
1602
|
+
|
|
1603
|
+
|
|
1604
|
+
encodeFormData : List ( String, String ) -> String
|
|
1605
|
+
encodeFormData fields =
|
|
1606
|
+
fields
|
|
1607
|
+
|> List.map
|
|
1608
|
+
(\( name, value ) ->
|
|
1609
|
+
Url.percentEncode name ++ "=" ++ Url.percentEncode value
|
|
1610
|
+
)
|
|
1611
|
+
|> String.join "&"
|
|
1612
|
+
|
|
1613
|
+
|
|
1614
|
+
type alias FormData =
|
|
1615
|
+
{ fields : List ( String, String )
|
|
1616
|
+
, method : Form.Method
|
|
1617
|
+
, action : String
|
|
1618
|
+
, id : Maybe String
|
|
1619
|
+
}
|