implemented FROM next to the link for other table columns

This commit is contained in:
Priec
2026-09-04 18:09:16 +02:00
parent 4506643dff
commit 6689e6c7f9
4 changed files with 83 additions and 9 deletions

Binary file not shown.

2
server

Submodule server updated: 66ce287729...41a34de46f

View File

@@ -74,6 +74,20 @@ impl Destination {
.map(|column| column.name.clone())
.collect()
}
fn is_verification(&self, name: &str) -> bool {
self.columns
.iter()
.any(|column| column.name == name && column.verification)
}
fn writable_types(&self) -> HashMap<String, String> {
self.types
.iter()
.filter(|(name, _)| !self.is_verification(name))
.map(|(name, data_type)| (name.clone(), data_type.clone()))
.collect()
}
}
/// GET /admin/import
@@ -625,7 +639,8 @@ async fn prepared(
read_mapping(locale, &chosen, &source).map_err(|message| reject(headers, message))?;
let prepared_names = destination.prepared_names(&assignments);
let mut prepared = prepare(&assignments, &source, &prepared_names);
normalize_dates(locale, &mut prepared, &destination.types, form.date_format)
let writable_types = destination.writable_types();
normalize_dates(locale, &mut prepared, &writable_types, form.date_format)
.map_err(|message| reject(headers, message))?;
Ok((destination, source, prepared))
}
@@ -657,7 +672,8 @@ fn source_options(locale: Locale, source: &Source) -> Vec<SourceOption> {
}
/// One prepared row as the staged import takes it: values under their destination
/// names, converted to the column's type.
/// names. Writable values are converted to their column type; projection
/// assertions retain the CSV cell's exact text.
fn import_row(
locale: Locale,
destination: &Destination,
@@ -666,6 +682,21 @@ fn import_row(
) -> Result<TableDataImportRow, String> {
let mut data = HashMap::new();
for (index, column) in columns.iter().enumerate() {
let raw = row.get(index).map(String::as_str).unwrap_or_default();
if destination.is_verification(column) {
let kind = if raw.is_empty() {
prost_types::value::Kind::NullValue(prost_types::NullValue::NullValue as i32)
} else {
prost_types::value::Kind::StringValue(raw.to_string())
};
data.insert(
column.clone(),
prost_types::Value {
kind: Some(kind),
},
);
continue;
}
let data_type = destination.types.get(column).ok_or_else(|| {
tr!(
locale,
@@ -673,11 +704,7 @@ fn import_row(
"column" => column.clone(),
)
})?;
let value = csv_value(
locale,
row.get(index).map(String::as_str).unwrap_or_default(),
data_type,
)?;
let value = csv_value(locale, raw, data_type)?;
data.insert(column.clone(), value);
}
Ok(TableDataImportRow { data, link_display_columns: Vec::new() })
@@ -773,6 +800,9 @@ fn unavailable(headers: &HeaderMap, message: String) -> Response {
#[cfg(test)]
mod tests {
use super::*;
use prost_types::value::Kind;
use crate::pages::import_export::import::destination::DestinationKey;
fn source() -> Source {
read_source(
@@ -801,4 +831,48 @@ mod tests {
assert!(options[3].label.contains('4'), "{}", options[3].label);
}
#[test]
fn projection_assertions_keep_exact_csv_text() {
let destination = Destination {
table_name: "orders".to_string(),
table_revision: 1,
columns: vec![
DestinationColumn {
key: DestinationKey::Column(1),
name: "projected_amount".to_string(),
required: false,
verification: true,
},
DestinationColumn {
key: DestinationKey::Column(2),
name: "ordinary_number".to_string(),
required: false,
verification: false,
},
],
types: HashMap::from([
("projected_amount".to_string(), "NUMERIC".to_string()),
("ordinary_number".to_string(), "BIGINT".to_string()),
]),
};
let row = import_row(
Locale::default(),
&destination,
&["projected_amount".to_string(), "ordinary_number".to_string()],
&["10.00".to_string(), "001".to_string()],
)
.unwrap();
assert_eq!(
row.data["projected_amount"].kind,
Some(Kind::StringValue("10.00".to_string()))
);
assert_eq!(
row.data["ordinary_number"].kind,
Some(Kind::NumberValue(1.0))
);
assert!(!destination.writable_types().contains_key("projected_amount"));
}
}