this repo has no description
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

simplify demo site

don’t try and keep track of all three form types. tests can verify they are the same. show just focus on showing 1 type of form at a time.

+530 -757
+7
formz/src/formz/field.gleam
··· 131 131 Field(..field, input: input.set_help_text(field.input, help_text)) 132 132 } 133 133 134 + pub fn set_widget( 135 + field: Field(format, b), 136 + widget: fn(Input(format), input.WidgetArgs) -> format, 137 + ) -> Field(format, b) { 138 + Field(..field, input: input.set_widget(field.input, widget)) 139 + } 140 + 134 141 pub fn set_value(field: Field(format, b), value: String) -> Field(format, b) { 135 142 Field(..field, input: input.set_value(field.input, value)) 136 143 }
+1 -1
formz/src/formz/string_generator/simple.gleam
··· 22 22 } 23 23 24 24 pub fn generate_visible_field(f: Input(String)) -> String { 25 - let label_el = "<label>" <> f.label <> ": </label>" 25 + let label_el = "<label for=\"" <> f.name <> "\">" <> f.label <> ": </label>" 26 26 let description_el = case string.is_empty(f.help_text) { 27 27 True -> "" 28 28 False -> "<span class=\"description\">" <> f.help_text <> "</span>"
-36
formz_demo/copy_forms.sh
··· 1 - 2 - 3 - # Check if a directory name is provided 4 - if [ -z "$1" ]; then 5 - echo "Usage: $0 directory" 6 - exit 1 7 - fi 8 - 9 - directory=$1 10 - 11 - # Check if the provided argument is a directory 12 - if [ ! -d "$directory" ]; then 13 - echo "Error: $directory is not a directory" 14 - exit 1 15 - fi 16 - 17 - # Loop through all files in the directory 18 - for exampledir in "$directory"/*; do 19 - if [ -d "$exampledir" ]; then 20 - string_file="$exampledir/strings.gleam" 21 - lustre_file="$exampledir/lustre.gleam" 22 - nakai_file="$exampledir/nakai.gleam" 23 - 24 - # echo $string_file 25 - # echo $lustre_file 26 - # echo $nakai_file 27 - 28 - cp $string_file $lustre_file 29 - cp $string_file $nakai_file 30 - 31 - sed -i '' 's|formz/string_generator|formz_lustre|g' "$lustre_file" 32 - sed -i '' 's|formz/string_generator|formz_nakai|g' "$nakai_file" 33 - 34 - echo "copied $string_file" 35 - fi 36 - done
+2
formz_demo/gleam.toml
··· 24 24 lustre = ">= 4.5.1 and < 5.0.0" 25 25 nakai = ">= 1.0.0 and < 2.0.0" 26 26 simplifile = ">= 2.2.0 and < 3.0.0" 27 + justin = ">= 1.0.1 and < 2.0.0" 28 + pprint = ">= 1.0.3 and < 2.0.0" 27 29 28 30 [dev-dependencies] 29 31 gleeunit = ">= 1.0.0 and < 2.0.0"
+4
formz_demo/manifest.toml
··· 10 10 { name = "formz", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "justin"], source = "local", path = "../formz" }, 11 11 { name = "formz_lustre", version = "1.0.0", build_tools = ["gleam"], requirements = ["formz", "gleam_stdlib", "lustre"], source = "local", path = "../formz_lustre" }, 12 12 { name = "formz_nakai", version = "1.0.0", build_tools = ["gleam"], requirements = ["formz", "gleam_stdlib", "nakai"], source = "local", path = "../formz_nakai" }, 13 + { name = "glam", version = "2.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glam", source = "hex", outer_checksum = "66EC3BCD632E51EED029678F8DF419659C1E57B1A93D874C5131FE220DFAD2B2" }, 13 14 { name = "gleam_crypto", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "8AE56026B3E05EBB1F076778478A762E9EB62B31AEEB4285755452F397029D22" }, 14 15 { name = "gleam_erlang", version = "0.27.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "DE468F676D71B313C6C8C5334425CFCF827837333F8AB47B64D8A6D7AA40185D" }, 15 16 { name = "gleam_http", version = "3.7.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "EA66440C2269F7CED0F6845E5BD0DB68095775D627FA709A841CA78A398D6D56" }, ··· 27 28 { name = "mist", version = "3.0.0", build_tools = ["gleam"], requirements = ["birl", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "CDA1A74E768419235E16886463EC4722EFF4AB3F8D820A76EAD45D7C167D7282" }, 28 29 { name = "nakai", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "nakai", source = "hex", outer_checksum = "FD55B7926640FFD21FCC048D7E21752ED94FD424E1A731DC5C9DFB9928007F08" }, 29 30 { name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" }, 31 + { name = "pprint", version = "1.0.3", build_tools = ["gleam"], requirements = ["glam", "gleam_stdlib"], otp_app = "pprint", source = "hex", outer_checksum = "76BBB92E23D12D954BD452686543F29EDE8EBEBB7FC0ACCBCA66EEF276EC3A06" }, 30 32 { name = "ranger", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "ranger", source = "hex", outer_checksum = "1566C272B1D141B3BBA38B25CB761EF56E312E79EC0E2DFD4D3C19FB0CC1F98C" }, 31 33 { name = "simplifile", version = "2.2.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0DFABEF7DC7A9E2FF4BB27B108034E60C81BEBFCB7AB816B9E7E18ED4503ACD8" }, 32 34 { name = "telemetry", version = "1.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "telemetry", source = "hex", outer_checksum = "7015FC8919DBE63764F4B4B87A95B7C0996BD539E0D499BE6EC9D7F3875B79E6" }, ··· 42 44 gleam_http = { version = ">= 3.7.0 and < 4.0.0" } 43 45 gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" } 44 46 gleeunit = { version = ">= 1.0.0 and < 2.0.0" } 47 + justin = { version = ">= 1.0.1 and < 2.0.0" } 45 48 lustre = { version = ">= 4.5.1 and < 5.0.0" } 46 49 mist = { version = ">= 3.0.0 and < 4.0.0" } 47 50 nakai = { version = ">= 1.0.0 and < 2.0.0" } 51 + pprint = { version = ">= 1.0.3 and < 2.0.0" } 48 52 simplifile = { version = ">= 2.2.0 and < 3.0.0" } 49 53 wisp = { version = ">= 1.2.0 and < 2.0.0" }
-109
formz_demo/priv/static/highlight-gleam.mjs
··· 1 - function gleam(hljs) { 2 - const KEYWORDS = { 3 - className: "keyword", 4 - beginKeywords: 5 - "as assert auto case const delegate derive echo else fn if " + 6 - "implement import let macro opaque panic pub test todo type use", 7 - }; 8 - const STRING = { 9 - className: "string", 10 - variants: [{ begin: /"/, end: /"/ }], 11 - contains: [hljs.BACKSLASH_ESCAPE], 12 - relevance: 0, 13 - }; 14 - const NAME = { 15 - className: "variable", 16 - begin: "\\b[a-z][a-z0-9_]*\\b", 17 - relevance: 0, 18 - }; 19 - const DISCARD_NAME = { 20 - className: "comment", 21 - begin: "\\b_[a-z][a-z0-9_]*\\b", 22 - relevance: 0, 23 - }; 24 - const NUMBER = { 25 - className: "number", 26 - variants: [ 27 - { 28 - // binary 29 - begin: "\\b0[bB](?:_?[01]+)+", 30 - }, 31 - { 32 - // octal 33 - begin: "\\b0[oO](?:_?[0-7]+)+", 34 - }, 35 - { 36 - // hex 37 - begin: "\\b0[xX](?:_?[0-9a-fA-F]+)+", 38 - }, 39 - { 40 - // dec, float 41 - begin: "\\b\\d(?:_?\\d+)*(?:\\.(?:\\d(?:_?\\d+)*)*)?", 42 - }, 43 - ], 44 - relevance: 0, 45 - }; 46 - 47 - return { 48 - name: "Gleam", 49 - aliases: ["gleam"], 50 - contains: [ 51 - hljs.C_LINE_COMMENT_MODE, 52 - STRING, 53 - { 54 - // bit array 55 - begin: "<<", 56 - end: ">>", 57 - contains: [ 58 - { 59 - className: "keyword", 60 - beginKeywords: 61 - "binary bits bytes int float bit_string bit_array bits utf8 utf16 " + 62 - "utf32 utf8_codepoint utf16_codepoint utf32_codepoint signed " + 63 - "unsigned big little native unit size", 64 - }, 65 - KEYWORDS, 66 - STRING, 67 - NAME, 68 - DISCARD_NAME, 69 - NUMBER, 70 - ], 71 - relevance: 10, 72 - }, 73 - { 74 - className: "function", 75 - beginKeywords: "fn", 76 - end: "\\(", 77 - excludeEnd: true, 78 - contains: [ 79 - { 80 - className: "title", 81 - begin: "[a-z][a-z0-9_]*\\w*", 82 - relevance: 0, 83 - }, 84 - ], 85 - }, 86 - { 87 - className: "attribute", 88 - begin: "@", 89 - end: "\\(", 90 - excludeEnd: true, 91 - }, 92 - KEYWORDS, 93 - { 94 - // Type names and constructors 95 - className: "title", 96 - begin: "\\b[A-Z][A-Za-z0-9]*\\b", 97 - relevance: 0, 98 - }, 99 - { 100 - className: "operator", 101 - begin: "[+\\-*/%!=<>&|.]+", 102 - relevance: 0, 103 - }, 104 - NAME, 105 - DISCARD_NAME, 106 - NUMBER, 107 - ], 108 - }; 109 - }
+70 -82
formz_demo/priv/static/stylesheet.css
··· 7 7 8 8 .container { 9 9 display: grid; 10 - grid-template-columns: auto minmax(300px, 600px); 10 + grid-template-columns: 60% auto; 11 11 grid-template-rows: auto; 12 12 grid-template-areas: 13 - "forms forms" 13 + "forms post" 14 14 "code post" 15 15 ; 16 16 width: 100%; 17 17 } 18 18 19 - .code { 20 - grid-area: code; 21 - float; 22 - white-space: pre; 23 - margin: 0 7px 20px; 24 - 25 - code { 26 - font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace; 27 - font-weight: normal; 28 - font-size: 1.1em; 29 - } 30 - } 31 - 32 19 .post { 33 - > div { 34 - margin: 0 7px 20px; 35 20 grid-area: post; 36 21 37 22 > div { 38 - font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace; 39 - min-height: 18px; 40 - } 23 + margin: 0 7px 20px; 41 24 42 - > div.success { 43 - padding: 10px; 44 - background: #90EE90; 45 - } 25 + > div { 26 + font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace; 27 + min-height: 18px; 28 + } 46 29 47 - > div.error { 48 - padding: 10px; 49 - background: #FF5733; 50 - } 30 + > div.success { 31 + padding: 10px; 32 + background: #90EE90; 33 + white-space: pre-wrap; 34 + } 51 35 52 - h2 { 53 - background: #444; 54 - color: #fafafa; 55 - padding: 5px; 56 - margin: 0; 57 - font-size: 12px; 58 - text-transform: uppercase; 59 - font-weight: normal; 60 - } 36 + > div.error { 37 + padding: 10px; 38 + background: #FF5733; 39 + } 61 40 62 - h2.discrepancy { 63 - position: relative; 64 - backdground: pink; 65 - } 66 - h2.discrepancy:after{ 67 - content: 'uh oh'; 68 - position: absolute; 69 - right: 1em; 70 - color: red; 71 - font-weight: bold; 41 + h2 { 42 + background: #444; 43 + color: #fafafa; 44 + padding: 5px; 45 + margin: 0; 46 + font-size: 12px; 47 + text-transform: uppercase; 48 + font-weight: normal; 49 + } 72 50 } 73 - } 74 - } 51 + table.input_data { 52 + border-spacing: 0; 53 + border-collapse: collapse; 54 + width: 100%; 75 55 76 - table.input_data { 77 - border-spacing: 0; 78 - border-collapse: collapse; 79 - width: 100%; 56 + th { 57 + text-align: left; 58 + font-weight: normal; 59 + background: #bbb; 60 + padding: 10px; 61 + } 80 62 81 - th { 82 - text-align: left; 83 - font-weight: normal; 84 - background: #bbb; 85 - padding: 10px; 63 + td:nth-child(1), td:nth-child(2) { 64 + font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace; 65 + } 66 + td:nth-child(3) { 67 + color: #bd2901; 68 + } 69 + td { 70 + background: #eee; 71 + padding: 10px; 72 + } 73 + } 86 74 } 87 75 88 - td:nth-child(1), td:nth-child(2) { 89 - font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace; 90 - } 91 - td:nth-child(3) { 92 - color: #bd2901; 93 - } 94 - td { 95 - background: #eee; 96 - padding: 10px; 76 + .form { 77 + grid-area: forms; 78 + padding: 0 13px; 79 + background: #f3f3f3; 80 + margin: 0 7px 15px; 97 81 } 98 - } 99 82 100 - table.forms { 101 - width: 100%; 102 - border-spacing: 7px 0; 103 - grid-area: forms; 104 - margin-bottom: 17px; 83 + .code { 84 + grid-area: code; 85 + margin: 0 7px 20px; 105 86 106 - th { 107 - text-align: left; 108 - font-weight: normal; 109 - background: #bbb; 110 - padding: 10px; 87 + h2 { 88 + margin: 0; 89 + padding: 5px; 90 + font-size: 13px; 91 + background: #ddd; 92 + } 93 + pre { 94 + margin-top: 0; 95 + background-color: #f3f3f3; 96 + padding: 10px; 97 + } 98 + code { 99 + font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace; 100 + font-weight: normal; 101 + font-size: 1em; 102 + } 111 103 } 112 104 113 - td { 114 - background: #eee; 115 - padding: 10px; 116 - } 117 105 }
+49
formz_demo/src/formz_demo/example/defaults.gleam
··· 1 + import formz/formz_use as formz 2 + import formz/string_generator/simple 3 + import formz_lustre/simple as lustre_simple 4 + import formz_nakai/simple as nakai_simple 5 + import lustre/element 6 + import nakai 7 + import nakai/html 8 + import wisp 9 + 10 + pub fn handle_get( 11 + form: formz.Form(format, output), 12 + ) -> formz.Form(format, output) { 13 + form 14 + } 15 + 16 + pub fn handle_post( 17 + formdata: wisp.FormData, 18 + form: formz.Form(format, output), 19 + ) -> Result(output, formz.Form(format, output)) { 20 + form 21 + |> formz.data(formdata.values) 22 + |> formz.parse() 23 + } 24 + 25 + pub fn format_string_form(form: formz.Form(String, output)) -> String { 26 + simple.generate_form(form) 27 + } 28 + 29 + pub fn format_lustre_form( 30 + form: formz.Form(element.Element(msg), output), 31 + ) -> element.Element(msg) { 32 + lustre_simple.generate_form(form) 33 + } 34 + 35 + pub fn format_nakai_form(form: formz.Form(html.Node, output)) -> html.Node { 36 + nakai_simple.generate_form(form) 37 + } 38 + 39 + pub fn formatted_string_form_to_string(str) -> String { 40 + str 41 + } 42 + 43 + pub fn formatted_lustre_form_to_string(element: element.Element(msg)) -> String { 44 + element.to_string(element) 45 + } 46 + 47 + pub fn formatted_nakai_form_to_string(node: html.Node) -> String { 48 + nakai.to_inline_string(node) 49 + }
+81 -167
formz_demo/src/formz_demo/example/page.gleam
··· 1 1 import formz/formz_use as formz 2 - import formz/string_generator/simple as simple_string 3 - import formz_lustre/simple as simple_lustre 4 - import formz_nakai/simple as simple_nakai 2 + import formz/input 5 3 import gleam/list 6 4 import gleam/option 7 5 import gleam/result 8 6 import gleam/string 7 + import justin 9 8 import lustre/attribute 10 9 import lustre/element 11 10 import lustre/element/html.{html} 12 - import nakai 13 - import nakai/html as nhtml 11 + import pprint 14 12 import wisp.{type Response} 15 13 16 14 pub fn build_page( ··· 18 16 code: String, 19 17 post_data: option.Option(List(#(String, String))), 20 18 output: option.Option(a), 21 - string_form: formz.Form(String, a), 22 - lustre_form: formz.Form(element.Element(msg), a), 23 - nakai_form: formz.Form(nhtml.Node, a), 24 - has_output_discrepancy: Bool, 25 - has_error_discrepancy: Bool, 19 + formyyyy: formz.Form(format, b), 20 + formatted_form: String, 26 21 ) -> Response { 27 22 let html = 28 23 html([], [ ··· 32 27 attribute.rel("stylesheet"), 33 28 attribute.href("/static/stylesheet.css"), 34 29 ]), 35 - html.link([ 36 - attribute.rel("stylesheet"), 37 - attribute.href( 38 - "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css", 39 - ), 40 - ]), 41 - html.script( 42 - [ 43 - attribute.src( 44 - "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js", 45 - ), 46 - ], 47 - "", 48 - ), 49 - html.script([attribute.src("/static/highlight-gleam.mjs")], ""), 50 - html.script( 51 - [], 52 - " 53 - hljs.registerLanguage('gleam', gleam); 54 - hljs.highlightAll(); 55 - ", 56 - ), 57 30 ]), 58 31 html.body([], [ 59 32 html.h1([], [ 60 33 html.a([attribute.href("/")], [html.text("Formz")]), 61 34 html.text(": "), 62 - html.a([attribute.href("")], [html.text(name)]), 35 + html.a([attribute.href("")], [html.text(justin.sentence_case(name))]), 63 36 ]), 64 37 html.div([attribute.class("container")], [ 65 - html.pre([attribute.class("code")], [ 66 - html.code([attribute.class("langauge-gleam")], [ 67 - html.text(code |> string.trim), 68 - ]), 69 - ]), 70 - post_data 71 - |> option.map(show_post( 72 - _, 73 - errors_list, 74 - output, 75 - has_output_discrepancy, 76 - has_error_discrepancy, 77 - )) 78 - |> option.unwrap(element.none()), 79 - show_forms(string_form, lustre_form, nakai_form), 38 + show_post(post_data, output, formyyyy), 39 + show_form(formatted_form), 40 + show_code(code), 80 41 ]), 81 42 ]), 82 43 ]) ··· 86 47 } 87 48 88 49 pub fn show_post( 89 - input_data: List(#(String, String)), 90 - errors: List(#(String, String)), 50 + input_data: option.Option(List(#(String, String))), 91 51 output: option.Option(a), 92 - has_output_discrepancy: Bool, 93 - has_error_discrepancy: Bool, 52 + form: formz.Form(format, b), 94 53 ) { 95 - let input_rows = 96 - element.fragment( 97 - input_data 98 - // |> list.reverse 99 - |> list.map(fn(t) { 100 - let #(key, value) = t 101 - let error = list.key_find(errors, key) |> result.unwrap("") 102 - html.tr([], [ 103 - html.td([], [html.text(key)]), 104 - html.td([], [html.text(string.inspect(value))]), 105 - html.td([], [html.text(error)]), 106 - ]) 107 - }), 108 - ) 109 - 110 - let errors_no_post = 111 - errors 112 - |> list.filter_map(fn(t) { 113 - let #(key, _) = t 114 - case list.key_find(input_data, key) { 115 - Ok(_) -> Error(Nil) 116 - Error(_) -> Ok(t) 117 - } 118 - }) 119 - 120 - let error_rows = case errors_no_post { 121 - [] -> element.none() 122 - _ -> 123 - element.fragment( 124 - list.map(errors_no_post, fn(t) { 125 - let #(key, value) = t 54 + case input_data { 55 + option.None -> element.none() 56 + option.Some(input_data) -> { 57 + let fields_no_post = 58 + form 59 + |> formz.get_inputs 60 + |> list.map(fn(i) { 126 61 html.tr([], [ 127 - html.td([], [html.text(key)]), 128 - html.td([], [html.text("<EMPTY>")]), 129 - html.td([], [html.text(value)]), 62 + html.td([], [html.text(i.name)]), 63 + html.td([], [ 64 + html.text( 65 + list.key_find(input_data, i.name) 66 + |> result.map(string.inspect) 67 + |> result.unwrap("<EMPTY>"), 68 + ), 69 + ]), 70 + html.td([], [ 71 + html.text(case i { 72 + input.Input(..) -> "" 73 + input.InvalidInput(error:, ..) -> error 74 + }), 75 + ]), 130 76 ]) 131 - }), 132 - ) 133 - } 134 - let output_row = case output { 135 - option.None -> "" 136 - option.Some(val) -> string.inspect(val) 137 - } 77 + }) 78 + |> element.fragment 138 79 139 - html.div([attribute.class("post")], [ 140 - html.div([], [ 141 - html.h2([attribute.classes([#("discrepancy", has_error_discrepancy)])], [ 142 - html.text("Post data"), 143 - ]), 144 - html.table([attribute.class("input_data")], [ 145 - html.tr([], [ 146 - html.th([], [html.text("Key")]), 147 - html.th([], [html.text("Input value")]), 148 - html.th([], [html.text("Error")]), 149 - ]), 150 - input_rows, 151 - error_rows, 152 - ]), 153 - html.h2([attribute.classes([#("discrepancy", has_output_discrepancy)])], [ 154 - html.text("Output"), 155 - ]), 156 - html.div( 157 - [ 158 - attribute.classes([ 159 - #("success", option.is_some(output)), 160 - #("error", option.is_none(output)), 161 - ]), 162 - ], 163 - [html.text(output_row)], 164 - ), 165 - ]), 166 - ]) 167 - } 80 + let output_row = case output { 81 + option.None -> "" 82 + option.Some(val) -> { 83 + let str = string.inspect(val) 84 + case string.length(str) { 85 + x if x < 50 -> str 86 + _ -> pprint.format(val) 87 + } 88 + } 89 + } 168 90 169 - fn show_forms( 170 - string_form: formz.Form(String, j), 171 - lustre_form: formz.Form(element.Element(msg), j), 172 - nakai_form: formz.Form(nhtml.Node, j), 173 - ) -> element.Element(msg) { 174 - html.table([attribute.classes([#("forms", True)])], [ 175 - html.tr([], [ 176 - html.th([attribute.style([#("width", "33.3%")])], [html.text("String")]), 177 - html.th([attribute.style([#("width", "33.3%")])], [html.text("Lustre")]), 178 - html.th([attribute.style([#("width", "33.3%")])], [html.text("Nakai")]), 179 - ]), 180 - html.tr([], [ 181 - html.td([], [ 182 - html.form([attribute.method("POST")], [ 183 - html.div( 184 - [ 185 - attribute.attribute( 186 - "dangerous-unescaped-html", 187 - simple_string.generate_form(string_form), 188 - ), 189 - ], 190 - [], 191 - ), 192 - html.p([], [ 193 - html.button([attribute.type_("submit")], [html.text("Submit")]), 91 + html.div([attribute.class("post")], [ 92 + html.div([], [ 93 + html.h2([], [html.text("Post data")]), 94 + html.table([attribute.class("input_data")], [ 95 + html.tr([], [ 96 + html.th([], [html.text("Key")]), 97 + html.th([], [html.text("Input value")]), 98 + html.th([], [html.text("Error")]), 99 + ]), 100 + // input_rows, 101 + fields_no_post, 194 102 ]), 195 - ]), 196 - ]), 197 - html.td([], [ 198 - html.form([attribute.method("POST")], [ 199 - simple_lustre.generate_form(lustre_form), 200 - html.p([], [ 201 - html.button([attribute.type_("submit")], [html.text("Submit")]), 202 - ]), 203 - ]), 204 - ]), 205 - html.td([], [ 206 - html.form([attribute.method("POST")], [ 103 + html.h2([], [html.text("Output")]), 207 104 html.div( 208 105 [ 209 - attribute.attribute( 210 - "dangerous-unescaped-html", 211 - simple_nakai.generate_form(nakai_form) |> nakai.to_string, 212 - ), 106 + attribute.classes([ 107 + #("success", option.is_some(output)), 108 + #("error", option.is_none(output)), 109 + ]), 213 110 ], 214 - [], 111 + [html.text(output_row)], 215 112 ), 216 - html.p([], [ 217 - html.button([attribute.type_("submit")], [html.text("Submit")]), 218 - ]), 219 113 ]), 114 + ]) 115 + } 116 + } 117 + } 118 + 119 + fn show_form(formatted_from: String) -> element.Element(msg) { 120 + html.form([attribute.method("POST"), attribute.class("form")], [ 121 + html.div( 122 + [attribute.attribute("dangerous-unescaped-html", formatted_from)], 123 + [], 124 + ), 125 + html.p([], [html.button([attribute.type_("submit")], [html.text("Submit")])]), 126 + ]) 127 + } 128 + 129 + fn show_code(code: String) -> element.Element(msg) { 130 + html.div([attribute.class("code")], [ 131 + html.pre([], [ 132 + html.code([attribute.class("langauge-gleam hljs")], [ 133 + html.text(code |> string.trim), 220 134 ]), 221 135 ]), 222 136 ])
+54 -73
formz_demo/src/formz_demo/example/run.gleam
··· 1 1 import formz/formz_use as formz 2 - import formz/input 3 2 import formz_demo/example/page 4 3 import gleam/http.{Get, Post} 5 - import gleam/list 6 4 import gleam/option 7 5 import simplifile 8 6 import wisp.{type Request, type Response} 9 7 10 - pub fn handle(req: Request, make_forms) -> Response { 8 + pub type ExampleRun(format, output, output2, msg) { 9 + ExampleRun( 10 + dir: String, 11 + make_form: fn() -> formz.Form(format, output), 12 + get_handler: fn(formz.Form(format, output)) -> formz.Form(format, output), 13 + post_handler: fn(wisp.FormData, formz.Form(format, output)) -> 14 + Result(output2, formz.Form(format, output)), 15 + format_form: fn(formz.Form(format, output)) -> format, 16 + formatted_form_to_string: fn(format) -> String, 17 + ) 18 + } 19 + 20 + pub fn handle( 21 + req: Request, 22 + example: ExampleRun(format, output, output2, msg), 23 + ) -> Response { 11 24 case req.method { 12 - Get -> handle_get(make_forms) 13 - Post -> handle_post(req, make_forms) 25 + Get -> handle_get(example) 26 + Post -> handle_post(req, example) 14 27 _ -> wisp.method_not_allowed(allowed: [Get, Post]) 15 28 } 16 29 } 17 30 18 - fn handle_get(make_forms) { 19 - let #(dir, name, string_form, lustre_form, nakai_form) = make_forms() 20 - let assert Ok(code) = 21 - simplifile.read("./src/formz_demo/examples/" <> dir <> "/strings.gleam") 31 + fn get_code(key: String) { 32 + let assert Ok(form_code) = 33 + simplifile.read("./src/formz_demo/examples/" <> key <> ".gleam") 34 + form_code 35 + } 36 + 37 + fn handle_get(example: ExampleRun(format, output, output2, msg)) { 38 + let form = example.make_form() |> example.get_handler 39 + 22 40 page.build_page( 23 - name, 24 - code, 41 + example.dir, 42 + get_code(example.dir), 25 43 option.None, 26 - [], 27 44 option.None, 28 - string_form, 29 - lustre_form, 30 - nakai_form, 31 - True, 32 - True, 45 + form, 46 + form 47 + |> example.format_form 48 + |> example.formatted_form_to_string, 33 49 ) 34 50 } 35 51 36 - fn handle_post(req: Request, make_forms) -> Response { 52 + fn handle_post( 53 + req: Request, 54 + example: ExampleRun(format, output, output2, msg), 55 + ) -> Response { 37 56 use formdata <- wisp.require_form(req) 38 57 39 - let #(dir, name, string_form, lustre_form, nakai_form) = make_forms() 58 + let form = 59 + example.make_form() 60 + |> example.post_handler(formdata, _) 40 61 41 - let assert Ok(code) = 42 - simplifile.read("./src/formz_demo/examples/" <> dir <> "/strings.gleam") 43 - 44 - let input_data = formdata.values 45 - 46 - let #(string_form, string_output, string_errors) = case 47 - string_form |> formz.data(input_data) |> formz.parse 48 - { 49 - Ok(r) -> #(string_form |> formz.data(input_data), option.Some(r), []) 50 - Error(f) -> #(f, option.None, get_errors(f)) 51 - } 52 - let #(lustre_form, lustre_output, lustre_errors) = case 53 - lustre_form |> formz.data(input_data) |> formz.parse 54 - { 55 - Ok(r) -> #(lustre_form |> formz.data(input_data), option.Some(r), []) 56 - Error(f) -> #(f, option.None, get_errors(f)) 57 - } 58 - let #(nakai_form, nakai_output, nakai_errors) = case 59 - nakai_form |> formz.data(input_data) |> formz.parse 60 - { 61 - Ok(r) -> #(nakai_form |> formz.data(input_data), option.Some(r), []) 62 - Error(f) -> #(f, option.None, get_errors(f)) 63 - } 64 - 65 - let has_output_discrepancy = case string_output, lustre_output, nakai_output { 66 - a, b, c if a == b && a == c -> False 67 - _, _, _ -> True 68 - } 69 - let has_error_discrepancy = case string_errors, lustre_errors, nakai_errors { 70 - a, b, c if a == b && a == c -> False 71 - _, _, _ -> True 62 + let #(form, form_output) = case form { 63 + Ok(r) -> #( 64 + example.make_form() |> formz.data(formdata.values), 65 + option.Some(r), 66 + ) 67 + Error(form_with_errors) -> #(form_with_errors, option.None) 72 68 } 73 69 74 70 page.build_page( 75 - name, 76 - code, 77 - option.Some(input_data), 78 - get_errors(string_form), 79 - string_output, 80 - string_form, 81 - lustre_form, 82 - nakai_form, 83 - has_output_discrepancy, 84 - has_error_discrepancy, 71 + example.dir, 72 + get_code(example.dir), 73 + option.Some(formdata.values), 74 + form_output, 75 + form, 76 + form 77 + |> example.format_form 78 + |> example.formatted_form_to_string, 85 79 ) 86 80 } 87 - 88 - fn get_errors( 89 - form: formz.Form(format, widget_args, a), 90 - ) -> List(#(String, String)) { 91 - form 92 - |> formz.get_inputs 93 - |> list.filter_map(fn(f) { 94 - case f { 95 - input.Input(..) -> Error(Nil) 96 - input.InvalidInput(error:, ..) -> Ok(#(f.name, error)) 97 - } 98 - }) 99 - }
+84
formz_demo/src/formz_demo/examples/all_the_inputs.gleam
··· 1 + import formz/field.{field} 2 + import formz/formz_use as formz 3 + import formz/input 4 + import formz/string_generator/fields 5 + 6 + pub fn make_form() { 7 + let choices = [#("Yes", True), #("Maybe", True), #("No", False)] 8 + 9 + use a <- formz.with(field("a", fields.text_field())) 10 + use b <- formz.with(field("b", fields.integer_field())) 11 + use c <- formz.with(field("c", fields.number_field())) 12 + use d <- formz.with(field("d", fields.boolean_field())) 13 + use e <- formz.with(field("e", fields.email_field())) 14 + use f <- formz.with(field("f", fields.hidden_field())) 15 + use g <- formz.with(field("g", fields.enum_field(letters()))) 16 + use h <- formz.with(field("h", fields.list_field(choices))) 17 + 18 + formz.create_form(#(a, b, c, d, e, f, g, h)) 19 + } 20 + 21 + pub fn handle_get(form) { 22 + form 23 + |> formz.update_input("f", input.set_value(_, "hidden")) 24 + } 25 + 26 + pub type Alphabet { 27 + A 28 + B 29 + C 30 + D 31 + E 32 + F 33 + G 34 + H 35 + I 36 + J 37 + K 38 + L 39 + M 40 + N 41 + O 42 + P 43 + Q 44 + R 45 + S 46 + T 47 + U 48 + V 49 + W 50 + X 51 + Y 52 + Z 53 + } 54 + 55 + pub fn letters() { 56 + [ 57 + #("A", A), 58 + #("B", B), 59 + #("C", C), 60 + #("D", D), 61 + #("E", E), 62 + #("F", F), 63 + #("G", G), 64 + #("H", H), 65 + #("I", I), 66 + #("J", J), 67 + #("K", K), 68 + #("L", L), 69 + #("M", M), 70 + #("N", N), 71 + #("O", O), 72 + #("P", P), 73 + #("Q", Q), 74 + #("R", R), 75 + #("S", S), 76 + #("T", T), 77 + #("U", U), 78 + #("V", V), 79 + #("W", W), 80 + #("X", X), 81 + #("Y", Y), 82 + #("Z", Z), 83 + ] 84 + }
-13
formz_demo/src/formz_demo/examples/example_1/example_1.gleam
··· 1 - import formz_demo/examples/example_1/lustre 2 - import formz_demo/examples/example_1/nakai 3 - import formz_demo/examples/example_1/strings 4 - 5 - pub fn make_forms() { 6 - #( 7 - "example_1", 8 - "Hello world", 9 - strings.make_form(), 10 - lustre.make_form(), 11 - nakai.make_form(), 12 - ) 13 - }
-8
formz_demo/src/formz_demo/examples/example_1/lustre.gleam
··· 1 - import formz/field.{field} 2 - import formz/formz_use as formz 3 - import formz_lustre/fields 4 - 5 - pub fn make_form() { 6 - use name <- formz.with(field("name", fields.text_field())) 7 - formz.create_form("Hello " <> name) 8 - }
-8
formz_demo/src/formz_demo/examples/example_1/nakai.gleam
··· 1 - import formz/field.{field} 2 - import formz/formz_use as formz 3 - import formz_nakai/fields 4 - 5 - pub fn make_form() { 6 - use name <- formz.with(field("name", fields.text_field())) 7 - formz.create_form("Hello " <> name) 8 - }
formz_demo/src/formz_demo/examples/example_1/strings.gleam formz_demo/src/formz_demo/examples/hello_world.gleam
-13
formz_demo/src/formz_demo/examples/example_2/example_2.gleam
··· 1 - import formz_demo/examples/example_2/lustre 2 - import formz_demo/examples/example_2/nakai 3 - import formz_demo/examples/example_2/strings 4 - 5 - pub fn make_forms() { 6 - #( 7 - "example_2", 8 - "All the inputs", 9 - strings.make_form(), 10 - lustre.make_form(), 11 - nakai.make_form(), 12 - ) 13 - }
-51
formz_demo/src/formz_demo/examples/example_2/lustre.gleam
··· 1 - import formz/field.{field} 2 - import formz/formz_use as formz 3 - import formz_lustre/fields 4 - import formz_demo/examples/example_2/types 5 - 6 - pub fn make_form() { 7 - use a <- formz.with(field("a", fields.text_field())) 8 - use b <- formz.with(field("b", fields.integer_field())) 9 - use c <- formz.with(field("c", fields.number_field())) 10 - use d <- formz.with(field("d", fields.boolean_field())) 11 - use e <- formz.with(field("e", fields.email_field())) 12 - use f <- formz.with(field("f", fields.enum_field(letters()))) 13 - use g <- formz.with(field("g", fields.list_field(choices()))) 14 - 15 - formz.create_form(#(a, b, c, d, e, f, g)) 16 - } 17 - 18 - fn letters() { 19 - [ 20 - #("A", types.A), 21 - #("B", types.B), 22 - #("C", types.C), 23 - #("D", types.D), 24 - #("E", types.E), 25 - #("F", types.F), 26 - #("G", types.G), 27 - #("H", types.H), 28 - #("I", types.I), 29 - #("J", types.J), 30 - #("K", types.K), 31 - #("L", types.L), 32 - #("M", types.M), 33 - #("N", types.N), 34 - #("O", types.O), 35 - #("P", types.P), 36 - #("Q", types.Q), 37 - #("R", types.R), 38 - #("S", types.S), 39 - #("T", types.T), 40 - #("U", types.U), 41 - #("V", types.V), 42 - #("W", types.W), 43 - #("X", types.X), 44 - #("Y", types.Y), 45 - #("Z", types.Z), 46 - ] 47 - } 48 - 49 - fn choices() { 50 - [#("Yes", True), #("Maybe", True), #("No", False)] 51 - }
-51
formz_demo/src/formz_demo/examples/example_2/nakai.gleam
··· 1 - import formz/field.{field} 2 - import formz/formz_use as formz 3 - import formz_nakai/fields 4 - import formz_demo/examples/example_2/types 5 - 6 - pub fn make_form() { 7 - use a <- formz.with(field("a", fields.text_field())) 8 - use b <- formz.with(field("b", fields.integer_field())) 9 - use c <- formz.with(field("c", fields.number_field())) 10 - use d <- formz.with(field("d", fields.boolean_field())) 11 - use e <- formz.with(field("e", fields.email_field())) 12 - use f <- formz.with(field("f", fields.enum_field(letters()))) 13 - use g <- formz.with(field("g", fields.list_field(choices()))) 14 - 15 - formz.create_form(#(a, b, c, d, e, f, g)) 16 - } 17 - 18 - fn letters() { 19 - [ 20 - #("A", types.A), 21 - #("B", types.B), 22 - #("C", types.C), 23 - #("D", types.D), 24 - #("E", types.E), 25 - #("F", types.F), 26 - #("G", types.G), 27 - #("H", types.H), 28 - #("I", types.I), 29 - #("J", types.J), 30 - #("K", types.K), 31 - #("L", types.L), 32 - #("M", types.M), 33 - #("N", types.N), 34 - #("O", types.O), 35 - #("P", types.P), 36 - #("Q", types.Q), 37 - #("R", types.R), 38 - #("S", types.S), 39 - #("T", types.T), 40 - #("U", types.U), 41 - #("V", types.V), 42 - #("W", types.W), 43 - #("X", types.X), 44 - #("Y", types.Y), 45 - #("Z", types.Z), 46 - ] 47 - } 48 - 49 - fn choices() { 50 - [#("Yes", True), #("Maybe", True), #("No", False)] 51 - }
-51
formz_demo/src/formz_demo/examples/example_2/strings.gleam
··· 1 - import formz/field.{field} 2 - import formz/formz_use as formz 3 - import formz/string_generator/fields 4 - import formz_demo/examples/example_2/types 5 - 6 - pub fn make_form() { 7 - use a <- formz.with(field("a", fields.text_field())) 8 - use b <- formz.with(field("b", fields.integer_field())) 9 - use c <- formz.with(field("c", fields.number_field())) 10 - use d <- formz.with(field("d", fields.boolean_field())) 11 - use e <- formz.with(field("e", fields.email_field())) 12 - use f <- formz.with(field("f", fields.enum_field(letters()))) 13 - use g <- formz.with(field("g", fields.list_field(choices()))) 14 - 15 - formz.create_form(#(a, b, c, d, e, f, g)) 16 - } 17 - 18 - fn letters() { 19 - [ 20 - #("A", types.A), 21 - #("B", types.B), 22 - #("C", types.C), 23 - #("D", types.D), 24 - #("E", types.E), 25 - #("F", types.F), 26 - #("G", types.G), 27 - #("H", types.H), 28 - #("I", types.I), 29 - #("J", types.J), 30 - #("K", types.K), 31 - #("L", types.L), 32 - #("M", types.M), 33 - #("N", types.N), 34 - #("O", types.O), 35 - #("P", types.P), 36 - #("Q", types.Q), 37 - #("R", types.R), 38 - #("S", types.S), 39 - #("T", types.T), 40 - #("U", types.U), 41 - #("V", types.V), 42 - #("W", types.W), 43 - #("X", types.X), 44 - #("Y", types.Y), 45 - #("Z", types.Z), 46 - ] 47 - } 48 - 49 - fn choices() { 50 - [#("Yes", True), #("Maybe", True), #("No", False)] 51 - }
-28
formz_demo/src/formz_demo/examples/example_2/types.gleam
··· 1 - pub type Alphabet { 2 - A 3 - B 4 - C 5 - D 6 - E 7 - F 8 - G 9 - H 10 - I 11 - J 12 - K 13 - L 14 - M 15 - N 16 - O 17 - P 18 - Q 19 - R 20 - S 21 - T 22 - U 23 - V 24 - W 25 - X 26 - Y 27 - Z 28 - }
-13
formz_demo/src/formz_demo/examples/example_3/example_3.gleam
··· 1 - import formz_demo/examples/example_3/lustre 2 - import formz_demo/examples/example_3/nakai 3 - import formz_demo/examples/example_3/strings 4 - 5 - pub fn make_forms() { 6 - #( 7 - "example_3", 8 - "Labels", 9 - strings.make_form(), 10 - lustre.make_form(), 11 - nakai.make_form(), 12 - ) 13 - }
-15
formz_demo/src/formz_demo/examples/example_3/lustre.gleam
··· 1 - import formz/field.{field} 2 - import formz/formz_use as formz 3 - import formz_lustre/fields 4 - 5 - pub fn make_form() { 6 - use name <- formz.with(field.full("name", "Name", "", fields.text_field())) 7 - use age <- formz.with(field.full("age", "Age", "", fields.integer_field())) 8 - 9 - use height <- formz.with( 10 - field("height", fields.integer_field()) 11 - |> field.set_label("Height (cm)"), 12 - ) 13 - 14 - formz.create_form(#(name, age, height)) 15 - }
-15
formz_demo/src/formz_demo/examples/example_3/nakai.gleam
··· 1 - import formz/field.{field} 2 - import formz/formz_use as formz 3 - import formz_nakai/fields 4 - 5 - pub fn make_form() { 6 - use name <- formz.with(field.full("name", "Name", "", fields.text_field())) 7 - use age <- formz.with(field.full("age", "Age", "", fields.integer_field())) 8 - 9 - use height <- formz.with( 10 - field("height", fields.integer_field()) 11 - |> field.set_label("Height (cm)"), 12 - ) 13 - 14 - formz.create_form(#(name, age, height)) 15 - }
formz_demo/src/formz_demo/examples/example_3/strings.gleam formz_demo/src/formz_demo/examples/labels.gleam
+40
formz_demo/src/formz_demo/examples/login.gleam
··· 1 + import formz/field.{field} 2 + import formz/formz_use as formz 3 + import formz/input 4 + import formz/string_generator/fields 5 + import formz/string_generator/widgets 6 + import wisp 7 + 8 + pub type Credentials { 9 + Credentials(username: String, password: String) 10 + } 11 + 12 + pub type User { 13 + User(username: String) 14 + } 15 + 16 + pub fn make_form() { 17 + use username <- formz.with(field("username", fields.text_field())) 18 + use password <- formz.with( 19 + field("password", fields.text_field()) 20 + |> field.set_widget(widgets.password_widget()), 21 + ) 22 + 23 + formz.create_form(Credentials(username, password)) 24 + } 25 + 26 + pub fn handle_post(formdata: wisp.FormData, form) { 27 + use cred, form <- formz.parse_and_try(form |> formz.data(formdata.values)) 28 + 29 + case cred { 30 + Credentials("admin", "l33t") -> Ok(User(cred.username)) 31 + Credentials("admin", _) -> 32 + form 33 + |> formz.update_input("password", input.set_error(_, "wrong password")) 34 + |> Error 35 + Credentials(_, _) -> 36 + form 37 + |> formz.update_input("username", input.set_error(_, "wrong username")) 38 + |> Error 39 + } 40 + }
+45
formz_demo/src/formz_demo/examples/sub_form.gleam
··· 1 + import formz/field 2 + import formz/formz_use as formz 3 + import formz/string_generator/fields 4 + 5 + pub fn make_form() { 6 + use billing_address <- formz.sub_form( 7 + "billing", 8 + "Billing Address", 9 + address_form(), 10 + ) 11 + use shipping_address <- formz.sub_form( 12 + "shipping", 13 + "Shipping Address", 14 + address_form(), 15 + ) 16 + 17 + formz.create_form(#(billing_address, shipping_address)) 18 + } 19 + 20 + fn address_form() { 21 + use street <- formz.with(field.field("street", fields.text_field())) 22 + use city <- formz.with(field.field("city", fields.text_field())) 23 + use state <- formz.with(field.field("state", fields.list_field(states_list()))) 24 + use postal_code <- formz.with(field.field("postal_code", fields.text_field())) 25 + 26 + formz.create_form(Address(street:, city:, state:, postal_code:)) 27 + } 28 + 29 + pub type Address { 30 + Address(street: String, city: String, state: String, postal_code: String) 31 + } 32 + 33 + fn states_list() { 34 + [ 35 + "Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", 36 + "Connecticut", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho", 37 + "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine", 38 + "Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", 39 + "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", 40 + "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio", 41 + "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", 42 + "South Dakota", "Tennessee", "Texas", "Utah", "Vermont", "Virginia", 43 + "Washington", "West Virginia", "Wisconsin", "Wyoming", 44 + ] 45 + }
+93 -23
formz_demo/src/formz_demo/router.gleam
··· 1 + import formz_demo/example/defaults 1 2 import formz_demo/example/run 2 3 import gleam/http/request 4 + import gleam/list 5 + import justin 3 6 import lustre/attribute 4 7 import lustre/element 5 8 import lustre/element/html.{html} 6 9 import wisp.{type Request, type Response} 7 10 8 - import formz_demo/examples/example_1/example_1 9 - import formz_demo/examples/example_2/example_2 10 - import formz_demo/examples/example_3/example_3 11 + import formz_demo/examples/all_the_inputs 12 + import formz_demo/examples/hello_world 13 + import formz_demo/examples/labels 14 + import formz_demo/examples/login 15 + import formz_demo/examples/sub_form 11 16 12 17 import formz_demo/web.{type Context} 13 18 19 + fn get_examples() { 20 + [ 21 + #("hello_world", fn(req, dir) { 22 + run.handle( 23 + req, 24 + run.ExampleRun( 25 + dir, 26 + hello_world.make_form, 27 + defaults.handle_get, 28 + defaults.handle_post, 29 + defaults.format_string_form, 30 + defaults.formatted_string_form_to_string, 31 + ), 32 + ) 33 + }), 34 + #("all_the_inputs", fn(req, dir) { 35 + run.handle( 36 + req, 37 + run.ExampleRun( 38 + dir, 39 + all_the_inputs.make_form, 40 + all_the_inputs.handle_get, 41 + defaults.handle_post, 42 + defaults.format_string_form, 43 + defaults.formatted_string_form_to_string, 44 + ), 45 + ) 46 + }), 47 + #("labels", fn(req, dir) { 48 + run.handle( 49 + req, 50 + run.ExampleRun( 51 + dir, 52 + labels.make_form, 53 + defaults.handle_get, 54 + defaults.handle_post, 55 + defaults.format_string_form, 56 + defaults.formatted_string_form_to_string, 57 + ), 58 + ) 59 + }), 60 + #("login", fn(req, dir) { 61 + run.handle( 62 + req, 63 + run.ExampleRun( 64 + dir, 65 + login.make_form, 66 + defaults.handle_get, 67 + login.handle_post, 68 + defaults.format_string_form, 69 + defaults.formatted_string_form_to_string, 70 + ), 71 + ) 72 + }), 73 + #("sub_form", fn(req, dir) { 74 + run.handle( 75 + req, 76 + run.ExampleRun( 77 + dir, 78 + sub_form.make_form, 79 + defaults.handle_get, 80 + defaults.handle_post, 81 + defaults.format_string_form, 82 + defaults.formatted_string_form_to_string, 83 + ), 84 + ) 85 + }), 86 + ] 87 + } 88 + 14 89 pub fn handle_request(req: Request, ctx: Context) -> Response { 15 90 use req <- web.middleware(req, ctx) 16 91 17 92 case request.path_segments(req) { 18 93 [] -> index() 19 - ["example-1"] -> run.handle(req, example_1.make_forms) 20 - ["example-2"] -> run.handle(req, example_2.make_forms) 21 - ["example-3"] -> run.handle(req, example_3.make_forms) 94 + [dir] -> 95 + case list.key_find(get_examples(), dir) { 96 + Ok(make_example) -> make_example(req, dir) 97 + Error(_) -> wisp.not_found() 98 + } 99 + 22 100 _ -> wisp.not_found() 23 101 } 24 102 } 25 103 26 104 pub fn index() -> Response { 105 + let examples_lis = 106 + get_examples() 107 + |> list.map(fn(t) { 108 + let #(dir, _) = t 109 + let name = justin.sentence_case(dir) 110 + html.li([], [html.a([attribute.href("/" <> dir)], [html.text(name)])]) 111 + }) 112 + 27 113 let html = 28 114 html([], [ 29 115 html.head([], [ ··· 35 121 ]), 36 122 html.body([], [ 37 123 html.h1([], [html.text("Hey there, formz!")]), 38 - html.ul([], [ 39 - html.li([], [ 40 - html.a([attribute.href("/example-1")], [ 41 - html.text(example_1.make_forms().1), 42 - ]), 43 - ]), 44 - html.li([], [ 45 - html.a([attribute.href("/example-2")], [ 46 - html.text(example_2.make_forms().1), 47 - ]), 48 - ]), 49 - html.li([], [ 50 - html.a([attribute.href("/example-3")], [ 51 - html.text(example_3.make_forms().1), 52 - ]), 53 - ]), 54 - ]), 124 + html.ul([], examples_lis), 55 125 ]), 56 126 ]) 57 127 |> element.to_document_string_builder