diff --git a/Cargo.lock b/Cargo.lock index 8a47e71..ebf003e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2948,7 +2948,7 @@ dependencies = [ [[package]] name = "portal" -version = "0.3.24" +version = "0.3.25" dependencies = [ "anyhow", "arc-swap", diff --git a/src/content.rs b/src/content.rs index abc6dfd..db02c14 100644 --- a/src/content.rs +++ b/src/content.rs @@ -446,6 +446,12 @@ pub struct Requirement { /// `ResourceSpec` mechanism a `Feature.resource` uses. #[serde(default)] pub resource: Option, + /// `type: select` only - a static list of options, as an + /// alternative to a `resource`. Each string is both the option's + /// stored value and its label. Faithful to the ancestor format's + /// inline enums. + #[serde(default)] + pub options: Vec, /// `type: select` only - which field in each item is the option's /// stable id. Defaults to trying `_id` then `id`. #[serde(default)] @@ -1204,9 +1210,12 @@ pub fn validate_questions( .collect(); for feature in &alternative.features { for requirement in &feature.requirements { - if requirement.kind == "select" && requirement.resource.is_none() { + if requirement.kind == "select" + && requirement.resource.is_none() + && requirement.options.is_empty() + { anyhow::bail!( - "question {:?} alternative {:?} feature {:?}: requirement {:?} is type: select but declares no resource to select from", + "question {:?} alternative {:?} feature {:?}: requirement {:?} is type: select but declares neither a resource nor inline options", question.id, alternative.name, feature.name, requirement.name ); } diff --git a/src/resource.rs b/src/resource.rs index 11410b3..7afdb1c 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -68,6 +68,16 @@ pub async fn get_requirement_options( .iter() .find(|r| r.name == requirement_name) .ok_or_else(|| ServerFnError::new("unknown requirement"))?; + // Inline options: return them as {id,label} objects, the shape the + // SelectField renders, without touching a resource. + if !requirement.options.is_empty() { + let items: Vec = requirement + .options + .iter() + .map(|o| serde_json::json!({ "id": o, "label": o })) + .collect(); + return Ok(serde_json::Value::Array(items)); + } let resource = requirement .resource .as_ref()