elm-pages 3.0.0-beta.8 → 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 +11 -2
- package/adapter/netlify.js +207 -0
- package/codegen/{elm-pages-codegen.js → elm-pages-codegen.cjs} +2730 -2938
- 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 +2 -2
- 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 +2 -2
- 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 +147 -63
- 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 +159 -92
- 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 +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 +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 -85
- 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 +237 -7
- 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 +629 -767
- 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 +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 -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 -1151
- package/src/Pages/Internal/Form.elm +0 -17
- package/src/Pages/Msg.elm +0 -79
- package/src/Pages/Transition.elm +0 -70
|
@@ -7,7 +7,7 @@ module Pages.Internal.ResponseSketch exposing (ResponseSketch(..))
|
|
|
7
7
|
-}
|
|
8
8
|
|
|
9
9
|
import Pages.Internal.NotFoundReason exposing (NotFoundReason)
|
|
10
|
-
import
|
|
10
|
+
import UrlPath exposing (UrlPath)
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
{-| -}
|
|
@@ -15,5 +15,5 @@ type ResponseSketch data action shared
|
|
|
15
15
|
= RenderPage data (Maybe action)
|
|
16
16
|
| HotUpdate data shared (Maybe action)
|
|
17
17
|
| Redirect String
|
|
18
|
-
| NotFound { reason : NotFoundReason, path :
|
|
18
|
+
| NotFound { reason : NotFoundReason, path : UrlPath }
|
|
19
19
|
| Action action
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Pages.Internal.Script exposing (Script(..))
|
|
2
|
+
|
|
3
|
+
import BackendTask exposing (BackendTask)
|
|
4
|
+
import Cli.Program as Program
|
|
5
|
+
import FatalError exposing (FatalError)
|
|
6
|
+
import Html exposing (Html)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
{-| -}
|
|
10
|
+
type Script
|
|
11
|
+
= Script
|
|
12
|
+
((Maybe { indent : Int, newLines : Bool }
|
|
13
|
+
-> Html Never
|
|
14
|
+
-> String
|
|
15
|
+
)
|
|
16
|
+
-> Program.Config (BackendTask FatalError ())
|
|
17
|
+
)
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
module Pages.Internal.StaticHttpBody exposing (Body(..), codec, encode)
|
|
2
2
|
|
|
3
|
+
import Base64
|
|
4
|
+
import Bytes exposing (Bytes)
|
|
3
5
|
import Codec exposing (Codec)
|
|
6
|
+
import Json.Decode
|
|
4
7
|
import Json.Encode as Encode
|
|
5
8
|
|
|
6
9
|
|
|
@@ -8,6 +11,7 @@ type Body
|
|
|
8
11
|
= EmptyBody
|
|
9
12
|
| StringBody String String
|
|
10
13
|
| JsonBody Encode.Value
|
|
14
|
+
| BytesBody String Bytes
|
|
11
15
|
|
|
12
16
|
|
|
13
17
|
encode : Body -> Encode.Value
|
|
@@ -26,6 +30,15 @@ encode body =
|
|
|
26
30
|
[ ( "content", content )
|
|
27
31
|
]
|
|
28
32
|
|
|
33
|
+
BytesBody _ content ->
|
|
34
|
+
encodeWithType "bytes"
|
|
35
|
+
[ ( "content"
|
|
36
|
+
, Base64.fromBytes content
|
|
37
|
+
|> Maybe.withDefault ""
|
|
38
|
+
|> Encode.string
|
|
39
|
+
)
|
|
40
|
+
]
|
|
41
|
+
|
|
29
42
|
|
|
30
43
|
encodeWithType : String -> List ( String, Encode.Value ) -> Encode.Value
|
|
31
44
|
encodeWithType typeName otherFields =
|
|
@@ -37,7 +50,7 @@ encodeWithType typeName otherFields =
|
|
|
37
50
|
codec : Codec Body
|
|
38
51
|
codec =
|
|
39
52
|
Codec.custom
|
|
40
|
-
(\vEmpty vString vJson value ->
|
|
53
|
+
(\vEmpty vString vJson vBytes value ->
|
|
41
54
|
case value of
|
|
42
55
|
EmptyBody ->
|
|
43
56
|
vEmpty
|
|
@@ -47,8 +60,29 @@ codec =
|
|
|
47
60
|
|
|
48
61
|
JsonBody body ->
|
|
49
62
|
vJson body
|
|
63
|
+
|
|
64
|
+
BytesBody contentType body ->
|
|
65
|
+
vBytes contentType body
|
|
50
66
|
)
|
|
51
67
|
|> Codec.variant0 "EmptyBody" EmptyBody
|
|
52
68
|
|> Codec.variant2 "StringBody" StringBody Codec.string Codec.string
|
|
53
69
|
|> Codec.variant1 "JsonBody" JsonBody Codec.value
|
|
70
|
+
|> Codec.variant2 "BytesBody" BytesBody Codec.string bytesCodec
|
|
54
71
|
|> Codec.buildCustom
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
bytesCodec : Codec Bytes
|
|
75
|
+
bytesCodec =
|
|
76
|
+
Codec.build (Base64.fromBytes >> Maybe.withDefault "" >> Encode.string)
|
|
77
|
+
(Json.Decode.string
|
|
78
|
+
|> Json.Decode.map Base64.toBytes
|
|
79
|
+
|> Json.Decode.andThen
|
|
80
|
+
(\decodedBytes ->
|
|
81
|
+
case decodedBytes of
|
|
82
|
+
Just bytes ->
|
|
83
|
+
Json.Decode.succeed bytes
|
|
84
|
+
|
|
85
|
+
Nothing ->
|
|
86
|
+
Json.Decode.fail "Couldn't parse bytes."
|
|
87
|
+
)
|
|
88
|
+
)
|
package/src/Pages/Manifest.elm
CHANGED
|
@@ -2,6 +2,7 @@ module Pages.Manifest exposing
|
|
|
2
2
|
( Config, Icon
|
|
3
3
|
, init
|
|
4
4
|
, withBackgroundColor, withCategories, withDisplayMode, withIarcRatingId, withLang, withOrientation, withShortName, withThemeColor
|
|
5
|
+
, withField
|
|
5
6
|
, DisplayMode(..), Orientation(..), IconPurpose(..)
|
|
6
7
|
, generator
|
|
7
8
|
, toJson
|
|
@@ -10,8 +11,8 @@ module Pages.Manifest exposing
|
|
|
10
11
|
{-| Represents the configuration of a
|
|
11
12
|
[web manifest file](https://developer.mozilla.org/en-US/docs/Web/Manifest).
|
|
12
13
|
|
|
13
|
-
You pass your `Pages.Manifest.Config` record into the `Pages.
|
|
14
|
-
|
|
14
|
+
You pass your `Pages.Manifest.Config` record into the `Pages.Manifest.generator`
|
|
15
|
+
in your `app/Api.elm` module to define a file generator that will build a `manifest.json` file as part of your build.
|
|
15
16
|
|
|
16
17
|
import Pages.Manifest as Manifest
|
|
17
18
|
import Pages.Manifest.Category
|
|
@@ -41,6 +42,11 @@ You pass your `Pages.Manifest.Config` record into the `Pages.application` functi
|
|
|
41
42
|
@docs withBackgroundColor, withCategories, withDisplayMode, withIarcRatingId, withLang, withOrientation, withShortName, withThemeColor
|
|
42
43
|
|
|
43
44
|
|
|
45
|
+
## Arbitrary Fields Escape Hatch
|
|
46
|
+
|
|
47
|
+
@docs withField
|
|
48
|
+
|
|
49
|
+
|
|
44
50
|
## Config options
|
|
45
51
|
|
|
46
52
|
@docs DisplayMode, Orientation, IconPurpose
|
|
@@ -58,9 +64,11 @@ You pass your `Pages.Manifest.Config` record into the `Pages.application` functi
|
|
|
58
64
|
-}
|
|
59
65
|
|
|
60
66
|
import ApiRoute
|
|
67
|
+
import BackendTask exposing (BackendTask)
|
|
61
68
|
import Color exposing (Color)
|
|
62
69
|
import Color.Convert
|
|
63
|
-
import
|
|
70
|
+
import Dict exposing (Dict)
|
|
71
|
+
import FatalError exposing (FatalError)
|
|
64
72
|
import Head
|
|
65
73
|
import Json.Encode as Encode
|
|
66
74
|
import LanguageTag exposing (LanguageTag, emptySubtags)
|
|
@@ -69,7 +77,7 @@ import LanguageTag.Language
|
|
|
69
77
|
import MimeType
|
|
70
78
|
import Pages.Manifest.Category as Category exposing (Category)
|
|
71
79
|
import Pages.Url
|
|
72
|
-
import
|
|
80
|
+
import UrlPath exposing (UrlPath)
|
|
73
81
|
|
|
74
82
|
|
|
75
83
|
|
|
@@ -106,7 +114,7 @@ type Orientation
|
|
|
106
114
|
init :
|
|
107
115
|
{ description : String
|
|
108
116
|
, name : String
|
|
109
|
-
, startUrl :
|
|
117
|
+
, startUrl : UrlPath
|
|
110
118
|
, icons : List Icon
|
|
111
119
|
}
|
|
112
120
|
-> Config
|
|
@@ -123,6 +131,7 @@ init options =
|
|
|
123
131
|
, shortName = Nothing
|
|
124
132
|
, icons = options.icons
|
|
125
133
|
, lang = usEnglish
|
|
134
|
+
, otherFields = Dict.empty
|
|
126
135
|
}
|
|
127
136
|
|
|
128
137
|
|
|
@@ -191,6 +200,17 @@ withLang languageTag config =
|
|
|
191
200
|
{ config | lang = languageTag }
|
|
192
201
|
|
|
193
202
|
|
|
203
|
+
{-| Escape hatch for specifying fields that aren't exposed through this module otherwise. The possible supported properties
|
|
204
|
+
in a manifest file can change over time, so see [MDN manifest.json docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json)
|
|
205
|
+
for a full listing of the current supported properties.
|
|
206
|
+
-}
|
|
207
|
+
withField : String -> Encode.Value -> Config -> Config
|
|
208
|
+
withField name value config =
|
|
209
|
+
{ config
|
|
210
|
+
| otherFields = config.otherFields |> Dict.insert name value
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
|
|
194
214
|
orientationToString : Orientation -> String
|
|
195
215
|
orientationToString orientation =
|
|
196
216
|
case orientation of
|
|
@@ -233,12 +253,13 @@ type alias Config =
|
|
|
233
253
|
, themeColor : Maybe Color
|
|
234
254
|
|
|
235
255
|
-- https://developer.mozilla.org/en-US/docs/Web/Manifest/start_url
|
|
236
|
-
, startUrl :
|
|
256
|
+
, startUrl : UrlPath
|
|
237
257
|
|
|
238
258
|
-- https://developer.mozilla.org/en-US/docs/Web/Manifest/short_name
|
|
239
259
|
, shortName : Maybe String
|
|
240
260
|
, icons : List Icon
|
|
241
261
|
, lang : LanguageTag
|
|
262
|
+
, otherFields : Dict String Encode.Value
|
|
242
263
|
}
|
|
243
264
|
|
|
244
265
|
|
|
@@ -322,18 +343,34 @@ nonEmptyList list =
|
|
|
322
343
|
Just list
|
|
323
344
|
|
|
324
345
|
|
|
325
|
-
{-| A generator for Api.elm to include a manifest.json.
|
|
346
|
+
{-| A generator for `Api.elm` to include a manifest.json. The String argument is the canonical URL of the site.
|
|
347
|
+
|
|
348
|
+
module Api exposing (routes)
|
|
349
|
+
|
|
350
|
+
import ApiRoute
|
|
351
|
+
import Pages.Manifest
|
|
352
|
+
|
|
353
|
+
routes :
|
|
354
|
+
BackendTask FatalError (List Route)
|
|
355
|
+
-> (Maybe { indent : Int, newLines : Bool } -> Html Never -> String)
|
|
356
|
+
-> List (ApiRoute.ApiRoute ApiRoute.Response)
|
|
357
|
+
routes getStaticRoutes htmlToString =
|
|
358
|
+
[ Pages.Manifest.generator
|
|
359
|
+
Site.canonicalUrl
|
|
360
|
+
Manifest.config
|
|
361
|
+
]
|
|
362
|
+
|
|
326
363
|
-}
|
|
327
|
-
generator : String ->
|
|
364
|
+
generator : String -> BackendTask FatalError Config -> ApiRoute.ApiRoute ApiRoute.Response
|
|
328
365
|
generator canonicalSiteUrl config =
|
|
329
366
|
ApiRoute.succeed
|
|
330
367
|
(config
|
|
331
|
-
|>
|
|
368
|
+
|> BackendTask.map (toJson canonicalSiteUrl >> Encode.encode 0)
|
|
332
369
|
)
|
|
333
370
|
|> ApiRoute.literal "manifest.json"
|
|
334
371
|
|> ApiRoute.single
|
|
335
372
|
|> ApiRoute.withGlobalHeadTags
|
|
336
|
-
(
|
|
373
|
+
(BackendTask.succeed
|
|
337
374
|
[ Head.manifestLink "/manifest.json"
|
|
338
375
|
]
|
|
339
376
|
)
|
|
@@ -409,7 +446,7 @@ toJson canonicalSiteUrl config =
|
|
|
409
446
|
|> Maybe.map Encode.string
|
|
410
447
|
)
|
|
411
448
|
, ( "start_url"
|
|
412
|
-
,
|
|
449
|
+
, UrlPath.toAbsolute config.startUrl
|
|
413
450
|
|> Encode.string
|
|
414
451
|
|> Just
|
|
415
452
|
)
|
|
@@ -420,6 +457,10 @@ toJson canonicalSiteUrl config =
|
|
|
420
457
|
, Encode.string "/" |> Just
|
|
421
458
|
)
|
|
422
459
|
]
|
|
460
|
+
++ (config.otherFields
|
|
461
|
+
|> Dict.toList
|
|
462
|
+
|> List.map (Tuple.mapSecond Just)
|
|
463
|
+
)
|
|
423
464
|
|> encodeMaybeObject
|
|
424
465
|
|
|
425
466
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module Pages.Navigation exposing (Navigation(..), LoadingState(..))
|
|
2
|
+
|
|
3
|
+
{-| `elm-pages` maintains a single `Maybe Navigation` state which is accessible from your `Route` modules through `app.navigation`.
|
|
4
|
+
|
|
5
|
+
You can use it to show a loading indicator while a page is loading:
|
|
6
|
+
|
|
7
|
+
import Pages.Navigation as Navigation
|
|
8
|
+
|
|
9
|
+
pageLoadingIndicator app =
|
|
10
|
+
case app.navigation of
|
|
11
|
+
Just (Navigation.Loading path _) ->
|
|
12
|
+
Spinner.view
|
|
13
|
+
|
|
14
|
+
Nothing ->
|
|
15
|
+
emptyView
|
|
16
|
+
|
|
17
|
+
emptyView : Html msg
|
|
18
|
+
emptyView =
|
|
19
|
+
Html.text ""
|
|
20
|
+
|
|
21
|
+
You can also use it to derive Pending UI or Optimistic UI from a pending form submission:
|
|
22
|
+
|
|
23
|
+
import Form
|
|
24
|
+
import Form.Handler
|
|
25
|
+
import Pages.Navigation as Navigation
|
|
26
|
+
|
|
27
|
+
view app =
|
|
28
|
+
let
|
|
29
|
+
optimisticProduct : Maybe Product
|
|
30
|
+
optimisticProduct =
|
|
31
|
+
case app.navigation of
|
|
32
|
+
Just (Navigation.Submitting formData) ->
|
|
33
|
+
formHandler
|
|
34
|
+
|> Form.Handler.run formData
|
|
35
|
+
|> Form.toResult
|
|
36
|
+
|> Result.toMaybe
|
|
37
|
+
|
|
38
|
+
Just (Navigation.LoadAfterSubmit formData path _) ->
|
|
39
|
+
formHandler
|
|
40
|
+
|> Form.Handler.run formData
|
|
41
|
+
|> Form.toResult
|
|
42
|
+
|> Result.toMaybe
|
|
43
|
+
|
|
44
|
+
Nothing ->
|
|
45
|
+
Nothing
|
|
46
|
+
in
|
|
47
|
+
-- our `productsView` function could show a loading spinner (Pending UI),
|
|
48
|
+
-- or it could assume the product will be created successfully (Optimistic UI) and
|
|
49
|
+
-- display it as a regular product in the list
|
|
50
|
+
productsView optimisticProduct app.data.products
|
|
51
|
+
|
|
52
|
+
allForms : Form.Handler.Handler String Product
|
|
53
|
+
allForms =
|
|
54
|
+
Form.Handler.init identity productForm
|
|
55
|
+
|
|
56
|
+
editItemForm : Form.HtmlForm String Product input msg
|
|
57
|
+
editItemForm =
|
|
58
|
+
Debug.todo "Form definition here"
|
|
59
|
+
|
|
60
|
+
@docs Navigation, LoadingState
|
|
61
|
+
|
|
62
|
+
-}
|
|
63
|
+
|
|
64
|
+
import Pages.FormData exposing (FormData)
|
|
65
|
+
import UrlPath exposing (UrlPath)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
{-| Represents the global page navigation state of the app.
|
|
69
|
+
|
|
70
|
+
- `Loading` - navigating to a page, for example from a link click, or from a programmatic navigation with `Browser.Navigation.pushUrl`.
|
|
71
|
+
- `Submitting` - submitting a form using the default submission strategy (note that Forms rendered with the [`Pages.Form.withConcurrent`](Pages-Form#withConcurrent) Option have their state managed in `app.concurrentSubmissions` instead of `app.navigation`).
|
|
72
|
+
- `LoadAfterSubmit` - the state immediately after `Submitting` - allows you to continue using the `FormData` from a submission while a data reload or redirect is occurring.
|
|
73
|
+
|
|
74
|
+
-}
|
|
75
|
+
type Navigation
|
|
76
|
+
= Submitting FormData
|
|
77
|
+
| LoadAfterSubmit FormData UrlPath LoadingState
|
|
78
|
+
| Loading UrlPath LoadingState
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
{-| -}
|
|
82
|
+
type LoadingState
|
|
83
|
+
= Redirecting
|
|
84
|
+
| Load
|
|
85
|
+
| ActionRedirect
|
package/src/Pages/PageUrl.elm
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
module Pages.PageUrl exposing
|
|
1
|
+
module Pages.PageUrl exposing
|
|
2
|
+
( PageUrl, toUrl
|
|
3
|
+
, parseQueryParams
|
|
4
|
+
)
|
|
2
5
|
|
|
3
|
-
{-| Same as a Url in `elm/url`, but slightly more structured. The path portion of the URL is parsed into a
|
|
4
|
-
the query params
|
|
5
|
-
|
|
6
|
-
Because `elm-pages` takes care of the main routing for pages in your app, the standard Elm URL parser API isn't suited
|
|
7
|
-
to parsing query params individually, which is why the structure of these types is different.
|
|
6
|
+
{-| Same as a Url in `elm/url`, but slightly more structured. The path portion of the URL is parsed into a `List String` representing each segment, and
|
|
7
|
+
the query params are parsed into a `Dict String (List String)`.
|
|
8
8
|
|
|
9
9
|
@docs PageUrl, toUrl
|
|
10
10
|
|
|
11
|
+
@docs parseQueryParams
|
|
12
|
+
|
|
11
13
|
-}
|
|
12
14
|
|
|
13
|
-
import
|
|
14
|
-
import QueryParams
|
|
15
|
+
import Dict exposing (Dict)
|
|
16
|
+
import QueryParams
|
|
15
17
|
import Url
|
|
18
|
+
import UrlPath exposing (UrlPath)
|
|
16
19
|
|
|
17
20
|
|
|
18
21
|
{-| -}
|
|
@@ -20,8 +23,8 @@ type alias PageUrl =
|
|
|
20
23
|
{ protocol : Url.Protocol
|
|
21
24
|
, host : String
|
|
22
25
|
, port_ : Maybe Int
|
|
23
|
-
, path :
|
|
24
|
-
, query :
|
|
26
|
+
, path : UrlPath
|
|
27
|
+
, query : Dict String (List String)
|
|
25
28
|
, fragment : Maybe String
|
|
26
29
|
}
|
|
27
30
|
|
|
@@ -32,7 +35,18 @@ toUrl url =
|
|
|
32
35
|
{ protocol = url.protocol
|
|
33
36
|
, host = url.host
|
|
34
37
|
, port_ = url.port_
|
|
35
|
-
, path = url.path |>
|
|
36
|
-
, query =
|
|
38
|
+
, path = url.path |> UrlPath.toRelative
|
|
39
|
+
, query =
|
|
40
|
+
if url.query |> Dict.isEmpty then
|
|
41
|
+
Nothing
|
|
42
|
+
|
|
43
|
+
else
|
|
44
|
+
url.query |> QueryParams.toString |> Just
|
|
37
45
|
, fragment = url.fragment
|
|
38
46
|
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
{-| -}
|
|
50
|
+
parseQueryParams : String -> Dict String (List String)
|
|
51
|
+
parseQueryParams =
|
|
52
|
+
QueryParams.fromString
|
|
@@ -1,32 +1,34 @@
|
|
|
1
|
-
module Pages.ProgramConfig exposing (ProgramConfig)
|
|
1
|
+
module Pages.ProgramConfig exposing (FormData, ProgramConfig)
|
|
2
2
|
|
|
3
3
|
import ApiRoute
|
|
4
|
+
import BackendTask exposing (BackendTask)
|
|
4
5
|
import Browser.Navigation
|
|
5
6
|
import Bytes exposing (Bytes)
|
|
6
7
|
import Bytes.Decode
|
|
7
8
|
import Bytes.Encode
|
|
8
|
-
import DataSource exposing (DataSource)
|
|
9
9
|
import Dict exposing (Dict)
|
|
10
|
-
import
|
|
10
|
+
import FatalError exposing (FatalError)
|
|
11
|
+
import Form
|
|
11
12
|
import Head
|
|
12
13
|
import Html exposing (Html)
|
|
13
14
|
import Http
|
|
14
15
|
import Json.Decode as Decode
|
|
15
16
|
import Json.Encode
|
|
16
17
|
import PageServerResponse exposing (PageServerResponse)
|
|
18
|
+
import Pages.ConcurrentSubmission
|
|
17
19
|
import Pages.Fetcher
|
|
18
20
|
import Pages.Flags
|
|
19
|
-
import Pages.FormState
|
|
20
21
|
import Pages.Internal.NotFoundReason exposing (NotFoundReason)
|
|
21
22
|
import Pages.Internal.Platform.ToJsPayload
|
|
22
23
|
import Pages.Internal.ResponseSketch exposing (ResponseSketch)
|
|
23
24
|
import Pages.Internal.RoutePattern exposing (RoutePattern)
|
|
24
|
-
import Pages.
|
|
25
|
+
import Pages.Navigation
|
|
25
26
|
import Pages.PageUrl exposing (PageUrl)
|
|
26
27
|
import Pages.SiteConfig exposing (SiteConfig)
|
|
27
|
-
import
|
|
28
|
-
import
|
|
28
|
+
import PagesMsg exposing (PagesMsg)
|
|
29
|
+
import Server.Request
|
|
29
30
|
import Url exposing (Url)
|
|
31
|
+
import UrlPath exposing (UrlPath)
|
|
30
32
|
|
|
31
33
|
|
|
32
34
|
type alias ProgramConfig userMsg userModel route pageData actionData sharedData effect mappedMsg errorPage =
|
|
@@ -38,7 +40,7 @@ type alias ProgramConfig userMsg userModel route pageData actionData sharedData
|
|
|
38
40
|
->
|
|
39
41
|
Maybe
|
|
40
42
|
{ path :
|
|
41
|
-
{ path :
|
|
43
|
+
{ path : UrlPath
|
|
42
44
|
, query : Maybe String
|
|
43
45
|
, fragment : Maybe String
|
|
44
46
|
}
|
|
@@ -46,18 +48,18 @@ type alias ProgramConfig userMsg userModel route pageData actionData sharedData
|
|
|
46
48
|
, pageUrl : Maybe PageUrl
|
|
47
49
|
}
|
|
48
50
|
-> ( userModel, effect )
|
|
49
|
-
, update :
|
|
50
|
-
, subscriptions : route ->
|
|
51
|
-
, sharedData :
|
|
52
|
-
, data : route ->
|
|
53
|
-
, action : route ->
|
|
51
|
+
, update : Form.Model -> Dict String (Pages.ConcurrentSubmission.ConcurrentSubmission actionData) -> Maybe Pages.Navigation.Navigation -> sharedData -> pageData -> Maybe Browser.Navigation.Key -> userMsg -> userModel -> ( userModel, effect )
|
|
52
|
+
, subscriptions : route -> UrlPath -> userModel -> Sub userMsg
|
|
53
|
+
, sharedData : BackendTask FatalError sharedData
|
|
54
|
+
, data : Server.Request.Request -> route -> BackendTask FatalError (PageServerResponse pageData errorPage)
|
|
55
|
+
, action : Server.Request.Request -> route -> BackendTask FatalError (PageServerResponse actionData errorPage)
|
|
54
56
|
, onActionData : actionData -> Maybe userMsg
|
|
55
57
|
, view :
|
|
56
|
-
|
|
57
|
-
-> Dict String (Pages.
|
|
58
|
-
-> Maybe Pages.
|
|
58
|
+
Form.Model
|
|
59
|
+
-> Dict String (Pages.ConcurrentSubmission.ConcurrentSubmission actionData)
|
|
60
|
+
-> Maybe Pages.Navigation.Navigation
|
|
59
61
|
->
|
|
60
|
-
{ path :
|
|
62
|
+
{ path : UrlPath
|
|
61
63
|
, route : route
|
|
62
64
|
}
|
|
63
65
|
-> Maybe PageUrl
|
|
@@ -65,11 +67,11 @@ type alias ProgramConfig userMsg userModel route pageData actionData sharedData
|
|
|
65
67
|
-> pageData
|
|
66
68
|
-> Maybe actionData
|
|
67
69
|
->
|
|
68
|
-
{ view : userModel -> { title : String, body : List (Html (
|
|
70
|
+
{ view : userModel -> { title : String, body : List (Html (PagesMsg userMsg)) }
|
|
69
71
|
, head : List Head.Tag
|
|
70
72
|
}
|
|
71
|
-
, handleRoute : route ->
|
|
72
|
-
, getStaticRoutes :
|
|
73
|
+
, handleRoute : route -> BackendTask FatalError (Maybe NotFoundReason)
|
|
74
|
+
, getStaticRoutes : BackendTask FatalError (List route)
|
|
73
75
|
, urlToRoute : Url -> route
|
|
74
76
|
, routeToPath : route -> List String
|
|
75
77
|
, site : Maybe SiteConfig
|
|
@@ -81,7 +83,7 @@ type alias ProgramConfig userMsg userModel route pageData actionData sharedData
|
|
|
81
83
|
{ protocol : Url.Protocol
|
|
82
84
|
, host : String
|
|
83
85
|
, port_ : Maybe Int
|
|
84
|
-
, path :
|
|
86
|
+
, path : UrlPath
|
|
85
87
|
, query : Maybe String
|
|
86
88
|
, fragment : Maybe String
|
|
87
89
|
, metadata : route
|
|
@@ -101,7 +103,7 @@ type alias ProgramConfig userMsg userModel route pageData actionData sharedData
|
|
|
101
103
|
, encodeResponse : ResponseSketch pageData actionData sharedData -> Bytes.Encode.Encoder
|
|
102
104
|
, encodeAction : actionData -> Bytes.Encode.Encoder
|
|
103
105
|
, decodeResponse : Bytes.Decode.Decoder (ResponseSketch pageData actionData sharedData)
|
|
104
|
-
, globalHeadTags : Maybe ((Maybe { indent : Int, newLines : Bool } -> Html Never -> String) ->
|
|
106
|
+
, globalHeadTags : Maybe ((Maybe { indent : Int, newLines : Bool } -> Html Never -> String) -> BackendTask FatalError (List Head.Tag))
|
|
105
107
|
, cmdToEffect : Cmd userMsg -> effect
|
|
106
108
|
, perform :
|
|
107
109
|
{ fetchRouteData :
|
|
@@ -127,3 +129,11 @@ type alias ProgramConfig userMsg userModel route pageData actionData sharedData
|
|
|
127
129
|
, errorPageToData : errorPage -> pageData
|
|
128
130
|
, notFoundRoute : route
|
|
129
131
|
}
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
type alias FormData =
|
|
135
|
+
{ fields : List ( String, String )
|
|
136
|
+
, method : Form.Method
|
|
137
|
+
, action : String
|
|
138
|
+
, id : Maybe String
|
|
139
|
+
}
|