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.
Files changed (165) hide show
  1. package/README.md +2 -2
  2. package/adapter/netlify.js +207 -0
  3. package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2731 -2939
  4. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmi +0 -0
  5. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateData.elmo +0 -0
  6. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-DeadCodeEliminateDataTest.elmo +0 -0
  7. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  8. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  9. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  10. package/generator/dead-code-review/elm-stuff/tests-0.19.1/elm.json +1 -1
  11. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1527 -422
  12. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/Runner.elm.js +16840 -13653
  13. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  14. package/generator/dead-code-review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
  15. package/generator/dead-code-review/elm.json +9 -7
  16. package/generator/dead-code-review/src/Pages/Review/DeadCodeEliminateData.elm +59 -10
  17. package/generator/dead-code-review/tests/Pages/Review/DeadCodeEliminateDataTest.elm +52 -36
  18. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmi +0 -0
  19. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Internal-RoutePattern.elmo +0 -0
  20. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmi +0 -0
  21. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/Pages-Review-NoContractViolations.elmo +0 -0
  22. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/d.dat +0 -0
  23. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/i.dat +0 -0
  24. package/generator/review/elm-stuff/tests-0.19.1/elm-stuff/0.19.1/o.dat +0 -0
  25. package/generator/review/elm-stuff/tests-0.19.1/elm.json +1 -1
  26. package/generator/review/elm-stuff/tests-0.19.1/js/Reporter.elm.js +1527 -422
  27. package/generator/review/elm-stuff/tests-0.19.1/js/Runner.elm.js +25118 -21832
  28. package/generator/review/elm-stuff/tests-0.19.1/js/node_runner.js +1 -1
  29. package/generator/review/elm-stuff/tests-0.19.1/js/node_supervisor.js +4 -4
  30. package/generator/review/elm.json +10 -10
  31. package/generator/src/RouteBuilder.elm +93 -128
  32. package/generator/src/SharedTemplate.elm +8 -7
  33. package/generator/src/SiteConfig.elm +3 -2
  34. package/generator/src/basepath-middleware.js +3 -3
  35. package/generator/src/build.js +143 -59
  36. package/generator/src/cli.js +292 -88
  37. package/generator/src/codegen.js +29 -27
  38. package/generator/src/compatibility-key.js +3 -0
  39. package/generator/src/compile-elm.js +43 -26
  40. package/generator/src/config.js +2 -4
  41. package/generator/src/copy-dir.js +2 -2
  42. package/generator/src/dev-server.js +160 -102
  43. package/generator/src/dir-helpers.js +9 -26
  44. package/generator/src/elm-codegen.js +5 -4
  45. package/generator/src/elm-file-constants.js +2 -3
  46. package/generator/src/error-formatter.js +12 -11
  47. package/generator/src/file-helpers.js +3 -4
  48. package/generator/src/generate-template-module-connector.js +23 -23
  49. package/generator/src/init.js +9 -8
  50. package/generator/src/pre-render-html.js +10 -13
  51. package/generator/src/render-test.js +109 -0
  52. package/generator/src/render-worker.js +25 -28
  53. package/generator/src/render.js +320 -143
  54. package/generator/src/request-cache.js +265 -162
  55. package/generator/src/resolve-elm-module.js +64 -0
  56. package/generator/src/rewrite-client-elm-json.js +6 -5
  57. package/generator/src/rewrite-elm-json-help.js +56 -0
  58. package/generator/src/rewrite-elm-json.js +17 -7
  59. package/generator/src/route-codegen-helpers.js +16 -31
  60. package/generator/src/seo-renderer.js +1 -3
  61. package/generator/src/vite-utils.js +1 -2
  62. package/generator/static-code/elm-pages.js +10 -0
  63. package/generator/static-code/hmr.js +79 -13
  64. package/generator/template/app/Api.elm +3 -2
  65. package/generator/template/app/Effect.elm +155 -0
  66. package/generator/template/app/ErrorPage.elm +49 -6
  67. package/generator/template/app/Route/Blog/Slug_.elm +86 -0
  68. package/generator/template/app/Route/Greet.elm +107 -0
  69. package/generator/template/app/Route/Hello.elm +119 -0
  70. package/generator/template/app/Route/Index.elm +26 -25
  71. package/generator/template/app/Shared.elm +38 -39
  72. package/generator/template/app/Site.elm +4 -7
  73. package/generator/template/app/View.elm +9 -8
  74. package/generator/template/codegen/elm.codegen.json +18 -0
  75. package/generator/template/custom-backend-task.ts +3 -0
  76. package/generator/template/elm-pages.config.mjs +13 -0
  77. package/generator/template/elm-tooling.json +0 -3
  78. package/generator/template/elm.json +25 -20
  79. package/generator/template/index.ts +1 -2
  80. package/generator/template/netlify.toml +4 -1
  81. package/generator/template/package.json +10 -4
  82. package/generator/template/script/.elm-pages/compiled-ports/custom-backend-task.mjs +7 -0
  83. package/generator/template/script/custom-backend-task.ts +3 -0
  84. package/generator/template/script/elm.json +61 -0
  85. package/generator/template/script/src/AddRoute.elm +312 -0
  86. package/generator/template/script/src/Stars.elm +42 -0
  87. package/package.json +30 -27
  88. package/src/ApiRoute.elm +249 -82
  89. package/src/BackendTask/Custom.elm +325 -0
  90. package/src/BackendTask/Env.elm +90 -0
  91. package/src/{DataSource → BackendTask}/File.elm +171 -56
  92. package/src/{DataSource → BackendTask}/Glob.elm +136 -125
  93. package/src/BackendTask/Http.elm +679 -0
  94. package/src/{DataSource → BackendTask}/Internal/Glob.elm +1 -1
  95. package/src/BackendTask/Internal/Request.elm +69 -0
  96. package/src/BackendTask/Random.elm +79 -0
  97. package/src/BackendTask/Time.elm +47 -0
  98. package/src/BackendTask.elm +531 -0
  99. package/src/FatalError.elm +90 -0
  100. package/src/FormData.elm +21 -18
  101. package/src/Head/Seo.elm +4 -4
  102. package/src/Head.elm +112 -8
  103. package/src/Internal/ApiRoute.elm +7 -5
  104. package/src/Internal/Request.elm +84 -4
  105. package/src/PageServerResponse.elm +6 -1
  106. package/src/Pages/ConcurrentSubmission.elm +127 -0
  107. package/src/Pages/Form.elm +340 -0
  108. package/src/Pages/FormData.elm +19 -0
  109. package/src/Pages/GeneratorProgramConfig.elm +15 -0
  110. package/src/Pages/Internal/FatalError.elm +5 -0
  111. package/src/Pages/Internal/Msg.elm +93 -0
  112. package/src/Pages/Internal/NotFoundReason.elm +4 -4
  113. package/src/Pages/Internal/Platform/Cli.elm +586 -768
  114. package/src/Pages/Internal/Platform/CompatibilityKey.elm +1 -1
  115. package/src/Pages/Internal/Platform/Effect.elm +1 -2
  116. package/src/Pages/Internal/Platform/GeneratorApplication.elm +379 -0
  117. package/src/Pages/Internal/Platform/StaticResponses.elm +65 -276
  118. package/src/Pages/Internal/Platform/ToJsPayload.elm +6 -9
  119. package/src/Pages/Internal/Platform.elm +330 -203
  120. package/src/Pages/Internal/ResponseSketch.elm +2 -2
  121. package/src/Pages/Internal/Script.elm +17 -0
  122. package/src/Pages/Internal/StaticHttpBody.elm +35 -1
  123. package/src/Pages/Manifest.elm +52 -11
  124. package/src/Pages/Navigation.elm +85 -0
  125. package/src/Pages/PageUrl.elm +26 -12
  126. package/src/Pages/ProgramConfig.elm +32 -22
  127. package/src/Pages/Script.elm +166 -0
  128. package/src/Pages/SiteConfig.elm +3 -2
  129. package/src/Pages/StaticHttp/Request.elm +2 -2
  130. package/src/Pages/StaticHttpRequest.elm +23 -99
  131. package/src/Pages/Url.elm +3 -3
  132. package/src/PagesMsg.elm +88 -0
  133. package/src/QueryParams.elm +21 -172
  134. package/src/RenderRequest.elm +7 -7
  135. package/src/RequestsAndPending.elm +37 -20
  136. package/src/Result/Extra.elm +26 -0
  137. package/src/Scaffold/Form.elm +569 -0
  138. package/src/Scaffold/Route.elm +1431 -0
  139. package/src/Server/Request.elm +476 -1001
  140. package/src/Server/Response.elm +130 -36
  141. package/src/Server/Session.elm +181 -111
  142. package/src/Server/SetCookie.elm +80 -32
  143. package/src/Stub.elm +53 -0
  144. package/src/Test/Html/Internal/ElmHtml/ToString.elm +8 -9
  145. package/src/{Path.elm → UrlPath.elm} +33 -36
  146. package/generator/template/public/images/icon-png.png +0 -0
  147. package/src/DataSource/Env.elm +0 -38
  148. package/src/DataSource/Http.elm +0 -446
  149. package/src/DataSource/Internal/Request.elm +0 -20
  150. package/src/DataSource/Port.elm +0 -90
  151. package/src/DataSource.elm +0 -546
  152. package/src/Form/Field.elm +0 -717
  153. package/src/Form/FieldStatus.elm +0 -36
  154. package/src/Form/FieldView.elm +0 -417
  155. package/src/Form/FormData.elm +0 -22
  156. package/src/Form/Validation.elm +0 -391
  157. package/src/Form/Value.elm +0 -118
  158. package/src/Form.elm +0 -1683
  159. package/src/FormDecoder.elm +0 -102
  160. package/src/Pages/FormState.elm +0 -256
  161. package/src/Pages/Generate.elm +0 -1242
  162. package/src/Pages/Internal/Form.elm +0 -17
  163. package/src/Pages/Internal/Platform/Cli.elm.bak +0 -1276
  164. package/src/Pages/Msg.elm +0 -79
  165. package/src/Pages/Transition.elm +0 -70
package/src/Head.elm CHANGED
@@ -9,14 +9,118 @@ module Head exposing
9
9
  , toJson, canonicalLink
10
10
  )
11
11
 
12
- {-| This module contains low-level functions for building up
13
- values that will be rendered into the page's `<head>` tag
14
- when you run `elm-pages build`. Most likely the `Head.Seo` module
15
- will do everything you need out of the box, and you will just need to import `Head`
16
- so you can use the `Tag` type in your type annotations.
17
-
18
- But this module might be useful if you have a special use case, or if you are
19
- writing a plugin package to extend `elm-pages`.
12
+ {-| This module contains functions for building up
13
+ tags with metadata that will be rendered into the page's `<head>` tag
14
+ when your page is pre-rendered (or server-rendered, in the case of your server-rendered Route Modules). See also [`Head.Seo`](Head-Seo),
15
+ which has some helper functions for defining OpenGraph and Twitter tags.
16
+
17
+ One of the unique benefits of using `elm-pages` is that all of your routes (both pre-rendered and server-rendered) fully
18
+ render the HTML of your page. That includes the full initial `view` (with the BackendTask resolved, and the `Model` from `init`).
19
+ The HTML response also includes all of the `Head` tags, which are defined in two places:
20
+
21
+ 1. `app/Site.elm` - there is a `head` definition in `Site.elm` where you define global head tags that will be included on every rendered page.
22
+
23
+ 2. In each Route Module - there is a `head` function where you have access to both the resolved `BackendTask` and the `RouteParams` for the page and can return head tags based on that.
24
+
25
+ Here is a common set of global head tags that we can define in `Site.elm`:
26
+
27
+ module Site exposing (canonicalUrl, config)
28
+
29
+ import BackendTask exposing (BackendTask)
30
+ import Head
31
+ import MimeType
32
+ import SiteConfig exposing (SiteConfig)
33
+
34
+ config : SiteConfig
35
+ config =
36
+ { canonicalUrl = "<https://elm-pages.com">
37
+ , head = head
38
+ }
39
+
40
+ head : BackendTask (List Head.Tag)
41
+ head =
42
+ [ Head.metaName "viewport" (Head.raw "width=device-width,initial-scale=1")
43
+ , Head.metaName "mobile-web-app-capable" (Head.raw "yes")
44
+ , Head.metaName "theme-color" (Head.raw "#ffffff")
45
+ , Head.metaName "apple-mobile-web-app-capable" (Head.raw "yes")
46
+ , Head.metaName "apple-mobile-web-app-status-bar-style" (Head.raw "black-translucent")
47
+ , Head.icon [ ( 32, 32 ) ] MimeType.Png (cloudinaryIcon MimeType.Png 32)
48
+ , Head.icon [ ( 16, 16 ) ] MimeType.Png (cloudinaryIcon MimeType.Png 16)
49
+ , Head.appleTouchIcon (Just 180) (cloudinaryIcon MimeType.Png 180)
50
+ , Head.appleTouchIcon (Just 192) (cloudinaryIcon MimeType.Png 192)
51
+ ]
52
+ |> BackendTask.succeed
53
+
54
+ And here is a `head` function for a Route Module for a blog post. Note that we have access to our `BackendTask` Data and
55
+ are using it to populate article metadata like the article's image, publish date, etc.
56
+
57
+ import Article
58
+ import BackendTask
59
+ import Date
60
+ import Head
61
+ import Head.Seo
62
+ import Path
63
+ import Route exposing (Route)
64
+ import RouteBuilder exposing (App, StatelessRoute)
65
+
66
+ type alias RouteParams =
67
+ { slug : String }
68
+
69
+ type alias Data =
70
+ { metadata : ArticleMetadata
71
+ , body : List Markdown.Block.Block
72
+ }
73
+
74
+ route : StatelessRoute RouteParams Data ActionData
75
+ route =
76
+ RouteBuilder.preRender
77
+ { data = data
78
+ , head = head
79
+ , pages = pages
80
+ }
81
+ |> RouteBuilder.buildNoState { view = view }
82
+
83
+ head :
84
+ App Data ActionData RouteParams
85
+ -> List Head.Tag
86
+ head static =
87
+ let
88
+ metadata =
89
+ static.data.metadata
90
+ in
91
+ Head.Seo.summaryLarge
92
+ { canonicalUrlOverride = Nothing
93
+ , siteName = "elm-pages"
94
+ , image =
95
+ { url = metadata.image
96
+ , alt = metadata.description
97
+ , dimensions = Nothing
98
+ , mimeType = Nothing
99
+ }
100
+ , description = metadata.description
101
+ , locale = Nothing
102
+ , title = metadata.title
103
+ }
104
+ |> Head.Seo.article
105
+ { tags = []
106
+ , section = Nothing
107
+ , publishedTime = Just (DateOrDateTime.Date metadata.published)
108
+ , modifiedTime = Nothing
109
+ , expirationTime = Nothing
110
+ }
111
+
112
+
113
+ ## Why is pre-rendered HTML important? Does it still matter for SEO?
114
+
115
+ Many search engines are able to execute JavaScript now. However, not all are, and even with crawlers like Google, there
116
+ is a longer lead time for your pages to be indexed when you have HTML with a blank page that is only visible after the JavaScript executes.
117
+
118
+ But most importantly, many tools that unfurl links will not execute JavaScript at all, but rather simply do a simple pass to parse your `<head>` tags.
119
+ It is not viable or reliable to add `<head>` tags for metadata on the client-side, it must be present in the initial HTML payload. Otherwise you may not
120
+ get unfurling preview content when you share a link to your site on Slack, Twitter, etc.
121
+
122
+
123
+ ## Building up Head Tags
20
124
 
21
125
  @docs Tag, metaName, metaProperty, metaRedirect
22
126
  @docs rssLink, sitemapLink, rootLanguage, manifestLink
@@ -8,8 +8,10 @@ module Internal.ApiRoute exposing
8
8
  , withRoutes
9
9
  )
10
10
 
11
- import DataSource exposing (DataSource)
11
+ import BackendTask exposing (BackendTask)
12
+ import FatalError exposing (FatalError)
12
13
  import Head
14
+ import Json.Decode
13
15
  import Pattern exposing (Pattern)
14
16
  import Regex exposing (Regex)
15
17
 
@@ -44,12 +46,12 @@ tryMatchDone path (ApiRoute handler) =
44
46
  type ApiRoute response
45
47
  = ApiRoute
46
48
  { regex : Regex
47
- , matchesToResponse : String -> DataSource (Maybe response)
48
- , buildTimeRoutes : DataSource (List String)
49
- , handleRoute : String -> DataSource Bool
49
+ , matchesToResponse : Json.Decode.Value -> String -> BackendTask FatalError (Maybe response)
50
+ , buildTimeRoutes : BackendTask FatalError (List String)
51
+ , handleRoute : String -> BackendTask FatalError Bool
50
52
  , pattern : Pattern
51
53
  , kind : String
52
- , globalHeadTags : Maybe (DataSource (List Head.Tag))
54
+ , globalHeadTags : Maybe (BackendTask FatalError (List Head.Tag))
53
55
  }
54
56
 
55
57
 
@@ -1,7 +1,87 @@
1
- module Internal.Request exposing (Parser(..))
1
+ module Internal.Request exposing (Request(..), RequestRecord, fakeRequest, toRequest)
2
2
 
3
- import Json.Decode
3
+ import CookieParser
4
+ import Dict exposing (Dict)
5
+ import Json.Decode as Decode
6
+ import Time
4
7
 
5
8
 
6
- type Parser decodesTo validationError
7
- = Parser (Json.Decode.Decoder ( Result validationError decodesTo, List validationError ))
9
+ type Request
10
+ = Request RequestRecord
11
+
12
+
13
+ type alias RequestRecord =
14
+ { time : Time.Posix
15
+ , method : String
16
+ , body : Maybe String
17
+ , rawUrl : String
18
+ , rawHeaders : Dict String String
19
+ , cookies : Dict String String
20
+ }
21
+
22
+
23
+ toRequest : Decode.Value -> Request
24
+ toRequest value =
25
+ Decode.decodeValue requestDecoder value
26
+ |> Result.map Request
27
+ |> Result.withDefault fakeRequest
28
+
29
+
30
+ fakeRequest : Request
31
+ fakeRequest =
32
+ Request
33
+ { time = Time.millisToPosix 0
34
+ , method = "ERROR"
35
+ , body = Just "ERROR"
36
+ , rawUrl = "ERROR"
37
+ , rawHeaders = Dict.empty
38
+ , cookies = Dict.empty
39
+ }
40
+
41
+
42
+ requestDecoder : Decode.Decoder RequestRecord
43
+ requestDecoder =
44
+ Decode.succeed RequestRecord
45
+ |> andMap
46
+ (Decode.field "requestTime"
47
+ (Decode.int |> Decode.map Time.millisToPosix)
48
+ )
49
+ |> andMap (Decode.field "method" Decode.string)
50
+ |> andMap (Decode.field "body" (Decode.nullable Decode.string))
51
+ |> andMap
52
+ (Decode.string
53
+ |> Decode.field "rawUrl"
54
+ )
55
+ |> andMap (Decode.field "headers" (Decode.dict Decode.string))
56
+ |> andMap
57
+ (Decode.field "headers"
58
+ (optionalField "cookie" Decode.string
59
+ |> Decode.map
60
+ (Maybe.map CookieParser.parse
61
+ >> Maybe.withDefault Dict.empty
62
+ )
63
+ )
64
+ )
65
+
66
+
67
+ andMap : Decode.Decoder a -> Decode.Decoder (a -> b) -> Decode.Decoder b
68
+ andMap =
69
+ Decode.map2 (|>)
70
+
71
+
72
+ optionalField : String -> Decode.Decoder a -> Decode.Decoder (Maybe a)
73
+ optionalField fieldName decoder_ =
74
+ let
75
+ finishDecoding : Decode.Value -> Decode.Decoder (Maybe a)
76
+ finishDecoding json =
77
+ case Decode.decodeValue (Decode.field fieldName Decode.value) json of
78
+ Ok _ ->
79
+ -- The field is present, so run the decoder on it.
80
+ Decode.map Just (Decode.field fieldName decoder_)
81
+
82
+ Err _ ->
83
+ -- The field was missing, which is fine!
84
+ Decode.succeed Nothing
85
+ in
86
+ Decode.value
87
+ |> Decode.andThen finishDecoding
@@ -15,7 +15,12 @@ type PageServerResponse data error
15
15
  | ErrorPage error { headers : List ( String, String ) }
16
16
 
17
17
 
18
- toRedirect : Response -> Maybe { statusCode : Int, location : String }
18
+ toRedirect :
19
+ { response
20
+ | statusCode : Int
21
+ , headers : List ( String, String )
22
+ }
23
+ -> Maybe { statusCode : Int, location : String }
19
24
  toRedirect response =
20
25
  response.headers
21
26
  |> Dict.fromList
@@ -0,0 +1,127 @@
1
+ module Pages.ConcurrentSubmission exposing
2
+ ( ConcurrentSubmission, Status(..)
3
+ , map
4
+ )
5
+
6
+ {-| When you render a `Form` with the [`Pages.Form.withConcurrent`](Pages-Form#withConcurrent) `Option`, the state of in-flight and completed submissions will be available
7
+ from your `Route` module through `app.concurrentSubmissions` as a `Dict String (ConcurrentSubmission (Maybe Action))`.
8
+
9
+ You can use this state to declaratively derive Pending UI or Optimistic UI from your pending submissions (without managing the state in your `Model`, since `elm-pages`
10
+ manages form submission state for you).
11
+
12
+ You can [see the full-stack TodoMVC example](https://github.com/dillonkearns/elm-pages/blob/master/examples/todos/app/Route/Visibility__.elm) for a complete example of deriving Pending UI state from `app.concurrentSubmissions`.
13
+
14
+ For example, this how the TodoMVC example derives the list of new items that are being created (but are still pending).
15
+
16
+ view :
17
+ App Data ActionData RouteParams
18
+ -> Shared.Model
19
+ -> Model
20
+ -> View (PagesMsg Msg)
21
+ view app shared model =
22
+ let
23
+ pendingActions : List Action
24
+ pendingActions =
25
+ app.concurrentSubmissions
26
+ |> Dict.values
27
+ |> List.filterMap
28
+ (\{ status, payload } ->
29
+ case status of
30
+ Pages.ConcurrentSubmission.Complete _ ->
31
+ Nothing
32
+
33
+ _ ->
34
+ allForms
35
+ |> Form.Handler.run payload.fields
36
+ |> Form.toResult
37
+ |> Result.toMaybe
38
+ )
39
+
40
+ newPendingItems : List Entry
41
+ newPendingItems =
42
+ pendingActions
43
+ |> List.filterMap
44
+ (\submission ->
45
+ case submission of
46
+ Add description ->
47
+ Just
48
+ { description = description
49
+ , completed = False
50
+ , id = ""
51
+ , isPending = True
52
+ }
53
+
54
+ _ ->
55
+ -- `newPendingItems` only cares about pending Add actions. Other values will use
56
+ -- pending submissions for other types of Actions.
57
+ Nothing
58
+ )
59
+ in
60
+ itemsView app newPendingItems
61
+
62
+ allForms : Form.Handler.Handler String Action
63
+ allForms =
64
+ |> Form.Handler.init Add addItemForm
65
+ -- |> Form.Handler.with ...
66
+
67
+
68
+ type Action
69
+ = UpdateEntry ( String, String )
70
+ | Add String
71
+ | Delete String
72
+ | DeleteComplete
73
+ | Check ( Bool, String )
74
+ | CheckAll Bool
75
+
76
+ @docs ConcurrentSubmission, Status
77
+
78
+ @docs map
79
+
80
+ -}
81
+
82
+ import Pages.FormData exposing (FormData)
83
+ import Time
84
+
85
+
86
+ {-| -}
87
+ type alias ConcurrentSubmission actionData =
88
+ { status : Status actionData
89
+ , payload : FormData
90
+ , initiatedAt : Time.Posix
91
+ }
92
+
93
+
94
+ {-| The status of a `ConcurrentSubmission`.
95
+
96
+ - `Submitting` - The submission is in-flight.
97
+ - `Reloading` - The submission has completed, and the page is now reloading the `Route`'s `data` to reflect the new state. The `actionData` holds any data returned from the `Route`'s `action`.
98
+ - `Complete` - The submission has completed, and the `Route`'s `data` has since reloaded so the state reflects the refreshed state after completing this specific form submission. The `actionData` holds any data returned from the `Route`'s `action`.
99
+
100
+ -}
101
+ type Status actionData
102
+ = Submitting
103
+ | Reloading actionData
104
+ | Complete actionData
105
+
106
+
107
+ {-| `map` a `ConcurrentSubmission`. Not needed for most high-level cases since this state is managed by the `elm-pages` framework for you.
108
+ -}
109
+ map : (a -> b) -> ConcurrentSubmission a -> ConcurrentSubmission b
110
+ map mapFn fetcherState =
111
+ { status = mapStatus mapFn fetcherState.status
112
+ , payload = fetcherState.payload
113
+ , initiatedAt = fetcherState.initiatedAt
114
+ }
115
+
116
+
117
+ mapStatus : (a -> b) -> Status a -> Status b
118
+ mapStatus mapFn fetcherSubmitStatus =
119
+ case fetcherSubmitStatus of
120
+ Submitting ->
121
+ Submitting
122
+
123
+ Reloading value ->
124
+ Reloading (mapFn value)
125
+
126
+ Complete value ->
127
+ Complete (mapFn value)