-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Created schema for flexible and extensible forms #11
Changes from 4 commits
eaf3fb1
403418b
340a355
4e9cd34
3208cf4
48f9b5c
88d71b8
5ba3174
48e0bfa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
pub mod models; | ||
|
||
use std::sync::Arc; | ||
use std::time::Duration; | ||
|
||
use anyhow::Context; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
use mongodb::bson::{oid::ObjectId, DateTime}; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Serialize, Deserialize, Clone, Debug)] | ||
pub struct User { | ||
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")] | ||
id: Option<ObjectId>, | ||
first_name: String, | ||
last_name: String, | ||
national_health_identifer: String, | ||
email_address: String, | ||
hashed_password: String, | ||
is_patient: bool, | ||
caregivers: Vec<ObjectId>, | ||
form_templates: Vec<Form>, | ||
form_filled: Vec<Form>, | ||
} | ||
|
||
#[derive(Serialize, Deserialize, Clone, Debug)] | ||
pub struct Form { | ||
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")] | ||
id: Option<ObjectId>, | ||
title: String, | ||
created_by: ObjectId, | ||
created_at: DateTime, | ||
questions: Vec<Question>, | ||
events: Vec<Event>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having The alternative would be e.g. have three collections, of Although now that I say that I realize that it'd also be kind of awkward given that we're working with Mongo rather than a traditional relational DB - although Mongo does still have |
||
} | ||
|
||
#[derive(Serialize, Deserialize, Clone, Debug)] | ||
pub enum Event { | ||
FormSubmitted(FormSubmitted), | ||
QuestionEdited(QuestionEdited), | ||
} | ||
|
||
#[derive(Serialize, Deserialize, Clone, Debug)] | ||
pub struct QuestionEdited { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How will questions being added/removed (so that the total number of questions changes) work? If a given question is edited in such a way that it has a different semantic meaning (i.e. we just replace it entirely), is there any reason to retain the same id rather than just treating it as a deletion + a creation? Is this intended specifically for cases where questions are edited while keeping the same meaning (e.g. typo corrections, or rephrasing the same general question, etc)? |
||
question_id: ObjectId, | ||
former_question: Question, | ||
new_question: Question, | ||
edited_by: ObjectId, | ||
edited_at: DateTime, | ||
} | ||
|
||
#[derive(Serialize, Deserialize, Clone, Debug)] | ||
pub struct FormSubmitted { | ||
answers: Vec<QuestionAndAnswer>, | ||
submitted_by: ObjectId, | ||
submitted_at: DateTime, | ||
} | ||
|
||
#[derive(Serialize, Deserialize, Clone, Debug)] | ||
pub enum Question { | ||
Multichoice(MultichoiceQuestion), | ||
Slider(SliderQuestion), | ||
FreeForm(FreeFormQuestion), | ||
} | ||
|
||
pub type MultichoiceAnswer = ObjectId; | ||
pub type SliderAnswer = f64; | ||
pub type FreeFormAnswer = String; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is it necessary to retype these basic values? They have no close conflicts. |
||
|
||
#[derive(Serialize, Deserialize, Clone, Debug)] | ||
pub enum QuestionAndAnswer { | ||
Multichoice(MultichoiceQuestion, MultichoiceAnswer), | ||
Slider(SliderQuestion, SliderAnswer), | ||
FreeForm(FreeFormQuestion, FreeFormAnswer), | ||
} | ||
|
||
// In the template, the answer will be set to the default | ||
// it is when the form is opened | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment is out of date given that the answer is no longer stored on |
||
#[derive(Serialize, Deserialize, Clone, Debug, Default)] | ||
pub struct FreeFormQuestion { | ||
id: ObjectId, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be serde-renamed to |
||
title: String, | ||
max_length: u64, | ||
min_length: u64, | ||
} | ||
|
||
// In the template, the answer will store the default value | ||
// for when the form is opened | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment is out of date given that the answer is no longer stored on |
||
#[derive(Serialize, Deserialize, Clone, Debug, Default)] | ||
pub struct SliderQuestion { | ||
id: ObjectId, | ||
title: String, | ||
units: Option<String>, | ||
low: f64, | ||
high: f64, | ||
step: f64, | ||
} | ||
|
||
#[derive(Serialize, Deserialize, Clone, Debug, Default)] | ||
pub struct MultichoiceQuestion { | ||
id: ObjectId, | ||
title: String, | ||
options: Vec<MultichoiceQuestionOption>, | ||
min_selected: u64, | ||
max_selected: u64, | ||
} | ||
|
||
#[derive(Serialize, Deserialize, Clone, Debug, Default)] | ||
pub struct MultichoiceQuestionOption { | ||
name: String, | ||
id: ObjectId, | ||
} | ||
|
||
fn _example() { | ||
let _form: Form = Form { | ||
id: Some(ObjectId::new()), | ||
title: String::from("Tremors"), | ||
created_by: ObjectId::new(), | ||
created_at: DateTime::now(), | ||
questions: vec![ | ||
Question::Multichoice(MultichoiceQuestion { | ||
id: ObjectId::new(), | ||
title: String::from("How many times have you experienced this in the last week?"), | ||
options: vec![MultichoiceQuestionOption { | ||
name: String::from("Once"), | ||
id: ObjectId::new(), | ||
}], | ||
min_selected: 1, | ||
max_selected: 2, | ||
}), | ||
Question::FreeForm(FreeFormQuestion { | ||
id: ObjectId::new(), | ||
title: String::from("Is there anything else you would like to add?"), | ||
max_length: 200, | ||
min_length: 0, | ||
}), | ||
], | ||
events: vec![ | ||
Event::QuestionEdited(QuestionEdited { | ||
question_id: ObjectId::new(), | ||
former_question: Question::FreeForm(FreeFormQuestion { | ||
id: ObjectId::new(), | ||
title: String::from("How are you feeling this week?"), | ||
max_length: 100, | ||
min_length: 10, | ||
}), | ||
new_question: Question::FreeForm(FreeFormQuestion { | ||
id: ObjectId::new(), | ||
title: String::from("Is there anything else you would like to add?"), | ||
max_length: 200, | ||
min_length: 0, | ||
}), | ||
edited_at: DateTime::now(), | ||
edited_by: ObjectId::new(), | ||
}), | ||
Event::FormSubmitted(FormSubmitted { | ||
answers: vec![ | ||
QuestionAndAnswer::Multichoice( | ||
MultichoiceQuestion { | ||
id: ObjectId::new(), | ||
title: String::from( | ||
"How many times have you experienced this in the last week?", | ||
), | ||
options: vec![MultichoiceQuestionOption { | ||
name: String::from("Once"), | ||
id: ObjectId::new(), | ||
}], | ||
min_selected: 1, | ||
max_selected: 2, | ||
}, | ||
ObjectId::new(), | ||
), | ||
QuestionAndAnswer::FreeForm( | ||
FreeFormQuestion { | ||
id: ObjectId::new(), | ||
title: String::from("Is there anything else you would like to add?"), | ||
max_length: 200, | ||
min_length: 0, | ||
}, | ||
String::from("I wasn't able to press the elevator buttons this morning"), | ||
), | ||
], | ||
submitted_at: DateTime::now(), | ||
submitted_by: ObjectId::new(), | ||
}), | ||
], | ||
}; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kinda confused why
form_templates
andform_filled
are distinct when instances of filled-out forms are stored asEvent::FormSubmitted
on a givenForm
instance; presumably this is just out of date?