1
1
module Demo exposing (init , update , view )
2
2
3
3
import Browser exposing (Document )
4
- import Html exposing (Html , div , h3 , h4 , pre , text )
4
+ import Html exposing (Html , div , span , text )
5
5
import Html.Attributes exposing (class , classList , style )
6
6
import Html.Events exposing (onClick )
7
7
import Json.Encode as Encode exposing (Value )
8
8
import Json.Form
9
9
import Json.Form.Config exposing (TextFieldStyle (..) )
10
10
import Json.Schema.Definitions exposing (Schema )
11
11
import Json.Value exposing (JsonValue (..) )
12
- import Snippets exposing (Snippet (..) , getSnippet , getSnippetTitle )
12
+ import Snippets exposing (Example , Snippet (..) , getSnippet , getSnippetTitle )
13
+
14
+
15
+ type alias ExampleDemo =
16
+ { form : Json . Form . Model
17
+ , example : Example
18
+ }
13
19
14
20
15
21
type alias Model =
16
22
{ showcase : Snippet
17
- , forms : List Json . Form . Model
23
+ , examples : List ExampleDemo
18
24
}
19
25
20
26
@@ -26,7 +32,7 @@ initialShowcase =
26
32
init : Value -> ( Model , Cmd Msg )
27
33
init _ =
28
34
{ showcase = initialShowcase
29
- , forms = []
35
+ , examples = []
30
36
}
31
37
|> update ( SetShowcase initialShowcase)
32
38
@@ -41,55 +47,57 @@ update message model =
41
47
case message of
42
48
JsonFormMsg index msg ->
43
49
let
44
- ( forms , cmds ) =
45
- model. forms
50
+ ( examples , cmds ) =
51
+ model. examples
46
52
|> List . indexedMap
47
- ( \ i form ->
53
+ ( \ i { form, example } ->
48
54
if i == index then
49
55
Json . Form . update msg form
50
56
|> Tuple . first
51
- |> Tuple . mapSecond ( Cmd . map ( JsonFormMsg index))
57
+ |> Tuple . mapFirst ( \ f -> { form = f, example = example } )
58
+ |> Tuple . mapSecond ( JsonFormMsg index |> Cmd . map)
52
59
53
60
else
54
- ( form, Cmd . none )
61
+ ( { form= form , example = example } , Cmd . none )
55
62
)
56
63
|> List . unzip
57
64
in
58
65
( { model
59
- | forms = forms
66
+ | examples = examples
60
67
}
61
68
, Cmd . batch cmds
62
69
)
63
70
64
71
SetShowcase s ->
65
72
let
66
- ( forms , cmds ) =
73
+ ( examples , cmds ) =
67
74
getSnippet s
68
75
|> List . indexedMap
69
- ( \ index schema ->
76
+ ( \ index example ->
70
77
let
71
78
config =
72
79
{ name = " form" ++ String . fromInt index
73
80
, dense = True
74
81
, textFieldStyle = Outlined
75
82
}
76
83
in
77
- Json . Form . init config schema Nothing
78
- |> Tuple . mapSecond ( Cmd . map ( JsonFormMsg index))
84
+ Json . Form . init config example. schema Nothing
85
+ |> Tuple . mapFirst ( \ form -> { form = form, example = example } )
86
+ |> Tuple . mapSecond ( JsonFormMsg index |> Cmd . map)
79
87
)
80
88
|> List . unzip
81
89
in
82
90
( { model
83
91
| showcase = s
84
- , forms = forms
92
+ , examples = examples
85
93
}
86
94
, Cmd . batch cmds
87
95
)
88
96
89
97
90
98
view : Model -> Document Msg
91
99
view model =
92
- { title = " Demo"
100
+ { title = " Json Form Demo"
93
101
, body =
94
102
[ topbar model
95
103
, content model
@@ -122,38 +130,113 @@ snippetTab activeSnippet snippet =
122
130
content : Model -> Html Msg
123
131
content model =
124
132
let
125
- generatedForm index form =
133
+ viewExample index { form, example } =
126
134
div [ class " example-section" ]
127
- [ div [ style " width" " 50%" , style " display" " inline-block" , style " max-width" " 300px" ]
128
- [ form
129
- |> Json . Form . view
130
- |> Html . map ( JsonFormMsg index)
131
- , form. value
132
- |> viewValue
135
+ [ Html . h3 [ class " example-section__heading" ] [ text example. title ]
136
+ , div [ class " example-section__content" ]
137
+ [ div [ style " display" " inline-block" , style " max-width" " 300px" , style " min-width" " 300px" ]
138
+ [ div [ style " padding" " 10px" , style " background" " var(--form-background)" ]
139
+ [ form
140
+ |> Json . Form . view
141
+ |> Html . map ( JsonFormMsg index)
142
+ ]
143
+ |> cardWithTitle " Form"
144
+ , form. value
145
+ |> Maybe . map viewValue
146
+ |> Maybe . withDefault ( text " " )
147
+ |> ( \ x -> div [ class " json-view" ] [ x ] )
148
+ |> cardWithTitle " Data"
149
+ |> ( \ x -> div [ style " margin-top" " 20px" ] [ x ] )
150
+ ]
151
+ , div [ style " width" " 100%" , style " min-width" " 300px" ] [ example. schema |> viewSchema ]
133
152
]
134
- , form. schema |> viewSchema
135
153
]
136
154
in
137
155
div [ class " app-content" ]
138
- [ h3 [ style " padding" " 8px" , style " border-bottom" " 1px solid #e8e8e8" ] [ text <| " Showcase: " ++ getSnippetTitle model. showcase ]
139
- , div []
140
- [ model. forms |> List . indexedMap generatedForm |> div []
141
- ]
156
+ [ model. examples |> List . indexedMap viewExample |> div []
142
157
]
143
158
144
159
145
- viewValue : Maybe JsonValue -> Html msg
160
+ viewValue : JsonValue -> Html msg
146
161
viewValue v =
162
+ let
163
+ str c =
164
+ Encode . string >> Encode . encode 0 >> val c
165
+
166
+ val c s =
167
+ span [ class <| " json-view__" ++ c ] [ text s ]
168
+ in
147
169
case v of
148
- Just val ->
170
+ NumericValue n ->
171
+ n
172
+ |> String . fromFloat
173
+ |> val " number"
174
+
175
+ NullValue ->
176
+ " null"
177
+ |> val " null"
178
+
179
+ BoolValue b ->
180
+ ( if b then
181
+ " true"
182
+
183
+ else
184
+ " false"
185
+ )
186
+ |> val " bool"
187
+
188
+ StringValue s ->
189
+ s |> str " string"
190
+
191
+ ObjectValue props ->
149
192
let
150
- code =
151
- val |> Json . Value . encode |> Encode . encode 2
193
+ lastIndex =
194
+ List . length props - 1
152
195
in
153
- Html . node " code-sample" [ class " schema-source" , Html . Attributes . attribute " code" code ] []
196
+ [ text " {"
197
+ , props
198
+ |> List . indexedMap
199
+ ( \ index ( key, vv ) ->
200
+ span []
201
+ [ key |> str " attr"
202
+ , text " : "
203
+ , viewValue vv
204
+ , if index == lastIndex then
205
+ text " \n "
154
206
155
- Nothing ->
156
- text " "
207
+ else
208
+ text " ,\n "
209
+ ]
210
+ )
211
+ |> div [ class " json-view__nested-props" ]
212
+ , text " }"
213
+ ]
214
+ |> span []
215
+
216
+ ArrayValue items ->
217
+ let
218
+ lastIndex =
219
+ List . length items - 1
220
+ in
221
+ [ text " ["
222
+ , items
223
+ |> List . indexedMap
224
+ ( \ index vv ->
225
+ span []
226
+ [ index |> String . fromInt |> val " attr"
227
+ , text " : "
228
+ , viewValue vv
229
+ , if index == lastIndex then
230
+ text " \n "
231
+
232
+ else
233
+ text " ,\n "
234
+ ]
235
+ )
236
+ |> div [ class " json-view__nested-props" ]
237
+ , text " ]"
238
+ ]
239
+ |> span []
157
240
158
241
159
242
viewSchema : Schema -> Html msg
@@ -162,6 +245,16 @@ viewSchema s =
162
245
code =
163
246
s
164
247
|> Json . Schema . Definitions . encode
165
- |> Encode . encode 2
248
+ |> Json . Value . decodeValue
166
249
in
167
- Html . node " code-sample" [ class " schema-source" , Html . Attributes . attribute " code" code ] []
250
+ viewValue code
251
+ |> ( \ x -> div [ class " json-view" ] [ x ] )
252
+ |> cardWithTitle " Schema"
253
+
254
+
255
+ cardWithTitle : String -> Html msg -> Html msg
256
+ cardWithTitle title cardContent =
257
+ div [ class " card" , style " width" " 100%" ]
258
+ [ span [ class " card__title" ] [ text title ]
259
+ , cardContent
260
+ ]
0 commit comments