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;
|
use crate::errors::AppError;
|
||||||
|
|
||||||
/// A subset of an HTTP form that represents a [`Presentation`] in its component
|
/// 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)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
pub(crate) struct PresentationForm {
|
pub(crate) struct PresentationForm {
|
||||||
pub(crate) presentation_tag: String,
|
pub(crate) presentation_tag: String,
|
||||||
|
|
|
||||||
|
|
@ -34,13 +34,37 @@ pub(super) struct PathParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: validate name, prevent leading underscore
|
// FIXME: validate name, prevent leading underscore
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
pub(super) struct FormBody {
|
pub(super) struct FormBody {
|
||||||
name: String,
|
name: String,
|
||||||
|
|
||||||
table_label: String,
|
table_label: String,
|
||||||
|
|
||||||
#[serde(flatten)]
|
presentation_tag: String,
|
||||||
presentation_form: PresentationForm,
|
|
||||||
|
#[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
|
/// 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()
|
.fetch_one()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let presentation = Presentation::try_from(form.presentation_form)?;
|
let presentation = Presentation::try_from(Into::<PresentationForm>::into(form.clone()))?;
|
||||||
|
|
||||||
query(&format!(
|
query(&format!(
|
||||||
"alter table {ident} add column if not exists {col} {typ}",
|
"alter table {ident} add column if not exists {col} {typ}",
|
||||||
|
|
|
||||||
|
|
@ -21,13 +21,36 @@ pub(super) struct PathParams {
|
||||||
workspace_id: Uuid,
|
workspace_id: Uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Validate)]
|
#[derive(Clone, Debug, Deserialize, Validate)]
|
||||||
pub(super) struct FormBody {
|
pub(super) struct FormBody {
|
||||||
field_id: Uuid,
|
field_id: Uuid,
|
||||||
table_label: String,
|
table_label: String,
|
||||||
|
|
||||||
#[serde(flatten)]
|
presentation_tag: String,
|
||||||
presentation_form: PresentationForm,
|
|
||||||
|
#[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`].
|
/// HTTP POST handler for updating an existing [`Field`].
|
||||||
|
|
@ -44,11 +67,7 @@ pub(super) async fn post(
|
||||||
rel_oid,
|
rel_oid,
|
||||||
workspace_id,
|
workspace_id,
|
||||||
}): Path<PathParams>,
|
}): Path<PathParams>,
|
||||||
ValidatedForm(FormBody {
|
ValidatedForm(form): ValidatedForm<FormBody>,
|
||||||
field_id,
|
|
||||||
table_label,
|
|
||||||
presentation_form,
|
|
||||||
}): ValidatedForm<FormBody>,
|
|
||||||
) -> Result<Response, AppError> {
|
) -> Result<Response, AppError> {
|
||||||
// FIXME CSRF
|
// FIXME CSRF
|
||||||
|
|
||||||
|
|
@ -57,18 +76,20 @@ pub(super) async fn post(
|
||||||
|
|
||||||
// Ensure field exists and belongs to portal.
|
// Ensure field exists and belongs to portal.
|
||||||
Field::belonging_to_portal(portal_id)
|
Field::belonging_to_portal(portal_id)
|
||||||
.with_id(field_id)
|
.with_id(form.field_id)
|
||||||
.fetch_one(&mut app_db)
|
.fetch_one(&mut app_db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Field::update()
|
Field::update()
|
||||||
.id(field_id)
|
.id(form.field_id)
|
||||||
.table_label(if table_label.is_empty() {
|
.table_label(if form.table_label.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(table_label)
|
Some(form.table_label.clone())
|
||||||
})
|
})
|
||||||
.presentation(Presentation::try_from(presentation_form)?)
|
.presentation(Presentation::try_from(Into::<PresentationForm>::into(
|
||||||
|
form,
|
||||||
|
))?)
|
||||||
.build()?
|
.build()?
|
||||||
.execute(&mut app_db)
|
.execute(&mut app_db)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue