fix single-option dropdown presentation form bug
This commit is contained in:
parent
a341a317fc
commit
92d2a963f5
3 changed files with 68 additions and 18 deletions
|
|
@ -8,7 +8,12 @@ use serde::Deserialize;
|
|||
use crate::errors::AppError;
|
||||
|
||||
/// A subset of an HTTP form that represents a [`Presentation`] in its component
|
||||
/// parts. It may be merged into a larger HTTP form using `serde(flatten)`.
|
||||
/// parts.
|
||||
///
|
||||
/// WARNING: Though this was originally designed to be combined with
|
||||
/// `#[serde(flatten)]`, Serde's buffering strategy causes `flatten` to break
|
||||
/// deserialization of `Vec<_>` fields when provided with a sequence of length
|
||||
/// == 1. `#[serde(flatten)]` should be avoided.
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub(crate) struct PresentationForm {
|
||||
pub(crate) presentation_tag: String,
|
||||
|
|
|
|||
|
|
@ -34,13 +34,37 @@ pub(super) struct PathParams {
|
|||
}
|
||||
|
||||
// FIXME: validate name, prevent leading underscore
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub(super) struct FormBody {
|
||||
name: String,
|
||||
|
||||
table_label: String,
|
||||
|
||||
#[serde(flatten)]
|
||||
presentation_form: PresentationForm,
|
||||
presentation_tag: String,
|
||||
|
||||
#[serde(default)]
|
||||
dropdown_option_colors: Vec<String>,
|
||||
|
||||
#[serde(default)]
|
||||
dropdown_option_values: Vec<String>,
|
||||
|
||||
#[serde(default)]
|
||||
text_input_mode: String,
|
||||
|
||||
#[serde(default)]
|
||||
timestamp_format: String,
|
||||
}
|
||||
|
||||
impl From<FormBody> for PresentationForm {
|
||||
fn from(value: FormBody) -> Self {
|
||||
Self {
|
||||
presentation_tag: value.presentation_tag,
|
||||
dropdown_option_colors: value.dropdown_option_colors,
|
||||
dropdown_option_values: value.dropdown_option_values,
|
||||
text_input_mode: value.text_input_mode,
|
||||
timestamp_format: value.timestamp_format,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// HTTP POST handler for adding a [`Field`] to a [`Portal`]. If the field name
|
||||
|
|
@ -84,7 +108,7 @@ pub(super) async fn post(
|
|||
.fetch_one()
|
||||
.await?;
|
||||
|
||||
let presentation = Presentation::try_from(form.presentation_form)?;
|
||||
let presentation = Presentation::try_from(Into::<PresentationForm>::into(form.clone()))?;
|
||||
|
||||
query(&format!(
|
||||
"alter table {ident} add column if not exists {col} {typ}",
|
||||
|
|
|
|||
|
|
@ -21,13 +21,36 @@ pub(super) struct PathParams {
|
|||
workspace_id: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Validate)]
|
||||
#[derive(Clone, Debug, Deserialize, Validate)]
|
||||
pub(super) struct FormBody {
|
||||
field_id: Uuid,
|
||||
table_label: String,
|
||||
|
||||
#[serde(flatten)]
|
||||
presentation_form: PresentationForm,
|
||||
presentation_tag: String,
|
||||
|
||||
#[serde(default)]
|
||||
dropdown_option_colors: Vec<String>,
|
||||
|
||||
#[serde(default)]
|
||||
dropdown_option_values: Vec<String>,
|
||||
|
||||
#[serde(default)]
|
||||
text_input_mode: String,
|
||||
|
||||
#[serde(default)]
|
||||
timestamp_format: String,
|
||||
}
|
||||
|
||||
impl From<FormBody> for PresentationForm {
|
||||
fn from(value: FormBody) -> Self {
|
||||
Self {
|
||||
presentation_tag: value.presentation_tag,
|
||||
dropdown_option_colors: value.dropdown_option_colors,
|
||||
dropdown_option_values: value.dropdown_option_values,
|
||||
text_input_mode: value.text_input_mode,
|
||||
timestamp_format: value.timestamp_format,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// HTTP POST handler for updating an existing [`Field`].
|
||||
|
|
@ -44,11 +67,7 @@ pub(super) async fn post(
|
|||
rel_oid,
|
||||
workspace_id,
|
||||
}): Path<PathParams>,
|
||||
ValidatedForm(FormBody {
|
||||
field_id,
|
||||
table_label,
|
||||
presentation_form,
|
||||
}): ValidatedForm<FormBody>,
|
||||
ValidatedForm(form): ValidatedForm<FormBody>,
|
||||
) -> Result<Response, AppError> {
|
||||
// FIXME CSRF
|
||||
|
||||
|
|
@ -57,18 +76,20 @@ pub(super) async fn post(
|
|||
|
||||
// Ensure field exists and belongs to portal.
|
||||
Field::belonging_to_portal(portal_id)
|
||||
.with_id(field_id)
|
||||
.with_id(form.field_id)
|
||||
.fetch_one(&mut app_db)
|
||||
.await?;
|
||||
|
||||
Field::update()
|
||||
.id(field_id)
|
||||
.table_label(if table_label.is_empty() {
|
||||
.id(form.field_id)
|
||||
.table_label(if form.table_label.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(table_label)
|
||||
Some(form.table_label.clone())
|
||||
})
|
||||
.presentation(Presentation::try_from(presentation_form)?)
|
||||
.presentation(Presentation::try_from(Into::<PresentationForm>::into(
|
||||
form,
|
||||
))?)
|
||||
.build()?
|
||||
.execute(&mut app_db)
|
||||
.await?;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue