use crate::{
RelatedFormFault,
form::RecordForm,
resource::{Mounted, Resource},
};
pub(in crate::panel) struct FormFacts {
has_form: bool,
keys: Vec<String>,
soft_deletes: bool,
own_keys: Option<String>,
}
impl FormFacts {
pub(super) fn of<R: Resource>(mounted: &Mounted<R>) -> Self {
Self {
has_form: <R::Form as RecordForm>::HAS_FORM,
keys: mounted
.form
.fields()
.map(|field| field.name().to_string())
.collect(),
soft_deletes: mounted.soft_delete.is_some(),
own_keys: mounted.form.needs_own_keys().map(str::to_string),
}
}
pub(super) fn related_faults(
&self,
child: &Self,
slug: &str,
foreign_key: &str,
) -> Vec<RelatedFormFault> {
let mut faults = Vec::new();
if !self.has_form {
faults.push(RelatedFormFault::NoOwnerForm);
}
if !child.has_form {
faults.push(RelatedFormFault::NoForm);
} else if !child.keys.iter().any(|key| key == foreign_key) {
faults.push(RelatedFormFault::UnboundForeignKey {
column: foreign_key.to_string(),
});
}
if child.soft_deletes {
faults.push(RelatedFormFault::SoftDeletes);
}
if let Some(field) = &child.own_keys {
faults.push(RelatedFormFault::OwnKeys {
field: field.clone(),
});
}
let prefix = format!("{slug}.");
faults.extend(
self.keys
.iter()
.filter(|key| *key == slug || key.starts_with(&prefix))
.map(|key| RelatedFormFault::ShadowedKey { field: key.clone() }),
);
faults
}
}