elm-pages 3.0.0-beta.4 → 3.0.0-beta.40
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 +10 -1
- package/adapter/netlify.js +207 -0
- package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2678 -2725
- 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 +1447 -342
- package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +17004 -13817
- 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 +1447 -342
- package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +25025 -21739
- 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 +115 -109
- package/generator/src/SharedTemplate.elm +3 -2
- package/generator/src/SiteConfig.elm +3 -2
- package/generator/src/basepath-middleware.js +3 -3
- package/generator/src/build.js +209 -92
- 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 +39 -0
- package/generator/src/copy-dir.js +2 -2
- package/generator/src/dev-server.js +176 -138
- 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 +39 -28
- package/generator/src/render-test.js +109 -0
- package/generator/src/render-worker.js +25 -28
- package/generator/src/render.js +321 -142
- 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 +12 -7
- package/generator/src/vite-utils.js +77 -0
- package/generator/static-code/elm-pages.js +10 -0
- package/generator/static-code/hmr.js +79 -13
- package/generator/template/app/Api.elm +6 -5
- package/generator/template/app/Effect.elm +123 -0
- package/generator/template/app/ErrorPage.elm +37 -6
- package/generator/template/app/Route/Index.elm +17 -10
- package/generator/template/app/Shared.elm +24 -47
- package/generator/template/app/Site.elm +19 -6
- package/generator/template/app/View.elm +1 -8
- package/generator/template/elm-tooling.json +0 -3
- package/generator/template/elm.json +32 -24
- package/generator/template/package.json +10 -4
- package/package.json +30 -27
- package/src/ApiRoute.elm +199 -61
- 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 +537 -0
- package/src/FatalError.elm +90 -0
- package/src/Head.elm +237 -7
- package/src/HtmlPrinter.elm +7 -3
- package/src/Internal/ApiRoute.elm +7 -5
- package/src/PageServerResponse.elm +6 -1
- package/src/Pages/Form.elm +229 -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/Platform/Cli.elm +612 -763
- package/src/Pages/Internal/Platform/CompatibilityKey.elm +6 -0
- 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 +327 -194
- package/src/Pages/Internal/Script.elm +17 -0
- package/src/Pages/Internal/StaticHttpBody.elm +35 -1
- package/src/Pages/Manifest.elm +29 -4
- package/src/Pages/PageUrl.elm +23 -9
- package/src/Pages/ProgramConfig.elm +26 -15
- package/src/Pages/Script.elm +109 -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/Transition.elm +12 -3
- package/src/PagesMsg.elm +82 -0
- package/src/Path.elm +16 -19
- package/src/QueryParams.elm +21 -172
- package/src/RequestsAndPending.elm +37 -20
- package/src/Result/Extra.elm +26 -0
- package/src/Scaffold/Form.elm +546 -0
- package/src/Scaffold/Route.elm +1402 -0
- package/src/Server/Request.elm +73 -72
- package/src/Server/Session.elm +62 -42
- package/src/Server/SetCookie.elm +12 -4
- package/src/Stub.elm +53 -0
- package/src/Test/Html/Internal/ElmHtml/ToString.elm +8 -9
- 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 -538
- 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 -800
- package/src/Pages/Internal/Form.elm +0 -17
- package/src/Pages/Msg.elm +0 -79
|
@@ -20,8 +20,7 @@ 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
|
|
@@ -30,14 +29,14 @@ import Json.Encode
|
|
|
30
29
|
import Pages.ContentCache as ContentCache
|
|
31
30
|
import Pages.Fetcher
|
|
32
31
|
import Pages.Flags
|
|
33
|
-
import Pages.
|
|
32
|
+
import Pages.Internal.Msg
|
|
34
33
|
import Pages.Internal.NotFoundReason exposing (NotFoundReason)
|
|
35
34
|
import Pages.Internal.ResponseSketch as ResponseSketch exposing (ResponseSketch)
|
|
36
35
|
import Pages.Internal.String as String
|
|
37
|
-
import Pages.Msg
|
|
38
36
|
import Pages.ProgramConfig exposing (ProgramConfig)
|
|
39
37
|
import Pages.StaticHttpRequest as StaticHttpRequest
|
|
40
38
|
import Pages.Transition
|
|
39
|
+
import PagesMsg exposing (PagesMsg)
|
|
41
40
|
import Path exposing (Path)
|
|
42
41
|
import QueryParams
|
|
43
42
|
import Task
|
|
@@ -45,11 +44,6 @@ import Time
|
|
|
45
44
|
import Url exposing (Url)
|
|
46
45
|
|
|
47
46
|
|
|
48
|
-
type Transition
|
|
49
|
-
= Loading Int Path
|
|
50
|
-
| Submitting FormData
|
|
51
|
-
|
|
52
|
-
|
|
53
47
|
{-| -}
|
|
54
48
|
type alias Program userModel userMsg pageData actionData sharedData errorPage =
|
|
55
49
|
Platform.Program Flags (Model userModel pageData actionData sharedData) (Msg userMsg pageData actionData sharedData errorPage)
|
|
@@ -58,7 +52,7 @@ type alias Program userModel userMsg pageData actionData sharedData errorPage =
|
|
|
58
52
|
mainView :
|
|
59
53
|
ProgramConfig userMsg userModel route pageData actionData sharedData effect (Msg userMsg pageData actionData sharedData errorPage) errorPage
|
|
60
54
|
-> Model userModel pageData actionData sharedData
|
|
61
|
-
-> { title : String, body : List (Html (
|
|
55
|
+
-> { title : String, body : List (Html (PagesMsg userMsg)) }
|
|
62
56
|
mainView config model =
|
|
63
57
|
case model.notFound of
|
|
64
58
|
Just info ->
|
|
@@ -230,7 +224,7 @@ init config flags url key =
|
|
|
230
224
|
, host = url.host
|
|
231
225
|
, port_ = url.port_
|
|
232
226
|
, path = pagePath
|
|
233
|
-
, query = url.query |> Maybe.map QueryParams.fromString
|
|
227
|
+
, query = url.query |> Maybe.map QueryParams.fromString |> Maybe.withDefault Dict.empty
|
|
234
228
|
, fragment = url.fragment
|
|
235
229
|
}
|
|
236
230
|
}
|
|
@@ -274,7 +268,7 @@ init config flags url key =
|
|
|
274
268
|
, url = url
|
|
275
269
|
, currentPath = url.path
|
|
276
270
|
, pageData = Err "Not found"
|
|
277
|
-
, ariaNavigationAnnouncement = "
|
|
271
|
+
, ariaNavigationAnnouncement = "Page Not Found" -- TODO use error page title for announcement?
|
|
278
272
|
, userFlags = flags
|
|
279
273
|
, notFound = Just info
|
|
280
274
|
, transition = Nothing
|
|
@@ -313,16 +307,23 @@ init config flags url key =
|
|
|
313
307
|
type Msg userMsg pageData actionData sharedData errorPage
|
|
314
308
|
= LinkClicked Browser.UrlRequest
|
|
315
309
|
| UrlChanged Url
|
|
316
|
-
|
|
317
|
-
|
|
|
310
|
+
-- TODO rename to PagesMsg
|
|
311
|
+
| UserMsg (PagesMsg userMsg)
|
|
312
|
+
--| SetField { formId : String, name : String, value : String }
|
|
313
|
+
| FormMsg (Form.Msg (Msg userMsg pageData actionData sharedData errorPage))
|
|
318
314
|
| UpdateCacheAndUrlNew Bool Url (Maybe userMsg) (Result Http.Error ( Url, ResponseSketch pageData actionData sharedData ))
|
|
319
|
-
| FetcherComplete Bool String Int (Result Http.Error ( Maybe userMsg,
|
|
315
|
+
| FetcherComplete Bool String Int (Result Http.Error ( Maybe userMsg, ActionDataOrRedirect actionData ))
|
|
320
316
|
| FetcherStarted String Int FormData Time.Posix
|
|
321
317
|
| PageScrollComplete
|
|
322
318
|
| HotReloadCompleteNew Bytes
|
|
323
319
|
| 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
320
|
|
|
325
321
|
|
|
322
|
+
type ActionDataOrRedirect action
|
|
323
|
+
= ActionResponse (Maybe action)
|
|
324
|
+
| RedirectResponse String
|
|
325
|
+
|
|
326
|
+
|
|
326
327
|
{-| -}
|
|
327
328
|
type alias Model userModel pageData actionData sharedData =
|
|
328
329
|
{ key : Maybe Browser.Navigation.Key
|
|
@@ -342,7 +343,7 @@ type alias Model userModel pageData actionData sharedData =
|
|
|
342
343
|
, transition : Maybe ( Int, Pages.Transition.Transition )
|
|
343
344
|
, nextTransitionKey : Int
|
|
344
345
|
, inFlightFetchers : Dict String ( Int, Pages.Transition.FetcherState actionData )
|
|
345
|
-
, pageFormState :
|
|
346
|
+
, pageFormState : Form.Model
|
|
346
347
|
, pendingRedirect : Bool
|
|
347
348
|
, pendingData : Maybe ( pageData, sharedData, Maybe actionData )
|
|
348
349
|
}
|
|
@@ -361,6 +362,7 @@ type Effect userMsg pageData actionData sharedData userEffect errorPage
|
|
|
361
362
|
| Batch (List (Effect userMsg pageData actionData sharedData userEffect errorPage))
|
|
362
363
|
| UserCmd userEffect
|
|
363
364
|
| CancelRequest Int
|
|
365
|
+
| RunCmd (Cmd (Msg userMsg pageData actionData sharedData errorPage))
|
|
364
366
|
|
|
365
367
|
|
|
366
368
|
{-| -}
|
|
@@ -371,6 +373,18 @@ update :
|
|
|
371
373
|
-> ( Model userModel pageData actionData sharedData, Effect userMsg pageData actionData sharedData userEffect errorPage )
|
|
372
374
|
update config appMsg model =
|
|
373
375
|
case appMsg of
|
|
376
|
+
FormMsg formMsg ->
|
|
377
|
+
let
|
|
378
|
+
-- TODO trigger formCmd
|
|
379
|
+
( newModel, formCmd ) =
|
|
380
|
+
Form.update formMsg model.pageFormState
|
|
381
|
+
in
|
|
382
|
+
( { model
|
|
383
|
+
| pageFormState = newModel
|
|
384
|
+
}
|
|
385
|
+
, RunCmd formCmd
|
|
386
|
+
)
|
|
387
|
+
|
|
374
388
|
LinkClicked urlRequest ->
|
|
375
389
|
case urlRequest of
|
|
376
390
|
Browser.Internal url ->
|
|
@@ -396,11 +410,6 @@ update config appMsg model =
|
|
|
396
410
|
, BrowserLoadUrl href
|
|
397
411
|
)
|
|
398
412
|
|
|
399
|
-
SetField info ->
|
|
400
|
-
( { model | pageFormState = Pages.FormState.setField info model.pageFormState }
|
|
401
|
-
, NoEffect
|
|
402
|
-
)
|
|
403
|
-
|
|
404
413
|
UrlChanged url ->
|
|
405
414
|
case model.pendingData of
|
|
406
415
|
Just ( newPageData, newSharedData, newActionData ) ->
|
|
@@ -414,7 +423,7 @@ update config appMsg model =
|
|
|
414
423
|
model
|
|
415
424
|
|
|
416
425
|
Nothing ->
|
|
417
|
-
if model.url.path == url.path then
|
|
426
|
+
if model.url.path == url.path && model.url.query == url.query then
|
|
418
427
|
( { model
|
|
419
428
|
| -- update the URL in case query params or fragment changed
|
|
420
429
|
url = url
|
|
@@ -423,46 +432,57 @@ update config appMsg model =
|
|
|
423
432
|
)
|
|
424
433
|
|
|
425
434
|
else
|
|
426
|
-
(
|
|
427
|
-
| url = url
|
|
428
|
-
}
|
|
435
|
+
( model
|
|
429
436
|
, NoEffect
|
|
430
437
|
)
|
|
431
438
|
-- TODO is it reasonable to always re-fetch route data if you re-navigate to the current route? Might be a good
|
|
432
439
|
-- parallel to the browser behavior
|
|
433
440
|
|> startNewGetLoad url (UpdateCacheAndUrlNew True url Nothing)
|
|
434
441
|
|
|
435
|
-
FetcherComplete
|
|
442
|
+
FetcherComplete _ fetcherKey _ userMsgResult ->
|
|
436
443
|
case userMsgResult of
|
|
437
|
-
Ok ( userMsg,
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
model
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
(
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
444
|
+
Ok ( userMsg, actionOrRedirect ) ->
|
|
445
|
+
case actionOrRedirect of
|
|
446
|
+
ActionResponse maybeFetcherDoneActionData ->
|
|
447
|
+
( { model
|
|
448
|
+
| inFlightFetchers =
|
|
449
|
+
model.inFlightFetchers
|
|
450
|
+
|> Dict.update fetcherKey
|
|
451
|
+
(Maybe.map
|
|
452
|
+
(\( transitionId, fetcherState ) ->
|
|
453
|
+
( transitionId
|
|
454
|
+
, { fetcherState
|
|
455
|
+
| status =
|
|
456
|
+
maybeFetcherDoneActionData
|
|
457
|
+
|> Maybe.map Pages.Transition.FetcherReloading
|
|
458
|
+
-- TODO remove this bad default, FetcherSubmitting is incorrect
|
|
459
|
+
|> Maybe.withDefault Pages.Transition.FetcherSubmitting
|
|
460
|
+
}
|
|
461
|
+
)
|
|
462
|
+
)
|
|
452
463
|
)
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
464
|
+
}
|
|
465
|
+
, NoEffect
|
|
466
|
+
)
|
|
467
|
+
|> (case userMsg of
|
|
468
|
+
Just justUserMsg ->
|
|
469
|
+
performUserMsg justUserMsg config
|
|
470
|
+
|
|
471
|
+
Nothing ->
|
|
472
|
+
identity
|
|
473
|
+
)
|
|
474
|
+
|> startNewGetLoad (currentUrlWithPath model.url.path model) (UpdateCacheAndUrlNew False model.url Nothing)
|
|
475
|
+
|
|
476
|
+
RedirectResponse redirectTo ->
|
|
477
|
+
( { model
|
|
478
|
+
| inFlightFetchers =
|
|
479
|
+
model.inFlightFetchers
|
|
480
|
+
|> Dict.remove fetcherKey
|
|
481
|
+
, pendingRedirect = True
|
|
482
|
+
}
|
|
483
|
+
, NoEffect
|
|
484
|
+
)
|
|
485
|
+
|> startNewGetLoad (currentUrlWithPath redirectTo model) (UpdateCacheAndUrlNew False model.url Nothing)
|
|
466
486
|
|
|
467
487
|
Err _ ->
|
|
468
488
|
-- TODO how to handle error?
|
|
@@ -480,74 +500,70 @@ update config appMsg model =
|
|
|
480
500
|
|
|
481
501
|
UserMsg userMsg_ ->
|
|
482
502
|
case userMsg_ of
|
|
483
|
-
Pages.Msg.UserMsg userMsg ->
|
|
503
|
+
Pages.Internal.Msg.UserMsg userMsg ->
|
|
484
504
|
( model, NoEffect )
|
|
485
505
|
|> performUserMsg userMsg config
|
|
486
506
|
|
|
487
|
-
Pages.Msg.Submit fields ->
|
|
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
|
-
|
|
524
|
-
|
|
525
|
-
( { model | nextTransitionKey = model.nextTransitionKey + 1 }
|
|
526
|
-
, SubmitFetcher fetcherKey model.nextTransitionKey fields
|
|
527
|
-
)
|
|
528
|
-
|> (case maybeUserMsg of
|
|
529
|
-
Just justUserMsg ->
|
|
530
|
-
performUserMsg justUserMsg config
|
|
507
|
+
Pages.Internal.Msg.Submit fields ->
|
|
508
|
+
if fields.valid then
|
|
509
|
+
let
|
|
510
|
+
payload : { fields : List ( String, String ), method : Form.Method, action : String, id : Maybe String }
|
|
511
|
+
payload =
|
|
512
|
+
{ fields = fields.fields
|
|
513
|
+
, method = fields.method
|
|
514
|
+
, action = fields.action
|
|
515
|
+
, id = Just fields.id
|
|
516
|
+
}
|
|
517
|
+
in
|
|
518
|
+
if fields.useFetcher then
|
|
519
|
+
( { model | nextTransitionKey = model.nextTransitionKey + 1 }
|
|
520
|
+
, SubmitFetcher fields.id model.nextTransitionKey payload
|
|
521
|
+
)
|
|
522
|
+
|> (case fields.msg of
|
|
523
|
+
Just justUserMsg ->
|
|
524
|
+
performUserMsg justUserMsg config
|
|
525
|
+
|
|
526
|
+
Nothing ->
|
|
527
|
+
identity
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
else
|
|
531
|
+
( { model
|
|
532
|
+
-- TODO should I setSubmitAttempted here, too?
|
|
533
|
+
| transition =
|
|
534
|
+
Just
|
|
535
|
+
( -- TODO remove hardcoded number
|
|
536
|
+
-1
|
|
537
|
+
, Pages.Transition.Submitting payload
|
|
538
|
+
)
|
|
539
|
+
}
|
|
540
|
+
, Submit payload
|
|
541
|
+
)
|
|
542
|
+
|> (case fields.msg of
|
|
543
|
+
Just justUserMsg ->
|
|
544
|
+
performUserMsg justUserMsg config
|
|
531
545
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
546
|
+
Nothing ->
|
|
547
|
+
identity
|
|
548
|
+
)
|
|
535
549
|
|
|
536
550
|
else
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
model.pageFormState
|
|
540
|
-
|> Pages.FormState.setSubmitAttempted fetcherKey
|
|
541
|
-
}
|
|
542
|
-
, NoEffect
|
|
543
|
-
)
|
|
551
|
+
-- TODO should the user msg still be run if the form is invalid?
|
|
552
|
+
( model, NoEffect )
|
|
544
553
|
|
|
545
|
-
Pages.Msg.
|
|
554
|
+
Pages.Internal.Msg.FormMsg formMsg ->
|
|
546
555
|
-- TODO when init is called for a new page, also need to clear out client-side `pageFormState`
|
|
547
|
-
|
|
548
|
-
|
|
556
|
+
let
|
|
557
|
+
( formModel, formCmd ) =
|
|
558
|
+
Form.update formMsg model.pageFormState
|
|
559
|
+
in
|
|
560
|
+
( { model | pageFormState = formModel }
|
|
561
|
+
, RunCmd (Cmd.map UserMsg formCmd)
|
|
549
562
|
)
|
|
550
563
|
|
|
564
|
+
Pages.Internal.Msg.NoOp ->
|
|
565
|
+
( model, NoEffect )
|
|
566
|
+
|
|
551
567
|
UpdateCacheAndUrlNew scrollToTopWhenDone urlWithoutRedirectResolution maybeUserMsg updateResult ->
|
|
552
568
|
-- TODO remove all fetchers that are in the state `FetcherReloading` here -- I think that's the right logic?
|
|
553
569
|
case
|
|
@@ -605,27 +621,32 @@ update config appMsg model =
|
|
|
605
621
|
, actionData = newActionData
|
|
606
622
|
}
|
|
607
623
|
|
|
608
|
-
( userModel,
|
|
624
|
+
( userModel, userEffect ) =
|
|
609
625
|
-- TODO if urlWithoutRedirectResolution is different from the url with redirect resolution, then
|
|
610
626
|
-- instead of calling update, call pushUrl (I think?)
|
|
611
627
|
-- TODO include user Cmd
|
|
612
|
-
|
|
613
|
-
(
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
628
|
+
if stayingOnSamePath then
|
|
629
|
+
( previousPageData.userModel, NoEffect )
|
|
630
|
+
|
|
631
|
+
else
|
|
632
|
+
config.update model.pageFormState
|
|
633
|
+
(model.inFlightFetchers |> toFetcherState)
|
|
634
|
+
(model.transition |> Maybe.map Tuple.second)
|
|
635
|
+
newSharedData
|
|
636
|
+
newPageData
|
|
637
|
+
model.key
|
|
638
|
+
(config.onPageChange
|
|
639
|
+
{ protocol = model.url.protocol
|
|
640
|
+
, host = model.url.host
|
|
641
|
+
, port_ = model.url.port_
|
|
642
|
+
, path = urlPathToPath urlWithoutRedirectResolution
|
|
643
|
+
, query = urlWithoutRedirectResolution.query
|
|
644
|
+
, fragment = urlWithoutRedirectResolution.fragment
|
|
645
|
+
, metadata = config.urlToRoute urlWithoutRedirectResolution
|
|
646
|
+
}
|
|
647
|
+
)
|
|
648
|
+
previousPageData.userModel
|
|
649
|
+
|> Tuple.mapSecond UserCmd
|
|
629
650
|
|
|
630
651
|
updatedModel : Model userModel pageData actionData sharedData
|
|
631
652
|
updatedModel =
|
|
@@ -656,10 +677,13 @@ update config appMsg model =
|
|
|
656
677
|
, currentPath = newUrl.path
|
|
657
678
|
}
|
|
658
679
|
, if not stayingOnSamePath && scrollToTopWhenDone then
|
|
659
|
-
|
|
680
|
+
Batch
|
|
681
|
+
[ ScrollToTop
|
|
682
|
+
, userEffect
|
|
683
|
+
]
|
|
660
684
|
|
|
661
685
|
else
|
|
662
|
-
|
|
686
|
+
userEffect
|
|
663
687
|
)
|
|
664
688
|
|> (case maybeUserMsg of
|
|
665
689
|
Just userMsg ->
|
|
@@ -679,10 +703,10 @@ update config appMsg model =
|
|
|
679
703
|
Err _ ->
|
|
680
704
|
{-
|
|
681
705
|
When there is an error loading the content.dat, we are either
|
|
682
|
-
1) in the dev server, and should show the relevant
|
|
706
|
+
1) in the dev server, and should show the relevant BackendTask error for the page
|
|
683
707
|
we're navigating to. This could be done more cleanly, but it's simplest to just
|
|
684
708
|
do a fresh page load and use the code path for presenting an error for a fresh page.
|
|
685
|
-
2) In a production app. That means we had a successful build, so there were no
|
|
709
|
+
2) In a production app. That means we had a successful build, so there were no BackendTask failures,
|
|
686
710
|
so the app must be stale (unless it's in some unexpected state from a bug). In the future,
|
|
687
711
|
it probably makes sense to include some sort of hash of the app version we are fetching, match
|
|
688
712
|
it with the current version that's running, and perform this logic when we see there is a mismatch.
|
|
@@ -745,7 +769,86 @@ update config appMsg model =
|
|
|
745
769
|
_ ->
|
|
746
770
|
( model, NoEffect )
|
|
747
771
|
)
|
|
748
|
-
|> Result.withDefault
|
|
772
|
+
|> Result.withDefault
|
|
773
|
+
(let
|
|
774
|
+
pageDataResult : Maybe (InitKind sharedData pageData actionData errorPage)
|
|
775
|
+
pageDataResult =
|
|
776
|
+
case Bytes.Decode.decode config.decodeResponse pageDataBytes of
|
|
777
|
+
Just (ResponseSketch.RenderPage _ _) ->
|
|
778
|
+
Nothing
|
|
779
|
+
|
|
780
|
+
Just (ResponseSketch.HotUpdate pageData shared actionData) ->
|
|
781
|
+
OkPage shared pageData actionData
|
|
782
|
+
|> Just
|
|
783
|
+
|
|
784
|
+
Just (ResponseSketch.NotFound notFound) ->
|
|
785
|
+
NotFound notFound
|
|
786
|
+
|> Just
|
|
787
|
+
|
|
788
|
+
_ ->
|
|
789
|
+
Nothing
|
|
790
|
+
in
|
|
791
|
+
case pageDataResult of
|
|
792
|
+
Just (OkPage sharedData pageData actionData) ->
|
|
793
|
+
let
|
|
794
|
+
urls : { currentUrl : Url, basePath : List String }
|
|
795
|
+
urls =
|
|
796
|
+
{ currentUrl = model.url
|
|
797
|
+
, basePath = config.basePath
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
pagePath : Path
|
|
801
|
+
pagePath =
|
|
802
|
+
urlsToPagePath urls
|
|
803
|
+
|
|
804
|
+
userFlags : Pages.Flags.Flags
|
|
805
|
+
userFlags =
|
|
806
|
+
model.userFlags
|
|
807
|
+
|> Decode.decodeValue
|
|
808
|
+
(Decode.field "userFlags" Decode.value)
|
|
809
|
+
|> Result.withDefault Json.Encode.null
|
|
810
|
+
|> Pages.Flags.BrowserFlags
|
|
811
|
+
|
|
812
|
+
( userModel, userCmd ) =
|
|
813
|
+
Just
|
|
814
|
+
{ path =
|
|
815
|
+
{ path = pagePath
|
|
816
|
+
, query = model.url.query
|
|
817
|
+
, fragment = model.url.fragment
|
|
818
|
+
}
|
|
819
|
+
, metadata = config.urlToRoute model.url
|
|
820
|
+
, pageUrl =
|
|
821
|
+
Just
|
|
822
|
+
{ protocol = model.url.protocol
|
|
823
|
+
, host = model.url.host
|
|
824
|
+
, port_ = model.url.port_
|
|
825
|
+
, path = pagePath
|
|
826
|
+
, query = model.url.query |> Maybe.map QueryParams.fromString |> Maybe.withDefault Dict.empty
|
|
827
|
+
, fragment = model.url.fragment
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|> config.init userFlags sharedData pageData actionData
|
|
831
|
+
|
|
832
|
+
cmd : Effect userMsg pageData actionData sharedData userEffect errorPage
|
|
833
|
+
cmd =
|
|
834
|
+
UserCmd userCmd
|
|
835
|
+
in
|
|
836
|
+
( { model
|
|
837
|
+
| pageData =
|
|
838
|
+
Ok
|
|
839
|
+
{ userModel = userModel
|
|
840
|
+
, sharedData = sharedData
|
|
841
|
+
, pageData = pageData
|
|
842
|
+
, actionData = actionData
|
|
843
|
+
}
|
|
844
|
+
, notFound = Nothing
|
|
845
|
+
}
|
|
846
|
+
, cmd
|
|
847
|
+
)
|
|
848
|
+
|
|
849
|
+
_ ->
|
|
850
|
+
( model, NoEffect )
|
|
851
|
+
)
|
|
749
852
|
|
|
750
853
|
FetcherStarted fetcherKey transitionId fetcherData initiatedAt ->
|
|
751
854
|
( { model
|
|
@@ -766,7 +869,7 @@ update config appMsg model =
|
|
|
766
869
|
toFetcherState : Dict String ( Int, Pages.Transition.FetcherState actionData ) -> Dict String (Pages.Transition.FetcherState actionData)
|
|
767
870
|
toFetcherState inFlightFetchers =
|
|
768
871
|
inFlightFetchers
|
|
769
|
-
|> Dict.map (\_ (
|
|
872
|
+
|> Dict.map (\_ ( _, fetcherState ) -> fetcherState)
|
|
770
873
|
|
|
771
874
|
|
|
772
875
|
performUserMsg :
|
|
@@ -800,6 +903,9 @@ perform config model effect =
|
|
|
800
903
|
NoEffect ->
|
|
801
904
|
Cmd.none
|
|
802
905
|
|
|
906
|
+
RunCmd cmd ->
|
|
907
|
+
cmd
|
|
908
|
+
|
|
803
909
|
Batch effects ->
|
|
804
910
|
effects
|
|
805
911
|
|> List.map (perform config model)
|
|
@@ -828,10 +934,10 @@ perform config model effect =
|
|
|
828
934
|
|> Maybe.withDefault Cmd.none
|
|
829
935
|
|
|
830
936
|
FetchPageData transitionKey maybeRequestInfo url toMsg ->
|
|
831
|
-
fetchRouteData
|
|
937
|
+
fetchRouteData transitionKey toMsg config url maybeRequestInfo
|
|
832
938
|
|
|
833
939
|
Submit fields ->
|
|
834
|
-
if fields.method == Get then
|
|
940
|
+
if fields.method == Form.Get then
|
|
835
941
|
model.key
|
|
836
942
|
|> Maybe.map (\key -> Browser.Navigation.pushUrl key (appendFormQueryParams fields))
|
|
837
943
|
|> Maybe.withDefault Cmd.none
|
|
@@ -843,7 +949,7 @@ perform config model effect =
|
|
|
843
949
|
-- TODO add optional path parameter to Submit variant to allow submitting to other routes
|
|
844
950
|
model.url
|
|
845
951
|
in
|
|
846
|
-
fetchRouteData
|
|
952
|
+
fetchRouteData -1 (UpdateCacheAndUrlNew False model.url Nothing) config urlToSubmitTo (Just fields)
|
|
847
953
|
|
|
848
954
|
SubmitFetcher fetcherKey transitionId formData ->
|
|
849
955
|
startFetcher2 config False fetcherKey transitionId formData model
|
|
@@ -863,7 +969,7 @@ perform config model effect =
|
|
|
863
969
|
|> config.perform
|
|
864
970
|
{ fetchRouteData =
|
|
865
971
|
\fetchInfo ->
|
|
866
|
-
fetchRouteData
|
|
972
|
+
fetchRouteData
|
|
867
973
|
-1
|
|
868
974
|
(prepare fetchInfo.toMsg)
|
|
869
975
|
config
|
|
@@ -873,15 +979,19 @@ perform config model effect =
|
|
|
873
979
|
---- TODO map the Msg with the wrapper type (like in the PR branch)
|
|
874
980
|
, submit =
|
|
875
981
|
\fetchInfo ->
|
|
876
|
-
fetchRouteData
|
|
982
|
+
fetchRouteData -1 (prepare fetchInfo.toMsg) config (fetchInfo.values.action |> Url.fromString |> Maybe.withDefault model.url) (Just fetchInfo.values)
|
|
877
983
|
, runFetcher =
|
|
878
984
|
\(Pages.Fetcher.Fetcher options) ->
|
|
879
985
|
-- TODO need to get the fetcherId here
|
|
880
986
|
-- TODO need to increment and pass in the transitionId
|
|
881
987
|
startFetcher "TODO" -1 options model
|
|
882
|
-
, fromPageMsg = Pages.Msg.UserMsg >> UserMsg
|
|
988
|
+
, fromPageMsg = Pages.Internal.Msg.UserMsg >> UserMsg
|
|
883
989
|
, key = key
|
|
884
|
-
, setField =
|
|
990
|
+
, setField =
|
|
991
|
+
\_ ->
|
|
992
|
+
--Task.succeed (SetField info) |> Task.perform identity
|
|
993
|
+
-- TODO
|
|
994
|
+
Cmd.none
|
|
885
995
|
}
|
|
886
996
|
|
|
887
997
|
Nothing ->
|
|
@@ -896,21 +1006,12 @@ startFetcher fetcherKey transitionId options model =
|
|
|
896
1006
|
let
|
|
897
1007
|
encodedBody : String
|
|
898
1008
|
encodedBody =
|
|
899
|
-
|
|
900
|
-
{ fields = options.fields
|
|
901
|
-
|
|
902
|
-
-- TODO remove hardcoding
|
|
903
|
-
, action = ""
|
|
1009
|
+
encodeFormData options.fields
|
|
904
1010
|
|
|
905
|
-
|
|
906
|
-
, method = Post
|
|
907
|
-
, id = Nothing
|
|
908
|
-
}
|
|
909
|
-
|
|
910
|
-
formData : { method : Method, action : String, fields : List ( String, String ), id : Maybe String }
|
|
1011
|
+
formData : { method : Form.Method, action : String, fields : List ( String, String ), id : Maybe String }
|
|
911
1012
|
formData =
|
|
912
1013
|
{ -- TODO remove hardcoding
|
|
913
|
-
method = Get
|
|
1014
|
+
method = Form.Get
|
|
914
1015
|
|
|
915
1016
|
-- TODO pass FormData directly
|
|
916
1017
|
, action = options.url |> Maybe.withDefault model.url.path
|
|
@@ -927,10 +1028,10 @@ startFetcher fetcherKey transitionId options model =
|
|
|
927
1028
|
Http.expectBytesResponse (FetcherComplete False fetcherKey model.nextTransitionKey)
|
|
928
1029
|
(\bytes ->
|
|
929
1030
|
case bytes of
|
|
930
|
-
Http.GoodStatus_
|
|
1031
|
+
Http.GoodStatus_ _ bytesBody ->
|
|
931
1032
|
( options.decoder (Ok bytesBody)
|
|
932
1033
|
|> Just
|
|
933
|
-
, Nothing
|
|
1034
|
+
, ActionResponse Nothing
|
|
934
1035
|
)
|
|
935
1036
|
|> Ok
|
|
936
1037
|
|
|
@@ -943,7 +1044,7 @@ startFetcher fetcherKey transitionId options model =
|
|
|
943
1044
|
Http.NetworkError_ ->
|
|
944
1045
|
Err <| Http.NetworkError
|
|
945
1046
|
|
|
946
|
-
Http.BadStatus_ metadata
|
|
1047
|
+
Http.BadStatus_ metadata _ ->
|
|
947
1048
|
Err <| Http.BadStatus metadata.statusCode
|
|
948
1049
|
)
|
|
949
1050
|
, tracker = Nothing
|
|
@@ -968,13 +1069,13 @@ startFetcher2 config fromPageReload fetcherKey transitionId formData model =
|
|
|
968
1069
|
let
|
|
969
1070
|
encodedBody : String
|
|
970
1071
|
encodedBody =
|
|
971
|
-
|
|
1072
|
+
encodeFormData formData.fields
|
|
972
1073
|
in
|
|
973
1074
|
-- TODO make sure that `actionData` isn't updated in Model for fetchers
|
|
974
1075
|
Cmd.batch
|
|
975
1076
|
[ cancelStaleFetchers model
|
|
976
1077
|
, case Dict.get fetcherKey model.inFlightFetchers of
|
|
977
|
-
Just ( inFlightId,
|
|
1078
|
+
Just ( inFlightId, _ ) ->
|
|
978
1079
|
Http.cancel (String.fromInt inFlightId)
|
|
979
1080
|
|
|
980
1081
|
Nothing ->
|
|
@@ -985,22 +1086,26 @@ startFetcher2 config fromPageReload fetcherKey transitionId formData model =
|
|
|
985
1086
|
Http.expectBytesResponse (FetcherComplete fromPageReload fetcherKey model.nextTransitionKey)
|
|
986
1087
|
(\bytes ->
|
|
987
1088
|
case bytes of
|
|
988
|
-
Http.GoodStatus_
|
|
1089
|
+
Http.GoodStatus_ _ bytesBody ->
|
|
989
1090
|
let
|
|
990
|
-
decodedAction :
|
|
1091
|
+
decodedAction : ActionDataOrRedirect actionData
|
|
991
1092
|
decodedAction =
|
|
992
1093
|
case Bytes.Decode.decode config.decodeResponse bytesBody of
|
|
1094
|
+
-- @@@
|
|
1095
|
+
Just (ResponseSketch.Redirect redirectTo) ->
|
|
1096
|
+
RedirectResponse redirectTo
|
|
1097
|
+
|
|
993
1098
|
Just (ResponseSketch.RenderPage _ maybeAction) ->
|
|
994
|
-
maybeAction
|
|
1099
|
+
ActionResponse maybeAction
|
|
995
1100
|
|
|
996
|
-
Just (ResponseSketch.HotUpdate
|
|
997
|
-
maybeAction
|
|
1101
|
+
Just (ResponseSketch.HotUpdate _ _ maybeAction) ->
|
|
1102
|
+
ActionResponse maybeAction
|
|
998
1103
|
|
|
999
|
-
Just (ResponseSketch.NotFound
|
|
1000
|
-
Nothing
|
|
1104
|
+
Just (ResponseSketch.NotFound _) ->
|
|
1105
|
+
ActionResponse Nothing
|
|
1001
1106
|
|
|
1002
1107
|
_ ->
|
|
1003
|
-
Nothing
|
|
1108
|
+
ActionResponse Nothing
|
|
1004
1109
|
in
|
|
1005
1110
|
-- TODO maybe have an optional way to pass the bytes through?
|
|
1006
1111
|
Ok ( Nothing, decodedAction )
|
|
@@ -1014,7 +1119,7 @@ startFetcher2 config fromPageReload fetcherKey transitionId formData model =
|
|
|
1014
1119
|
Http.NetworkError_ ->
|
|
1015
1120
|
Err <| Http.NetworkError
|
|
1016
1121
|
|
|
1017
|
-
Http.BadStatus_ metadata
|
|
1122
|
+
Http.BadStatus_ metadata _ ->
|
|
1018
1123
|
Err <| Http.BadStatus metadata.statusCode
|
|
1019
1124
|
)
|
|
1020
1125
|
, tracker = Just (String.fromInt transitionId)
|
|
@@ -1025,7 +1130,7 @@ startFetcher2 config fromPageReload fetcherKey transitionId formData model =
|
|
|
1025
1130
|
|
|
1026
1131
|
-- TODO use formData.method to do either query params or POST body
|
|
1027
1132
|
, url = formData.action |> Url.fromString |> Maybe.map (\{ path } -> Path.join [ path, "content.dat" ] |> Path.toAbsolute) |> Maybe.withDefault "/"
|
|
1028
|
-
, method = formData.method |>
|
|
1133
|
+
, method = formData.method |> methodToString
|
|
1029
1134
|
, timeout = Nothing
|
|
1030
1135
|
}
|
|
1031
1136
|
]
|
|
@@ -1036,7 +1141,7 @@ cancelStaleFetchers model =
|
|
|
1036
1141
|
model.inFlightFetchers
|
|
1037
1142
|
|> Dict.toList
|
|
1038
1143
|
|> List.filterMap
|
|
1039
|
-
(\(
|
|
1144
|
+
(\( _, ( id, fetcher ) ) ->
|
|
1040
1145
|
case fetcher.status of
|
|
1041
1146
|
Pages.Transition.FetcherReloading _ ->
|
|
1042
1147
|
Http.cancel (String.fromInt id)
|
|
@@ -1059,10 +1164,10 @@ appendFormQueryParams fields =
|
|
|
1059
1164
|
|> Maybe.withDefault "/"
|
|
1060
1165
|
)
|
|
1061
1166
|
++ (case fields.method of
|
|
1062
|
-
Get ->
|
|
1063
|
-
"?" ++
|
|
1167
|
+
Form.Get ->
|
|
1168
|
+
"?" ++ encodeFormData fields.fields
|
|
1064
1169
|
|
|
1065
|
-
Post ->
|
|
1170
|
+
Form.Post ->
|
|
1066
1171
|
""
|
|
1067
1172
|
)
|
|
1068
1173
|
|
|
@@ -1104,7 +1209,7 @@ application config =
|
|
|
1104
1209
|
[ config.subscriptions (model.url |> config.urlToRoute)
|
|
1105
1210
|
(urls.currentUrl |> config.urlToRoute |> config.routeToPath |> Path.join)
|
|
1106
1211
|
pageData.userModel
|
|
1107
|
-
|> Sub.map (Pages.Msg.UserMsg >> UserMsg)
|
|
1212
|
+
|> Sub.map (Pages.Internal.Msg.UserMsg >> UserMsg)
|
|
1108
1213
|
, config.hotReloadData
|
|
1109
1214
|
|> Sub.map HotReloadCompleteNew
|
|
1110
1215
|
]
|
|
@@ -1157,14 +1262,13 @@ urlPathToPath urls =
|
|
|
1157
1262
|
|
|
1158
1263
|
|
|
1159
1264
|
fetchRouteData :
|
|
1160
|
-
|
|
1161
|
-
-> Int
|
|
1265
|
+
Int
|
|
1162
1266
|
-> (Result Http.Error ( Url, ResponseSketch pageData actionData sharedData ) -> Msg userMsg pageData actionData sharedData errorPage)
|
|
1163
1267
|
-> ProgramConfig userMsg userModel route pageData actionData sharedData effect (Msg userMsg pageData actionData sharedData errorPage) errorPage
|
|
1164
1268
|
-> Url
|
|
1165
1269
|
-> Maybe FormData
|
|
1166
1270
|
-> Cmd (Msg userMsg pageData actionData sharedData errorPage)
|
|
1167
|
-
fetchRouteData
|
|
1271
|
+
fetchRouteData transitionKey toMsg config url details =
|
|
1168
1272
|
{-
|
|
1169
1273
|
TODO:
|
|
1170
1274
|
- [X] `toMsg` needs a parameter for the callback Msg so it can pass it on if there is a Redirect response
|
|
@@ -1178,14 +1282,14 @@ fetchRouteData forPageDataReload transitionKey toMsg config url details =
|
|
|
1178
1282
|
|
|
1179
1283
|
-}
|
|
1180
1284
|
let
|
|
1181
|
-
formMethod : Method
|
|
1285
|
+
formMethod : Form.Method
|
|
1182
1286
|
formMethod =
|
|
1183
1287
|
details
|
|
1184
1288
|
|> Maybe.map .method
|
|
1185
|
-
|> Maybe.withDefault Get
|
|
1289
|
+
|> Maybe.withDefault Form.Get
|
|
1186
1290
|
in
|
|
1187
1291
|
Http.request
|
|
1188
|
-
{ method = details |> Maybe.map (.method >>
|
|
1292
|
+
{ method = details |> Maybe.map (.method >> methodToString) |> Maybe.withDefault "GET"
|
|
1189
1293
|
, headers = []
|
|
1190
1294
|
, url =
|
|
1191
1295
|
"/"
|
|
@@ -1203,34 +1307,34 @@ fetchRouteData forPageDataReload transitionKey toMsg config url details =
|
|
|
1203
1307
|
|> String.join "/"
|
|
1204
1308
|
)
|
|
1205
1309
|
++ (case formMethod of
|
|
1206
|
-
Post ->
|
|
1310
|
+
Form.Post ->
|
|
1207
1311
|
"/"
|
|
1208
1312
|
|
|
1209
|
-
Get ->
|
|
1313
|
+
Form.Get ->
|
|
1210
1314
|
details
|
|
1211
|
-
|> Maybe.map
|
|
1315
|
+
|> Maybe.map (.fields >> encodeFormData)
|
|
1212
1316
|
|> Maybe.map (\encoded -> "?" ++ encoded)
|
|
1213
1317
|
|> Maybe.withDefault ""
|
|
1214
1318
|
)
|
|
1215
1319
|
++ (case formMethod of
|
|
1216
1320
|
-- TODO extract this to something unit testable
|
|
1217
1321
|
-- TODO make states mutually exclusive for submissions and direct URL requests (shouldn't be possible to append two query param strings)
|
|
1218
|
-
Post ->
|
|
1322
|
+
Form.Post ->
|
|
1219
1323
|
""
|
|
1220
1324
|
|
|
1221
|
-
Get ->
|
|
1325
|
+
Form.Get ->
|
|
1222
1326
|
url.query
|
|
1223
1327
|
|> Maybe.map (\encoded -> "?" ++ encoded)
|
|
1224
1328
|
|> Maybe.withDefault ""
|
|
1225
1329
|
)
|
|
1226
1330
|
, body =
|
|
1227
1331
|
case formMethod of
|
|
1228
|
-
Post ->
|
|
1332
|
+
Form.Post ->
|
|
1229
1333
|
let
|
|
1230
1334
|
urlEncodedFields : Maybe String
|
|
1231
1335
|
urlEncodedFields =
|
|
1232
1336
|
details
|
|
1233
|
-
|> Maybe.map
|
|
1337
|
+
|> Maybe.map (.fields >> encodeFormData)
|
|
1234
1338
|
in
|
|
1235
1339
|
urlEncodedFields
|
|
1236
1340
|
|> Maybe.map (\encoded -> Http.stringBody "application/x-www-form-urlencoded" encoded)
|
|
@@ -1251,7 +1355,7 @@ fetchRouteData forPageDataReload transitionKey toMsg config url details =
|
|
|
1251
1355
|
Http.NetworkError_ ->
|
|
1252
1356
|
Err Http.NetworkError
|
|
1253
1357
|
|
|
1254
|
-
Http.BadStatus_
|
|
1358
|
+
Http.BadStatus_ _ body ->
|
|
1255
1359
|
body
|
|
1256
1360
|
|> Bytes.Decode.decode config.decodeResponse
|
|
1257
1361
|
|> Result.fromMaybe "Decoding error"
|
|
@@ -1303,7 +1407,7 @@ startNewGetLoad urlToGet toMsg ( model, effect ) =
|
|
|
1303
1407
|
cancelIfStale : Effect userMsg pageData actionData sharedData userEffect errorPage
|
|
1304
1408
|
cancelIfStale =
|
|
1305
1409
|
case model.transition of
|
|
1306
|
-
Just ( transitionKey, Pages.Transition.Loading
|
|
1410
|
+
Just ( transitionKey, Pages.Transition.Loading _ _ ) ->
|
|
1307
1411
|
CancelRequest transitionKey
|
|
1308
1412
|
|
|
1309
1413
|
_ ->
|
|
@@ -1314,13 +1418,13 @@ startNewGetLoad urlToGet toMsg ( model, effect ) =
|
|
|
1314
1418
|
, transition =
|
|
1315
1419
|
( model.nextTransitionKey
|
|
1316
1420
|
, case model.transition of
|
|
1317
|
-
Just (
|
|
1421
|
+
Just ( _, Pages.Transition.LoadAfterSubmit submitData _ _ ) ->
|
|
1318
1422
|
Pages.Transition.LoadAfterSubmit
|
|
1319
1423
|
submitData
|
|
1320
1424
|
(urlToGet.path |> Path.fromString)
|
|
1321
1425
|
Pages.Transition.Load
|
|
1322
1426
|
|
|
1323
|
-
Just (
|
|
1427
|
+
Just ( _, Pages.Transition.Submitting submitData ) ->
|
|
1324
1428
|
Pages.Transition.LoadAfterSubmit
|
|
1325
1429
|
submitData
|
|
1326
1430
|
(urlToGet.path |> Path.fromString)
|
|
@@ -1392,6 +1496,7 @@ loadDataAndUpdateUrl ( newPageData, newSharedData, newActionData ) maybeUserMsg
|
|
|
1392
1496
|
, actionData = newActionData
|
|
1393
1497
|
}
|
|
1394
1498
|
|
|
1499
|
+
-- TODO use userEffect here?
|
|
1395
1500
|
( userModel, _ ) =
|
|
1396
1501
|
-- TODO if urlWithoutRedirectResolution is different from the url with redirect resolution, then
|
|
1397
1502
|
-- instead of calling update, call pushUrl (I think?)
|
|
@@ -1467,10 +1572,10 @@ loadDataAndUpdateUrl ( newPageData, newSharedData, newActionData ) maybeUserMsg
|
|
|
1467
1572
|
Err _ ->
|
|
1468
1573
|
{-
|
|
1469
1574
|
When there is an error loading the content.dat, we are either
|
|
1470
|
-
1) in the dev server, and should show the relevant
|
|
1575
|
+
1) in the dev server, and should show the relevant BackendTask error for the page
|
|
1471
1576
|
we're navigating to. This could be done more cleanly, but it's simplest to just
|
|
1472
1577
|
do a fresh page load and use the code path for presenting an error for a fresh page.
|
|
1473
|
-
2) In a production app. That means we had a successful build, so there were no
|
|
1578
|
+
2) In a production app. That means we had a successful build, so there were no BackendTask failures,
|
|
1474
1579
|
so the app must be stale (unless it's in some unexpected state from a bug). In the future,
|
|
1475
1580
|
it probably makes sense to include some sort of hash of the app version we are fetching, match
|
|
1476
1581
|
it with the current version that's running, and perform this logic when we see there is a mismatch.
|
|
@@ -1483,3 +1588,31 @@ loadDataAndUpdateUrl ( newPageData, newSharedData, newActionData ) maybeUserMsg
|
|
|
1483
1588
|
|> Url.toString
|
|
1484
1589
|
|> BrowserLoadUrl
|
|
1485
1590
|
)
|
|
1591
|
+
|
|
1592
|
+
|
|
1593
|
+
methodToString : Form.Method -> String
|
|
1594
|
+
methodToString method =
|
|
1595
|
+
case method of
|
|
1596
|
+
Form.Get ->
|
|
1597
|
+
"GET"
|
|
1598
|
+
|
|
1599
|
+
Form.Post ->
|
|
1600
|
+
"POST"
|
|
1601
|
+
|
|
1602
|
+
|
|
1603
|
+
encodeFormData : List ( String, String ) -> String
|
|
1604
|
+
encodeFormData fields =
|
|
1605
|
+
fields
|
|
1606
|
+
|> List.map
|
|
1607
|
+
(\( name, value ) ->
|
|
1608
|
+
Url.percentEncode name ++ "=" ++ Url.percentEncode value
|
|
1609
|
+
)
|
|
1610
|
+
|> String.join "&"
|
|
1611
|
+
|
|
1612
|
+
|
|
1613
|
+
type alias FormData =
|
|
1614
|
+
{ fields : List ( String, String )
|
|
1615
|
+
, method : Form.Method
|
|
1616
|
+
, action : String
|
|
1617
|
+
, id : Maybe String
|
|
1618
|
+
}
|