| 20 |
20 |
|
|
| 21 |
21 |
|
use std::collections::HashMap;
|
| 22 |
22 |
|
|
| 23 |
|
- |
use makeover_layout::{Field, FieldKind};
|
|
23 |
+ |
use makeover_layout::{Choice, Field, FieldKind};
|
| 24 |
24 |
|
use makeover_webview::Emit;
|
| 25 |
|
- |
use makeover_webview::form::{Choice, Filling, Markup, Value, field_html};
|
|
25 |
+ |
use makeover_webview::form::{Filling, Markup, Value, field_html};
|
| 26 |
26 |
|
use serde::Deserialize;
|
| 27 |
27 |
|
use tracing::{instrument, warn};
|
| 28 |
28 |
|
|
| 47 |
47 |
|
|
| 48 |
48 |
|
/// One field, as the frontend sends it.
|
| 49 |
49 |
|
///
|
| 50 |
|
- |
/// A mirror of [`Field`] plus everything the description deliberately does not
|
| 51 |
|
- |
/// carry: the current value, the placeholder, the select's options. Those are
|
| 52 |
|
- |
/// renderer-side state and arrive in [`Filling`].
|
|
50 |
+ |
/// A mirror of [`Field`] plus the one thing the description deliberately does
|
|
51 |
+ |
/// not carry, the current value, which arrives in [`Filling`].
|
|
52 |
+ |
///
|
|
53 |
+ |
/// It used to be three things. The placeholder and a select's options were
|
|
54 |
+ |
/// renderer-side until makeover-layout 0.8.0 moved both onto [`Field`], so they
|
|
55 |
+ |
/// still arrive in the same JSON and simply land in a different struct. The
|
|
56 |
+ |
/// wire shape the frontend sends is unchanged by that, and deliberately: this
|
|
57 |
+ |
/// type is the boundary, and a description reorganising itself is not a reason
|
|
58 |
+ |
/// to make fifteen call sites in `js/` send something new.
|
| 53 |
59 |
|
#[derive(Debug, Deserialize)]
|
| 54 |
60 |
|
#[serde(rename_all = "camelCase")]
|
| 55 |
61 |
|
pub struct FieldSpec {
|
| 161 |
167 |
|
for spec in &fields {
|
| 162 |
168 |
|
let kind = kind_of(&spec.kind);
|
| 163 |
169 |
|
|
| 164 |
|
- |
let field = Field {
|
| 165 |
|
- |
kind,
|
| 166 |
|
- |
name: &spec.name,
|
| 167 |
|
- |
label: &spec.label,
|
| 168 |
|
- |
hint: spec.hint.as_deref(),
|
| 169 |
|
- |
error: spec.error.as_deref(),
|
| 170 |
|
- |
required: spec.required,
|
| 171 |
|
- |
extended: spec.extended,
|
| 172 |
|
- |
};
|
| 173 |
|
- |
|
| 174 |
|
- |
// Built here rather than inline so the borrow outlives the Value that
|
|
170 |
+ |
// Built here rather than inline so the borrow outlives the Field that
|
| 175 |
171 |
|
// points into it.
|
| 176 |
172 |
|
let choices: Vec<Choice<'_>> = spec
|
| 177 |
173 |
|
.options
|
| 184 |
180 |
|
})
|
| 185 |
181 |
|
.collect();
|
| 186 |
182 |
|
|
|
183 |
+ |
let field = Field {
|
|
184 |
+ |
kind,
|
|
185 |
+ |
name: &spec.name,
|
|
186 |
+ |
label: &spec.label,
|
|
187 |
+ |
hint: spec.hint.as_deref(),
|
|
188 |
+ |
error: spec.error.as_deref(),
|
|
189 |
+ |
// Both moved onto the description in makeover-layout 0.8.0. They
|
|
190 |
+ |
// arrived in `Filling` until then, which is why this function used
|
|
191 |
+ |
// to assemble the field and its filling from the same spec in two
|
|
192 |
+ |
// places.
|
|
193 |
+ |
placeholder: spec.placeholder.as_deref(),
|
|
194 |
+ |
options: &choices,
|
|
195 |
+ |
required: spec.required,
|
|
196 |
+ |
extended: spec.extended,
|
|
197 |
+ |
};
|
|
198 |
+ |
|
| 187 |
199 |
|
let value = match kind {
|
| 188 |
200 |
|
FieldKind::Checkbox => Value::On(spec.checked.unwrap_or_default()),
|
| 189 |
|
- |
FieldKind::Select => Value::Chosen {
|
| 190 |
|
- |
options: &choices,
|
| 191 |
|
- |
value: spec.current_value(),
|
| 192 |
|
- |
},
|
|
201 |
+ |
// A select's value is the value of one of its options and the
|
|
202 |
+ |
// options are on the field now, so it takes the same variant
|
|
203 |
+ |
// everything else typed does.
|
|
204 |
+ |
FieldKind::Select => Value::Text(spec.current_value()),
|
| 193 |
205 |
|
_ => match spec.value.as_deref() {
|
| 194 |
206 |
|
Some(text) => Value::Text(text),
|
| 195 |
207 |
|
None => Value::Absent,
|
| 198 |
210 |
|
|
| 199 |
211 |
|
let filling = Filling {
|
| 200 |
212 |
|
value,
|
| 201 |
|
- |
placeholder: spec.placeholder.as_deref(),
|
| 202 |
213 |
|
trailing: spec.trailing_html.as_deref().map(Markup),
|
| 203 |
214 |
|
id_prefix: id_prefix.as_deref(),
|
| 204 |
215 |
|
};
|