web interface for table_definition improved
This commit is contained in:
@@ -5,8 +5,15 @@
|
||||
//! parallel repeated fields. `serde_html_form` (via `axum_extra::extract::Form`)
|
||||
//! decodes the repeats into `Vec`s, which `to_draft` zips back into a
|
||||
//! [`TableDraft`].
|
||||
//!
|
||||
//! The column half of that form is the shared one — the field names here are
|
||||
//! the same ones [`crate::schema::ColumnForm`] declares, and both are rebuilt
|
||||
//! by [`crate::schema::columns_from_rows`], so the two screens that describe
|
||||
//! columns cannot drift apart.
|
||||
|
||||
use super::draft::{ColumnDefinition, LinkDefinition, LinkMode, MoneyMode, TableDraft};
|
||||
use crate::schema::{ColumnDraft, columns_from_rows};
|
||||
|
||||
use super::draft::{LinkDefinition, LinkMode, TableDraft};
|
||||
|
||||
/// The `profile_name` option meaning "create a new profile too".
|
||||
pub(crate) const NEW_PROFILE: &str = "__new__";
|
||||
@@ -39,6 +46,10 @@ pub(crate) struct BuilderForm {
|
||||
#[serde(default)]
|
||||
pub gtin_type_input: String,
|
||||
#[serde(default)]
|
||||
pub decimal_precision_input: String,
|
||||
#[serde(default)]
|
||||
pub decimal_scale_input: String,
|
||||
#[serde(default)]
|
||||
pub column_indexing_input: String,
|
||||
#[serde(default)]
|
||||
pub column_quantity_ledger_input: String,
|
||||
@@ -71,49 +82,37 @@ pub(crate) struct BuilderForm {
|
||||
pub row_display_columns: Vec<String>,
|
||||
}
|
||||
|
||||
fn is_yes(value: &str) -> bool {
|
||||
value.trim().eq_ignore_ascii_case("yes")
|
||||
}
|
||||
|
||||
impl BuilderForm {
|
||||
pub(crate) fn creating_new_profile(&self) -> bool {
|
||||
self.profile_name == NEW_PROFILE
|
||||
}
|
||||
|
||||
/// Rebuilds the draft this form was rendered from.
|
||||
///
|
||||
/// The column vectors are parallel, so a short one (a truncated or
|
||||
/// tampered-with post) simply limits how many columns are reconstructed
|
||||
/// rather than mis-pairing them.
|
||||
pub(crate) fn to_draft(&self) -> TableDraft {
|
||||
let creating_new_profile = self.creating_new_profile();
|
||||
|
||||
let column_count = [
|
||||
self.column_names.len(),
|
||||
self.column_types.len(),
|
||||
self.column_indexed.len(),
|
||||
self.column_quantity_ledger.len(),
|
||||
self.column_rounding.len(),
|
||||
self.column_currencies.len(),
|
||||
]
|
||||
.into_iter()
|
||||
.min()
|
||||
.unwrap_or(0);
|
||||
|
||||
let columns = (0..column_count)
|
||||
.map(|index| ColumnDefinition {
|
||||
name: self.column_names[index].clone(),
|
||||
data_type: self.column_types[index].clone(),
|
||||
indexed: is_yes(&self.column_indexed[index]),
|
||||
quantity_ledger: is_yes(&self.column_quantity_ledger[index]),
|
||||
money_mode: if self.column_rounding[index].trim() == MoneyMode::Rounded.label() {
|
||||
MoneyMode::Rounded
|
||||
} else {
|
||||
MoneyMode::Exact
|
||||
},
|
||||
currency: self.column_currencies[index].clone(),
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let columns = ColumnDraft {
|
||||
name_input: self.column_name_input.clone(),
|
||||
type_input: self.column_type_input.clone(),
|
||||
temporal_type_input: self.temporal_type_input.clone(),
|
||||
gtin_type_input: self.gtin_type_input.clone(),
|
||||
decimal_precision_input: self.decimal_precision_input.clone(),
|
||||
decimal_scale_input: self.decimal_scale_input.clone(),
|
||||
indexing_input: self.column_indexing_input.clone(),
|
||||
quantity_ledger_input: self.column_quantity_ledger_input.clone(),
|
||||
rounding_input: self.column_rounding_input.clone(),
|
||||
currency_input: self.column_currency_input.clone(),
|
||||
added: columns_from_rows(
|
||||
&self.column_names,
|
||||
&self.column_types,
|
||||
&self.column_indexed,
|
||||
&self.column_quantity_ledger,
|
||||
&self.column_rounding,
|
||||
&self.column_currencies,
|
||||
),
|
||||
// The table is being created here, so ACCOUNTING is on the table.
|
||||
accounting_allowed: true,
|
||||
};
|
||||
|
||||
let link_count = self.link_tables.len().min(self.link_modes.len());
|
||||
let links = (0..link_count)
|
||||
@@ -128,7 +127,7 @@ impl BuilderForm {
|
||||
let row_display_columns = self
|
||||
.row_display_columns
|
||||
.iter()
|
||||
.filter(|display| columns.iter().any(|column| &&column.name == display))
|
||||
.filter(|display| columns.added.iter().any(|column| &&column.name == display))
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
@@ -142,14 +141,6 @@ impl BuilderForm {
|
||||
creating_new_profile,
|
||||
accounting_currency: self.accounting_currency.clone(),
|
||||
table_name: self.table_name.clone(),
|
||||
column_name_input: self.column_name_input.clone(),
|
||||
column_type_input: self.column_type_input.clone(),
|
||||
temporal_type_input: self.temporal_type_input.clone(),
|
||||
gtin_type_input: self.gtin_type_input.clone(),
|
||||
column_indexing_input: self.column_indexing_input.clone(),
|
||||
column_quantity_ledger_input: self.column_quantity_ledger_input.clone(),
|
||||
column_rounding_input: self.column_rounding_input.clone(),
|
||||
column_currency_input: self.column_currency_input.clone(),
|
||||
columns,
|
||||
links,
|
||||
row_display_columns,
|
||||
@@ -192,13 +183,18 @@ impl AddTablePageState {
|
||||
None
|
||||
},
|
||||
}];
|
||||
candidates.extend(self.draft.columns.iter().enumerate().map(|(index, column)| {
|
||||
RowDisplayCandidate {
|
||||
index: index + 1,
|
||||
name: column.name.clone(),
|
||||
position: self.draft.row_display_position(&column.name),
|
||||
}
|
||||
}));
|
||||
candidates.extend(
|
||||
self.draft
|
||||
.columns
|
||||
.added
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, column)| RowDisplayCandidate {
|
||||
index: index + 1,
|
||||
name: column.name.clone(),
|
||||
position: self.draft.row_display_position(&column.name),
|
||||
}),
|
||||
);
|
||||
candidates
|
||||
}
|
||||
}
|
||||
@@ -225,6 +221,7 @@ impl RowDisplayCandidate {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::schema::MoneyMode;
|
||||
|
||||
fn posted_form() -> BuilderForm {
|
||||
BuilderForm {
|
||||
@@ -247,9 +244,9 @@ mod tests {
|
||||
fn round_trips_columns_links_and_display_columns() {
|
||||
let draft = posted_form().to_draft();
|
||||
|
||||
assert_eq!(draft.columns.len(), 2);
|
||||
assert!(draft.columns[0].indexed);
|
||||
assert_eq!(draft.columns[1].money_mode, MoneyMode::Rounded);
|
||||
assert_eq!(draft.columns.added.len(), 2);
|
||||
assert!(draft.columns.added[0].indexed);
|
||||
assert_eq!(draft.columns.added[1].money_mode, MoneyMode::Rounded);
|
||||
assert_eq!(draft.links[0].mode, LinkMode::Required);
|
||||
assert_eq!(draft.links[1].mode, LinkMode::None);
|
||||
assert_eq!(draft.row_display_columns, vec!["number"]);
|
||||
@@ -276,9 +273,9 @@ mod tests {
|
||||
|
||||
let draft = form.to_draft();
|
||||
|
||||
assert_eq!(draft.columns.len(), 1);
|
||||
assert_eq!(draft.columns[0].name, "number");
|
||||
assert_eq!(draft.columns[0].data_type, "text");
|
||||
assert_eq!(draft.columns.added.len(), 1);
|
||||
assert_eq!(draft.columns.added[0].name, "number");
|
||||
assert_eq!(draft.columns.added[0].data_type, "text");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user