0x33.board: add email sub form
s-ol
5 months ago
0 | dom = require 'mmm.dom' | |
1 | import form, h3, h4, h5, hr, div, span, section, label, input, p, br, i from dom | |
2 | unpack or= table.unpack | |
3 | ||
4 | input_field = (text, attr) -> | |
5 | if not attr and 'table' == type text | |
6 | text, attr = attr, text | |
7 | text = table.remove attr | |
8 | ||
9 | label { | |
10 | style: | |
11 | display: 'flex' | |
12 | 'align-items': 'baseline' | |
13 | ||
14 | div text, style: width: '10em' | |
15 | input attr | |
16 | } | |
17 | ||
18 | input_box = (text, attr) -> | |
19 | if not attr and 'table' == type text | |
20 | text, attr = attr, text | |
21 | text = table.remove attr | |
22 | ||
23 | label { | |
24 | style: | |
25 | display: 'flex' | |
26 | input attr | |
27 | span text | |
28 | } | |
29 | ||
30 | form_section = (...) -> | |
31 | section { | |
32 | style: 'margin-bottom': '1em' | |
33 | ||
34 | unpack ... | |
35 | } | |
36 | ||
37 | pp = (...) -> | |
38 | p { | |
39 | style: margin: '0 0 0.5em' | |
40 | ||
41 | ... | |
42 | } | |
43 | ||
44 | form { | |
45 | id: 'subscribe-form' | |
46 | method: 'POST' | |
47 | ||
48 | style: | |
49 | display: 'flex' | |
50 | 'flex-direction': 'column' | |
51 | 'align-items': 'flex-start' | |
52 | ||
53 | h3 "Edit: 0x33.board pre-order survery / email subscription" | |
54 | ||
55 | p "Thank you! You can always come back here to change your settings." | |
56 | ||
57 | h4 "email updates" | |
58 | section { | |
59 | style: padding: "0 0.5em 1em" | |
60 | ||
61 | form_section { | |
62 | input_field "name (optional):", name: 'name' | |
63 | input_field "e-mail adress:", type: 'email', name: 'mail_addr' | |
64 | } | |
65 | ||
66 | h5 "frequency:" | |
67 | form_section { | |
68 | input_box { | |
69 | type: 'radio' | |
70 | name: 'mail_frequency' | |
71 | value: 'never' | |
72 | ||
73 | span "never (unsubscribe)" | |
74 | } | |
75 | input_box { | |
76 | type: 'radio' | |
77 | name: 'mail_frequency' | |
78 | value: 'release' | |
79 | ||
80 | "just once (at release)" | |
81 | } | |
82 | input_box { | |
83 | type: 'radio' | |
84 | name: 'mail_frequency' | |
85 | value: 'rare' | |
86 | ||
87 | "rare progress updates (max one monthly)" | |
88 | } | |
89 | input_box "also inform me about other projects", type: 'checkbox', name: 'mail_other' | |
90 | } | |
91 | ||
92 | pp "You'll be able to change these settings any time by coming back here.", br!, | |
93 | "This link will also be provided in every email sent." | |
94 | } | |
95 | ||
96 | h4 "feedback" | |
97 | section { | |
98 | style: padding: "0 0.5em" | |
99 | ||
100 | pp "The questions in this section help me prioritize and design features." | |
101 | ||
102 | h5 "features:" | |
103 | form_section { | |
104 | pp "I'm interested in using the 0x33.board…" | |
105 | input_box "…as a MIDI keyboard", type: 'checkbox', name: 'usage', value: 'midi' | |
106 | input_box "…with other I2C devices", type: 'checkbox', name: 'usage', value: 'i2c' | |
107 | input_box "…as a standalone synth", type: 'checkbox', name: 'usage', value: 'synth' | |
108 | input_box '…as a computer keyboard', type: 'checkbox', name: 'usage', value: 'hid' | |
109 | } | |
110 | ||
111 | h5 "case material preference:" | |
112 | form_section { | |
113 | pp "Mixing and matching will also be possible.", br!, "From cheapest to most expensive:" | |
114 | input_box "MDF / fiberboard", type: 'radio', name: 'material', value: 'mdf', required: true | |
115 | input_box "acrylic", type: 'radio', name: 'material', value: 'acrylic', required: true | |
116 | input_box "aluminum", type: 'radio', name: 'material', value: 'aluminum', required: true | |
117 | } | |
118 | ||
119 | h5 "other:" | |
120 | form_section { | |
121 | pp "It's most important to me that the keyboard…" | |
122 | dom.table { | |
123 | dom.tr { | |
124 | dom.td input_box { | |
125 | type: 'radio' | |
126 | name: 'budget_durability' | |
127 | value: 'budget' | |
128 | required: true | |
129 | ||
130 | "…is available at a low cost" | |
131 | } | |
132 | dom.td input_box { | |
133 | type: 'radio' | |
134 | name: 'budget_durability' | |
135 | value: 'durability' | |
136 | required: true | |
137 | ||
138 | "…is durable" | |
139 | } | |
140 | } | |
141 | dom.tr { | |
142 | dom.td input_box { | |
143 | type: 'radio' | |
144 | name: 'firmware' | |
145 | value: 'mature' | |
146 | required: true | |
147 | ||
148 | "…works out of the box" | |
149 | } | |
150 | dom.td input_box { | |
151 | type: 'radio' | |
152 | name: 'firmware' | |
153 | value: 'extensible' | |
154 | required: true | |
155 | ||
156 | "…is open-source and extensible" | |
157 | } | |
158 | } | |
159 | } | |
160 | } | |
161 | } | |
162 | ||
163 | input id: 'subscribe-submit', type: 'submit', value: 'Update', disabled: true | |
164 | ||
165 | dom.noscript { | |
166 | p { | |
167 | "Unfortunately this form cannot restore your past choices without JavaScript." | |
168 | "The script embedded on this page is only 30 lines of vanilla JS and doesn't involve any tracking or 3rd party code." | |
169 | } | |
170 | ||
171 | p { | |
172 | "Nevertheless, if you wish to unsubscribe or otherwise change your settings you can send an email to ", | |
173 | dom.b "s+0x33sub", (i "[ät]"), " s-ol ", (i "[döt]"), " nu", | |
174 | " detailing the changes." | |
175 | } | |
176 | } | |
177 | ||
178 | dom.script " | |
179 | (function() { | |
180 | var q = window.location.hash.substr(1).split(':') | |
181 | if (q.length == 2) { | |
182 | var id = q[0] | |
183 | var key = q[1] | |
184 | var url = '//json-hopper.s-ol.nu/0x33.board/' + id + '?_key=' + key | |
185 | ||
186 | fetch(url) | |
187 | .then(function (res) { return res.json() }) | |
188 | .then(function (data) { | |
189 | var form = document.getElementById('subscribe-form') | |
190 | var submit = document.getElementById('subscribe-submit') | |
191 | ||
192 | if (data['usage'] == null) data['usage'] = [] | |
193 | ||
194 | form['name'].value = data.name | |
195 | form['mail_addr'].value = data.mail_addr | |
196 | form['mail_frequency'].value = data.mail_frequency | |
197 | form['mail_other'].checked = data.mail_other | |
198 | form['usage'].forEach(function (topic) { | |
199 | topic.checked = data['usage'].indexOf(topic.value) > -1 | |
200 | }) | |
201 | form['material'].value = data.material | |
202 | form['budget_durability'].value = data.budget_durability | |
203 | form['firmware'].value = data.firmware | |
204 | ||
205 | form.action = url | |
206 | submit.disabled = false | |
207 | }) | |
208 | .catch(function (err) { | |
209 | window.alert('Error recovering Form data: ' + err) | |
210 | }) | |
211 | } | |
212 | })()" | |
213 | } |
0 | dom = require 'mmm.dom' | |
1 | import form, h3, h4, h5, hr, div, span, section, label, input, p, br, i from dom | |
2 | unpack or= table.unpack | |
3 | ||
4 | input_field = (text, attr) -> | |
5 | if not attr and 'table' == type text | |
6 | text, attr = attr, text | |
7 | text = table.remove attr | |
8 | ||
9 | label { | |
10 | style: | |
11 | display: 'flex' | |
12 | 'align-items': 'baseline' | |
13 | ||
14 | div text, style: width: '10em' | |
15 | input attr | |
16 | } | |
17 | ||
18 | input_box = (text, attr) -> | |
19 | if not attr and 'table' == type text | |
20 | text, attr = attr, text | |
21 | text = table.remove attr | |
22 | ||
23 | label { | |
24 | style: | |
25 | display: 'flex' | |
26 | input attr | |
27 | span text | |
28 | } | |
29 | ||
30 | form_section = (...) -> | |
31 | section { | |
32 | style: 'margin-bottom': '1em' | |
33 | ||
34 | unpack ... | |
35 | } | |
36 | ||
37 | pp = (...) -> | |
38 | p { | |
39 | style: margin: '0 0 0.5em' | |
40 | ||
41 | ... | |
42 | } | |
43 | ||
44 | form { | |
45 | method: 'POST' | |
46 | action: '//json-hopper.s-ol.nu/0x33.board/' | |
47 | ||
48 | style: | |
49 | display: 'flex' | |
50 | 'flex-direction': 'column' | |
51 | 'align-items': 'flex-start' | |
52 | ||
53 | h3 "0x33.board pre-order survery / email subscription" | |
54 | ||
55 | p "If you would be interested in purchasing a 0x33.board when available, " .. | |
56 | "please fill out this form so i can notify you." | |
57 | ||
58 | h4 "email updates" | |
59 | section { | |
60 | style: padding: "0 0.5em 1em" | |
61 | ||
62 | form_section { | |
63 | input_field "name (optional):", name: 'name' | |
64 | input_field "e-mail adress:", type: 'email', name: 'mail_addr' | |
65 | } | |
66 | ||
67 | h5 "frequency:" | |
68 | form_section { | |
69 | input_box { | |
70 | type: 'radio' | |
71 | name: 'mail_frequency' | |
72 | value: 'release' | |
73 | checked: true | |
74 | ||
75 | "just once (at release)" | |
76 | } | |
77 | input_box { | |
78 | type: 'radio' | |
79 | name: 'mail_frequency' | |
80 | value: 'rare' | |
81 | ||
82 | "rare progress updates (max one monthly)" | |
83 | } | |
84 | input_box "also inform me about other projects", type: 'checkbox', name: 'mail_other' | |
85 | } | |
86 | ||
87 | pp "You'll be able to change these settings any time by coming back", br!, | |
88 | "to a link that will be provided after submitting and in every email sent." | |
89 | } | |
90 | ||
91 | h4 "feedback" | |
92 | section { | |
93 | style: padding: "0 0.5em" | |
94 | ||
95 | pp "The questions in this section help me prioritize and design features." | |
96 | ||
97 | h5 "features:" | |
98 | form_section { | |
99 | pp "I'm interested in using the 0x33.board…" | |
100 | input_box "…as a MIDI keyboard", type: 'checkbox', name: 'usage', value: 'midi' | |
101 | input_box "…with other I2C devices", type: 'checkbox', name: 'usage', value: 'i2c' | |
102 | input_box "…as a standalone synth", type: 'checkbox', name: 'usage', value: 'synth' | |
103 | input_box '…as a computer keyboard', type: 'checkbox', name: 'usage', value: 'hid' | |
104 | } | |
105 | ||
106 | h5 "case materials:" | |
107 | form_section { | |
108 | pp "Mixing and matching will also be possible.", br!, "From cheapest to most expensive:" | |
109 | input_box "MDF / fiberboard", type: 'radio', name: 'material', value: 'mdf', required: true | |
110 | input_box "acrylic", type: 'radio', name: 'material', value: 'acrylic', required: true | |
111 | input_box "aluminum", type: 'radio', name: 'material', value: 'aluminum', required: true | |
112 | } | |
113 | ||
114 | h5 "other:" | |
115 | form_section { | |
116 | pp "It's most important to me that the keyboard…" | |
117 | dom.table { | |
118 | dom.tr { | |
119 | dom.td input_box { | |
120 | type: 'radio' | |
121 | name: 'budget_durability' | |
122 | value: 'budget' | |
123 | required: true | |
124 | ||
125 | "…is available at a low cost" | |
126 | } | |
127 | dom.td input_box { | |
128 | type: 'radio' | |
129 | name: 'budget_durability' | |
130 | value: 'durability' | |
131 | required: true | |
132 | ||
133 | "…is durable" | |
134 | } | |
135 | } | |
136 | dom.tr { | |
137 | dom.td input_box { | |
138 | type: 'radio' | |
139 | name: 'firmware' | |
140 | value: 'mature' | |
141 | required: true | |
142 | ||
143 | "…works out of the box" | |
144 | } | |
145 | dom.td input_box { | |
146 | type: 'radio' | |
147 | name: 'firmware' | |
148 | value: 'extensible' | |
149 | required: true | |
150 | ||
151 | "…is open-source and extensible" | |
152 | } | |
153 | } | |
154 | } | |
155 | } | |
156 | } | |
157 | ||
158 | input type: 'submit', value: 'Subscribe' | |
159 | } |
2 | 2 | |
3 | 3 | <mmm-embed nolink facet="preview" /></mmm-embed> |
4 | 4 | |
5 | <div style="display: flex; align-items: center;"> | |
6 | <mmm-embed path="certification"></mmm-embed> | |
7 | <mmm-embed path="certification" facet="facts" nolink></mmm-embed> | |
5 | <div> | |
6 | <a class="action-btn" href="https://s-ol.nu/0x33.board/sub">be notified on release</a> | |
7 | or follow me on | |
8 | <a class="action-btn secondary" href="https://merveilles.town/@s_ol">mastodon</a> | |
9 | for updates | |
8 | 10 | </div> |
9 | 11 | |
10 | 12 | The `0x33.board` is a 48-key isomorphic MIDI key controller. |
17 | 19 | |
18 | 20 | The firmware is currently a work in progress (as is this documentation page). |
19 | 21 | |
22 | <div style="display: flex; align-items: center;"> | |
23 | <mmm-embed path="certification"></mmm-embed> | |
24 | <mmm-embed path="certification" facet="facts" nolink></mmm-embed> | |
25 | </div> | |
26 | ||
20 | 27 | availability |
21 | 28 | ------------ |
22 | 29 | |
23 | The first batch of 0x33.boards will be available once the next PCB revision is evaluated and | |
24 | <mmm-link path="/HEX-keycaps">the production keycaps</mmm-link> are ready. | |
30 | The first batch of 0x33.boards will be available once the next PCB revision is evaluated. | |
25 | 31 | |
26 | 32 | 0x33.boards are produced in small batches and manually soldered and assembled by me in Italy. |
27 | 33 | Various materials will be available for the case on demand. |
32 | 38 | The `0x33.board` is certified open hardware. |
33 | 39 | The source for the various components are available as follows: |
34 | 40 | |
35 | - hardware design (CERN-OHL-S 2.0): | |
36 | - <span style="display: inline-block; width: 5em;">git clone</span> [https://git.s-ol.nu/hw/0x33.board/hardware.git][hardware-git] | |
37 | - <span style="display: inline-block; width: 5em;">browse</span> [https://git.s-ol.nu/hw/0x33.board/hardware/-/][hardware-web] | |
38 | - firmware source (MIT): | |
39 | - <span style="display: inline-block; width: 5em;">git clone</span> [https://git.s-ol.nu/hw/0x33.board/firmware.git][firmware-git] | |
40 | - <span style="display: inline-block; width: 5em;">browse</span> [https://git.s-ol.nu/hw/0x33.board/firmware/-/][firmware-web] | |
41 | - documentation source (CC BY 4.0): | |
42 | - <span style="display: inline-block; width: 5em;">git clone</span> [https://git.s-ol.nu/hw/hw.s-ol.nu.git][docs-git] | |
43 | - <span style="display: inline-block; width: 5em;">browse</span> [https://git.s-ol.nu/hw/hw.s-ol.nu/-/][docs-web] | |
41 | - hardware design (CERN-OHL-S 2.0): | |
42 | <code>git clone [https://git.s-ol.nu/hw/0x33.board/hardware.git][hardware-web]</code> | |
43 | - firmware source (MIT): | |
44 | <code>git clone [https://git.s-ol.nu/hw/0x33.board/firmware.git][firmware-web]</code> | |
45 | - documentation source (CC BY 4.0): | |
46 | <code>git clone [https://git.s-ol.nu/hw/hw.s-ol.nu.git][docs-web]</code> | |
44 | 47 | |
45 | 48 | hardware revision history |
46 | 49 | ------------------------- |
59 | 62 | - MIDI, I2C need bodge |
60 | 63 | - no I2C pull-up / levelshifting |
61 | 64 | - fixed "nkro" key-matrix |
62 | - r3 (wip) | |
63 | - jacks labelled MIDI, I2C, PWM; different jack part | |
65 | - [r3 / d4cf583](https://git.s-ol.nu/hw/0x33.board/hardware/-/r3/) | |
66 | - jacks labelled MIDI, I2C, PWM; adjusted positions; different jack part | |
64 | 67 | - fixed MIDI, 5V tolerant I2C port |
65 | - solderable "SMTSO" thread inserts | |
68 | - solderable "SMTSO" thread inserts, no need for plastic spacers | |
69 | - OSHW certified! | |
66 | 70 | |
67 | [hardware-git]: https://git.s-ol.nu/hw/0x33.board/hardware.git | |
68 | 71 | [hardware-web]: https://git.s-ol.nu/hw/0x33.board/hardware/-/ |
69 | [firmware-git]: https://git.s-ol.nu/hw/0x33.board/firmware.git | |
70 | 72 | [firmware-web]: https://git.s-ol.nu/hw/0x33.board/firmware/-/ |
71 | [docs-git]: https://git.s-ol.nu/hw/hw.s-ol.nu.git | |
72 | 73 | [docs-web]: https://git.s-ol.nu/hw/hw.s-ol.nu/-/ |