Skip to main content

qa_spec/spec/
question.rs

1use crate::expr::Expr;
2use crate::store::StoreTarget;
3use schemars::JsonSchema;
4use serde::{Deserialize, Serialize};
5
6/// Supported question data types.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
8#[serde(rename_all = "snake_case")]
9pub enum QuestionType {
10    String,
11    Boolean,
12    Integer,
13    Number,
14    Enum,
15}
16
17/// Constraints that can be enforced per question.
18#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
19pub struct Constraint {
20    #[serde(skip_serializing_if = "Option::is_none")]
21    pub pattern: Option<String>,
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub min: Option<f64>,
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub max: Option<f64>,
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub min_len: Option<usize>,
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub max_len: Option<usize>,
30}
31
32/// Definition of a single question inside a form.
33#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
34pub struct QuestionSpec {
35    pub id: String,
36    #[serde(rename = "type")]
37    pub kind: QuestionType,
38    pub title: String,
39    #[serde(default, skip_serializing_if = "Option::is_none")]
40    pub description: Option<String>,
41    #[serde(default)]
42    pub required: bool,
43    #[serde(default, skip_serializing_if = "Option::is_none")]
44    pub choices: Option<Vec<String>>,
45    #[serde(default, skip_serializing_if = "Option::is_none")]
46    pub default_value: Option<String>,
47    #[serde(default)]
48    pub secret: bool,
49    #[serde(default, skip_serializing_if = "Option::is_none")]
50    pub visible_if: Option<Expr>,
51    #[serde(default, skip_serializing_if = "Option::is_none")]
52    pub constraint: Option<Constraint>,
53    #[serde(default)]
54    pub policy: QuestionPolicy,
55}
56
57/// Per-question overrides for progress behavior.
58#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema, Default)]
59pub struct QuestionPolicy {
60    #[serde(default, skip_serializing_if = "Vec::is_empty")]
61    pub skip_if_present_in: Vec<StoreTarget>,
62    #[serde(default)]
63    pub editable_if_from_default: bool,
64}