web needs fixes

This commit is contained in:
Filipriec
2026-08-26 15:32:39 +02:00
parent 313166eae5
commit ec1596f0ea
5 changed files with 42 additions and 18 deletions

View File

@@ -298,7 +298,7 @@ impl TableDraft {
self.generated_aliases self.generated_aliases
.iter() .iter()
.find(|entry| entry.source == source) .find(|entry| entry.source == source)
.map(|entry| entry.alias.trim()) .map(|entry| entry.alias.as_str())
.unwrap_or_default() .unwrap_or_default()
} }
@@ -530,7 +530,7 @@ impl TableDraft {
if let Some(error) = validate_accounting_currency(locale, self) { if let Some(error) = validate_accounting_currency(locale, self) {
return Err(error); return Err(error);
} }
if let Some(error) = validate_table_name(locale, self.table_name.trim()) { if let Some(error) = validate_table_name(locale, &self.table_name) {
return Err(error); return Err(error);
} }
if self.table_name_conflicts() { if self.table_name_conflicts() {
@@ -565,10 +565,9 @@ impl TableDraft {
} }
pub(crate) fn into_request( pub(crate) fn into_request(
mut self, self,
locale: Locale, locale: Locale,
) -> Result<PostTableDefinitionRequest, String> { ) -> Result<PostTableDefinitionRequest, String> {
self.table_name = self.table_name.trim().to_string();
self.validate(locale)?; self.validate(locale)?;
Ok(PostTableDefinitionRequest { Ok(PostTableDefinitionRequest {
@@ -770,6 +769,12 @@ mod tests {
}]; }];
assert!(draft.validate(crate::i18n::Locale::default()).is_ok()); assert!(draft.validate(crate::i18n::Locale::default()).is_ok());
draft.generated_aliases[0].alias = " Md ".to_string();
assert!(
draft.validate(crate::i18n::Locale::default()).is_err(),
"boundary whitespace must not be silently removed"
);
draft.generated_aliases[0].alias = "NOTE🙂".to_string(); draft.generated_aliases[0].alias = "NOTE🙂".to_string();
assert!( assert!(
draft.validate(crate::i18n::Locale::default()).is_err(), draft.validate(crate::i18n::Locale::default()).is_err(),
@@ -1105,8 +1110,18 @@ mod tests {
draft.table_name = "general_ledger".to_string(); draft.table_name = "general_ledger".to_string();
assert!(draft.validate(crate::i18n::Locale::default()).is_err()); assert!(draft.validate(crate::i18n::Locale::default()).is_err());
draft.table_name = "invoice".to_string(); draft.table_name = " Invoice ".to_string();
assert!(draft.validate(crate::i18n::Locale::default()).is_err());
draft.table_name = "2026-Sales_Q4".to_string();
assert!(draft.validate(crate::i18n::Locale::default()).is_ok()); assert!(draft.validate(crate::i18n::Locale::default()).is_ok());
assert_eq!(
draft
.into_request(crate::i18n::Locale::default())
.unwrap()
.table_name,
"2026-Sales_Q4"
);
} }
/// A shared table has no books of its own, so the two definition rows that /// A shared table has no books of its own, so the two definition rows that

View File

@@ -71,7 +71,7 @@ pub(crate) async fn load_page(
// for, so it is told what that table is on every render rather than left to // for, so it is told what that table is on every render rather than left to
// read a copy that a `refresh` could have moved on from. // read a copy that a `refresh` could have moved on from.
draft.columns.global = draft.global; draft.columns.global = draft.global;
draft.columns.table_name = draft.table_name.trim().to_string(); draft.columns.table_name = draft.table_name.clone();
let tree = definitions let tree = definitions
.get_profile_tree( .get_profile_tree(

View File

@@ -140,7 +140,7 @@ impl BuilderForm {
// takes no column that posts to one profile's books, and no link // takes no column that posts to one profile's books, and no link
// may point at the table being created. // may point at the table being created.
global: self.global, global: self.global,
table_name: self.table_name.trim().to_string(), table_name: self.table_name.clone(),
}; };
// Drop display columns whose column is gone, so a stale post cannot // Drop display columns whose column is gone, so a stale post cannot
@@ -181,7 +181,7 @@ impl BuilderForm {
.zip(self.generated_alias_names.iter()) .zip(self.generated_alias_names.iter())
.map(|(source, alias)| GeneratedAlias { .map(|(source, alias)| GeneratedAlias {
source: source.trim().to_string(), source: source.trim().to_string(),
alias: alias.trim().to_string(), alias: alias.clone(),
}) })
.collect(), .collect(),
} }
@@ -576,16 +576,16 @@ mod tests {
form.column_rounding.push("exact".into()); form.column_rounding.push("exact".into());
form.column_currencies.push("EUR".into()); form.column_currencies.push("EUR".into());
form.generated_alias_sources = vec!["debit".into(), "account".into()]; form.generated_alias_sources = vec!["debit".into(), "account".into()];
form.generated_alias_names = vec![" md ".into(), "ucet".into()]; form.generated_alias_names = vec!["Md 🙂".into(), "ucet".into()];
let mut draft = form.to_draft(); let mut draft = form.to_draft();
draft.columns.catalog = crate::schema::tests::catalog(); draft.columns.catalog = crate::schema::tests::catalog();
assert_eq!(draft.alias_for("debit"), "md"); assert_eq!(draft.alias_for("debit"), "Md 🙂");
assert_eq!( assert_eq!(
draft.aliased_generated_columns(), draft.aliased_generated_columns(),
vec![ vec![
("debit".to_string(), "md".to_string()), ("debit".to_string(), "Md 🙂".to_string()),
("account".to_string(), "ucet".to_string()), ("account".to_string(), "ucet".to_string()),
] ]
); );
@@ -601,8 +601,8 @@ mod tests {
}; };
let rows = page.column_rows(); let rows = page.column_rows();
let row = |name: &str| rows.iter().find(|row| row.name == name).unwrap(); let row = |name: &str| rows.iter().find(|row| row.name == name).unwrap();
assert_eq!(row("debit").alias_source.as_deref(), Some("debit")); assert_eq!(row("Md 🙂").alias_source.as_deref(), Some("debit"));
assert_eq!(row("debit").alias, "md"); assert_eq!(row("Md 🙂").alias, "Md 🙂");
// `account` is reported by the catalog, so it is named there and the // `account` is reported by the catalog, so it is named there and the
// physical column it lands in is not offered a second field. // physical column it lands in is not offered a second field.
assert_eq!(row("account").alias_source.as_deref(), Some("account")); assert_eq!(row("account").alias_source.as_deref(), Some("account"));

View File

@@ -629,7 +629,7 @@ impl ColumnDraft {
let column_name = if compound { let column_name = if compound {
column_type.clone() column_type.clone()
} else { } else {
self.name_input.trim().to_string() self.name_input.clone()
}; };
if column_name.is_empty() { if column_name.is_empty() {
@@ -820,10 +820,13 @@ impl ColumnDraft {
column_type: &str, column_type: &str,
) -> Option<String> { ) -> Option<String> {
let target = link_target(column_type)?; let target = link_target(column_type)?;
if target == LEDGER_ACCOUNTS_TABLE { if common::alias::canonical_table_name(target) == LEDGER_ACCOUNTS_TABLE {
return Some(crate::tr!(locale, "schema-err-account-link")); return Some(crate::tr!(locale, "schema-err-account-link"));
} }
(!self.table_name.is_empty() && target == self.table_name).then(|| { (!self.table_name.is_empty()
&& common::alias::canonical_table_name(target)
== common::alias::canonical_table_name(&self.table_name))
.then(|| {
crate::tr!( crate::tr!(
locale, locale,
"schema-err-link-self", "schema-err-link-self",
@@ -1781,6 +1784,8 @@ pub(crate) mod tests {
draft.name_input = "Total".to_string(); draft.name_input = "Total".to_string();
assert!(draft.add_from_inputs(crate::i18n::Locale::default()).is_err()); assert!(draft.add_from_inputs(crate::i18n::Locale::default()).is_err());
draft.name_input = " total".to_string();
assert!(draft.add_from_inputs(crate::i18n::Locale::default()).is_err());
draft.name_input = "created_at".to_string(); draft.name_input = "created_at".to_string();
assert!(draft.add_from_inputs(crate::i18n::Locale::default()).is_err()); assert!(draft.add_from_inputs(crate::i18n::Locale::default()).is_err());
@@ -2220,7 +2225,7 @@ pub(crate) mod tests {
draft.table_name = "invoice".to_string(); draft.table_name = "invoice".to_string();
draft.name_input = "parent".to_string(); draft.name_input = "parent".to_string();
draft.type_input = "link".to_string(); draft.type_input = "link".to_string();
draft.link_table_input = "invoice".to_string(); draft.link_table_input = "INVOICE".to_string();
let error = draft.add_from_inputs(crate::i18n::Locale::default()).unwrap_err(); let error = draft.add_from_inputs(crate::i18n::Locale::default()).unwrap_err();
assert!(error.contains("cannot point at the table"), "{error}"); assert!(error.contains("cannot point at the table"), "{error}");
@@ -2245,6 +2250,10 @@ pub(crate) mod tests {
let error = draft.add_from_inputs(crate::i18n::Locale::default()).unwrap_err(); let error = draft.add_from_inputs(crate::i18n::Locale::default()).unwrap_err();
assert!(error.contains("built into ACCOUNTING"), "{error}"); assert!(error.contains("built into ACCOUNTING"), "{error}");
draft.link_table_input = "LEDGER_ACCOUNTS".to_string();
let error = draft.add_from_inputs(crate::i18n::Locale::default()).unwrap_err();
assert!(error.contains("built into ACCOUNTING"), "{error}");
} }
/// The names a definition row generates are the table's columns too, so a /// The names a definition row generates are the table's columns too, so a