Browse Source

Continued site_poll_post

integrate_codes_to_fields
anghenfil 2 years ago
parent
commit
6f65f5cc2b
  1. 6
      src/db_system/code_management.rs
  2. 20
      src/survey_manager/cache_generator.rs
  3. 87
      src/webserver/site_poll_get.rs
  4. 116
      src/webserver/site_poll_post.rs

6
src/db_system/code_management.rs

@ -10,9 +10,9 @@ lazy_static! {
pub static ref CODE_MANAGER: RwLock<HashMap<String, String>> = RwLock::new(db_system::storage::DOCUMENTS.write().unwrap().load_codes());
}
pub fn check_code(code : &str) -> Option<String>{
pub fn check_code(code : &str) -> Result<String, status::Custom<content::Html<String>>>{
match CODE_MANAGER.read().unwrap().get(code) {
Some(code) => Some(code.clone()),
None => None
Some(code) => Ok(code.clone()),
None => Err(status::Custom(Status::NotFound, content::Html(templates::get_error("Error 404: Survey not found. Please check survey code.", "", vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), Vec::new()))))
}
}

20
src/survey_manager/cache_generator.rs

@ -41,9 +41,9 @@ pub fn generate_questionblock(questionblock : &database::QuestionBlock, pollid :
let questions : String = questionblock.questions.iter().map(|question| {
if question.optional {
webserver::delivery::CACHE.write().unwrap().add_value(format!("{}/q{}-optional", pollid, question.identifier), String::from("true")); //TODO: handle error if there is more then one question with identifier X
webserver::delivery::CACHE.write().unwrap().add_value(format!("{}/{}-optional", pollid, question.identifier), String::from("true")); //TODO: handle error if there is more then one question with identifier X
}else{
webserver::delivery::CACHE.write().unwrap().add_value(format!("{}/q{}-optional", pollid, question.identifier), String::from("false"));
webserver::delivery::CACHE.write().unwrap().add_value(format!("{}/{}-optional", pollid, question.identifier), String::from("false"));
}
@ -83,25 +83,25 @@ pub fn generate_question(question : &database::Question, last_question_type : i8
<div class=\"group d-flex\">
<p class=\"question\">{}</p>
<div class=\"checkboxes ml-auto\">
<input type=\"hidden\" name=\"q{}\" />
<input type=\"hidden\" name=\"{}\" />
<label class=\"checkbox form-group\">
<input type=\"radio\" name=\"q{}\" value=\"N/A\" oninvalid=\"report_missing()\"{}>
<input type=\"radio\" name=\"{}\" value=\"N/A\" oninvalid=\"report_missing()\"{}>
<span class=\"default\"></span>
</label>
<label class=\"checkbox form-group\">
<input type=\"radio\" name=\"q{}\" value=\"1\">
<input type=\"radio\" name=\"{}\" value=\"1\">
<span class=\"default\"></span>
</label>
<label class=\"checkbox form-group\">
<input type=\"radio\" name=\"q{}\" value=\"2\">
<input type=\"radio\" name=\"{}\" value=\"2\">
<span class=\"default\"></span>
</label>
<label class=\"checkbox form-group\">
<input type=\"radio\" name=\"q{}\" value=\"3\">
<input type=\"radio\" name=\"{}\" value=\"3\">
<span class=\"default\"></span>
</label>
<label class=\"checkbox form-group\">
<input type=\"radio\" name=\"q{}\" value=\"4\">
<input type=\"radio\" name=\"{}\" value=\"4\">
<span class=\"default\"></span>
</label>
</div>
@ -112,14 +112,14 @@ pub fn generate_question(question : &database::Question, last_question_type : i8
<div>
<p>{}</p>
<div class=\"textfield\">
<textarea class=\"textfield\" name=\"q{}\" rows=\"5\" {}></textarea>
<textarea class=\"textfield\" name=\"{}\" rows=\"5\" {}></textarea>
</div>
</div>", question.question, question.identifier, required);
}else if question.questiontype == 30 {
let options : String = question.selection_options.iter().map(|option|{
format!("<option value=\"{}\">{}</option>", option, option)
}).collect();
return format!("<div><p>{}</p><select name=\"q{}\" {}>
return format!("<div><p>{}</p><select name=\"{}\" {}>
{}
</select></div>", question.question, question.identifier, required, options);
}else{

87
src/webserver/site_poll_get.rs

@ -13,9 +13,8 @@ use db_system::storage;
pub fn poll(code: &RawStr, sessionid: Option<&RawStr>) -> Result<content::Html<String>, status::Custom<content::Html<String>>> {
let sessionid: String = session_manager::session_handling(sessionid, code)?; //Aquire valid sessionid or report error
let surveyid = check_code(code).unwrap();
println!("{} -> {}", code, surveyid);
let surveyid = check_code(code)?;
let mut session : webserver::session_manager::Session= session_manager::SESSIONS.read().unwrap().get(&sessionid).unwrap().clone();
let maxsteps = match storage::DOCUMENTS.read().unwrap().get(&surveyid){
Some(document) => {
match document.get_qbc("qbc"){ //Get QuestionBlockContainer from document
@ -34,81 +33,33 @@ pub fn poll(code: &RawStr, sessionid: Option<&RawStr>) -> Result<content::Html<S
let mut step = session_manager::SESSIONS.read().unwrap().get(&sessionid).unwrap().step.clone();
if step == 0 {
}else if step < maxsteps {
}else if step == maxsteps{
}
let cache = webserver::delivery::CACHE.read().unwrap();
let content = cache.get_file(format!("{}/{}", &surveyid, step));
if step < maxsteps {
let cache = webserver::delivery::CACHE.read().unwrap();
let content = cache.get_file(format!("{}/{}", &surveyid, step));
let template_content = format!("{}
let template_content = format!("
<div class=\"mainframe text-center align-middle\">
<form action=\"/poll?code={}&sessionid={}\" method=\"post\">
{}
<button type=\"submit\" name=\"submit\" value=\"{}\" onclick=\"on_submit()\">Continue</button>
</form>
</div>", "", code, sessionid, content.unwrap().content, step);
return Ok(content::Html(templates::get_main(&template_content, vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()),vec!("script/poll.js".to_string()))))
/*
let sessionid: String = match session_manager::session_handling(sessionid, code) {
Ok(sessionid) => sessionid,
Err(e) => return Err(e)
};
let codetemp = code.to_string().clone();
let poll : String = if code_management::CODE_MANAGER.read().unwrap().contains_key(&codetemp) {
code_management::CODE_MANAGER.read().unwrap().get(&codetemp).unwrap().clone()
}else{
return Err(status::Custom(Status::BadRequest, content::Html(templates::get_error("Error 400: Invalid Code", "The Code your entered is invalid.", vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), Vec::new()))))
};
let mut logo = String::new();
if Path::new(&format!("data/logos/{}.png", &poll)).exists(){
logo = format!("<img class=\"logo\" src=\"/images/{}.png\" alt=\"logo\">", &poll);
}
let mut step = session_manager::SESSIONS.read().unwrap().get(&sessionid).unwrap().step.clone();
</div>", code, sessionid, content.unwrap().content, step);
if step == 0 { //First step, change step to first questionblock
step = String::from("questionblock-0"); //TODO: Check if at least one questionblock exists
}else{ //Step should look like "questionblock-x"
if !webserver::delivery::CACHE.read().unwrap().check_file(&format!("{}/{}", &poll, &step)) {
//Questionblock unknown (not in cache)
eprintln!("Error 500 occured: {}/{} not found in cache.", &poll, &step);
return Err(status::Custom(Status::InternalServerError, content::Html(templates::get_error("Error 500: Cache error", "Missing questionblock in cache.", vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), Vec::new()))))
}
}
session.step = session.step+1;
session_manager::SESSIONS.write().unwrap().insert(sessionid.clone(), session);
if session_manager::SESSIONS.read().unwrap().get(&sessionid).unwrap().complete {
let template_content = format!("{}
return Ok(content::Html(templates::get_main(&template_content, vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()),vec!("script/poll.js".to_string()))))
}else if step == maxsteps{
let template_content = format!("
<div class=\"mainframe text-center align-middle\">
<h1>Completed!</h1>
<p>Thank you for your participation!</p>
</div>", logo);
return Ok(content::Html(templates::get_main(&template_content, vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), Vec::new())))
}
<h1>Thank you for participating!</h1>
</div>");
let cache = webserver::delivery::CACHE.read().unwrap();
let content = cache.get_file(format!("{}/{}", &poll, step));
session.step = session.step+1;
session_manager::SESSIONS.write().unwrap().insert(sessionid.clone(), session);
if content.is_ok() {
let template_content = format!("{}
<div class=\"mainframe text-center align-middle\">
<form action=\"/poll?code={}&sessionid={}\" method=\"post\">
{}
<button type=\"submit\" name=\"submit\" value=\"{}\" onclick=\"on_submit()\">Continue</button>
</form>
</div>", logo, code, sessionid, content.unwrap().content, step);
return Ok(content::Html(templates::get_main(&template_content, vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()),vec!("script/poll.js".to_string()))))
} else {
return Err(status::Custom(Status::NotFound, content::Html(templates::get_error("Error 404: Not found", "Couldn't find requested survey", vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), Vec::new()))))
}else{
return Err(status::Custom(Status::BadRequest, content::Html(templates::get_error("Error 400", "Submitted data were invalid", vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), Vec::new()))))
}
*/
}
}

116
src/webserver/site_poll_post.rs

@ -13,12 +13,13 @@ pub fn poll(code: &RawStr, data: Form<FormData>, sessionid: Option<&RawStr>) ->
let mut data_fields = data.fields.clone();
let sessionid: String = session_manager::session_handling(sessionid, code)?; //Aquire valid sessionid or report error
let surveyid = check_code(code).unwrap();
let mut session : webserver::session_manager::Session= session_manager::SESSIONS.read().unwrap().get(&sessionid).unwrap().clone();
let qbc = match storage::DOCUMENTS.read().unwrap().get(&surveyid){
let surveyid = check_code(code)?;
let mut session: webserver::session_manager::Session = session_manager::SESSIONS.read().unwrap().get(&sessionid).unwrap().clone();
let maxsteps = match storage::DOCUMENTS.read().unwrap().get(&surveyid) {
Some(document) => {
match document.get_qbc("qbc"){ //Get QuestionBlockContainer from document
Some(qbc) => qbc.clone(),
match document.get_qbc("qbc") { //Get QuestionBlockContainer from document
Some(qbc) => qbc.questionblocks.len(),
None => {
eprintln!("KeyNotFound: qbc for survey {}", surveyid);
return Err(status::Custom(Status::InternalServerError, content::Html(templates::get_error("Error 500: Internal Server Error.", "", vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), Vec::new()))))
@ -30,18 +31,25 @@ pub fn poll(code: &RawStr, data: Form<FormData>, sessionid: Option<&RawStr>) ->
return Err(status::Custom(Status::InternalServerError, content::Html(templates::get_error("Error 500: Internal Server Error.", "", vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), Vec::new()))))
}
};
let maxsteps = qbc.questionblocks.len();
if session.step == 0 {
}else if session.step < maxsteps {
}else if session.step == maxsteps{
}
let qbc = match storage::DOCUMENTS.read().unwrap().get(&surveyid) {
Some(document) => {
match document.get_qbc("qbc") { //Get QuestionBlockContainer from document
Some(qbc) => qbc.clone(),
None => {
eprintln!("KeyNotFound: qbc for survey {}", surveyid);
return Err(status::Custom(Status::InternalServerError, content::Html(templates::get_error("Error 500: Internal Server Error.", "", vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), Vec::new()))))
}
}
}
None => {
eprintln!("DocumentNotFound: {}", surveyid);
return Err(status::Custom(Status::InternalServerError, content::Html(templates::get_error("Error 500: Internal Server Error.", "", vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), Vec::new()))))
}
};
let mut submitted_step: usize = match data_fields.get("submit").cloned(){
Some(submitted_step) => match submitted_step.parse::<usize>(){
let mut submitted_step: usize = match data_fields.get("submit").cloned() {
Some(submitted_step) => match submitted_step.parse::<usize>() {
Ok(submitted_step) => submitted_step,
Err(_) => return Err(status::Custom(Status::BadRequest, content::Html(templates::get_error("Error 400", "Submitted data were invalid", vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), Vec::new()))))
},
@ -49,38 +57,86 @@ pub fn poll(code: &RawStr, data: Form<FormData>, sessionid: Option<&RawStr>) ->
};
let mut error = false;
if submitted_step != session.step{ //user submitted wrong step
if session.step > submitted_step { //Example: User submitted step 6 but should submit step 4
if submitted_step != session.step-1 { //user submitted wrong step
if session.step-1 > submitted_step { //Example: User submitted step 6 but should submit step 4
//do not accept step and display expected step (in example step 4)
println!("User submitted later step");
error = true;
}else if submitted_step < session.step { //Example: user submitted step 3 again, but should be at step 5
} else if submitted_step < session.step-1 { //Example: user submitted step 3 again, but should be at step 5
//accept step and display next step (in example step 4)
session.step = submitted_step;
session_manager::SESSIONS.write().unwrap().insert(sessionid, session.clone());
println!("User submitted earlier step");
session.step = submitted_step+1;
session_manager::SESSIONS.write().unwrap().insert(sessionid.clone(), session.clone());
}
}
println!("Loading questionblock for step: {}", session.step-1);
//TODO: Check if every required field is there
let questionblock : &database::QuestionBlock = match &qbc.questionblocks.get(session.step){
let questionblock: &database::QuestionBlock = match &qbc.questionblocks.get(session.step-1) {
Some(questionblock) => questionblock,
None => return Err(status::Custom(Status::BadRequest, content::Html(templates::get_error("Error 400", "Submitted data were invalid", vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), Vec::new()))))
};
let mut processed_fields : HashMap<String, String> = HashMap::new(); //We will add every question to this map. We won't add data which doesn't belong to any question
let mut processed_fields: HashMap<String, String> = HashMap::new(); //We will add every question to this map. We won't add data which doesn't belong to any question
for question in questionblock.questions.iter(){ //TODO: Check if input type is correct
if !question.optional && !data_fields.contains_key(&question.identifier){ //TODO: maybe report error
error = true;
let fields : String = data_fields.keys().map(|s|s.clone()).collect();
println!("Datafields: {}", fields);
for question in questionblock.questions.iter() { //TODO: Check if input type is correct
if !question.optional && !data_fields.contains_key(&question.identifier) { //TODO: report error
error = true;
eprintln!("Missing question: {}",question.identifier);
break;
}
//processed_fields.insert(question.identifier, data_fields.get(&question.identifier).unwrap().clone())
eprintln!("Mapping question: {}",question.identifier);
processed_fields.insert(question.identifier.clone(), data_fields.get(&question.identifier).unwrap().clone());
}
if !error{
if !error {
//Save data to database
}else{
if session.step < maxsteps{
}
let cache = webserver::delivery::CACHE.read().unwrap();
let content = cache.get_file(format!("{}/{}", &surveyid, session.step));
let template_content = format!("{}
<div class=\"mainframe text-center align-middle\">
<form action=\"/poll?code={}&sessionid={}\" method=\"post\">
{}
<button type=\"submit\" name=\"submit\" value=\"{}\" onclick=\"on_submit()\">Continue</button>
</form>
</div>", "", code, sessionid, content.unwrap().content, session.step);
session.step = session.step+1;
session_manager::SESSIONS.write().unwrap().insert(sessionid.clone(), session);
Err(status::Custom(Status::NotFound, content::Html(templates::get_error("Error 404: Not implemented yet.", "", vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), Vec::new()))))
return Ok(content::Html(templates::get_main(&template_content, vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), vec!("script/poll.js".to_string()))))
} else if session.step == maxsteps{
let template_content = format!("
<div class=\"mainframe text-center align-middle\">
<h1>Thank you for participating!</h1>
</div>");
session.step = session.step+1;
session_manager::SESSIONS.write().unwrap().insert(sessionid.clone(), session);
return Ok(content::Html(templates::get_main(&template_content, vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), vec!("script/poll.js".to_string()))))
} else {
return Err(status::Custom(Status::BadRequest, content::Html(templates::get_error("Error 400", "Submitted data were invalid", vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), Vec::new()))))
}
} else { //If error occured, display last stap (session.step-1) again.
let cache = webserver::delivery::CACHE.read().unwrap();
let content = cache.get_file(format!("{}/{}", &surveyid, session.step-1));
let template_content = format!("{}
<div class=\"mainframe text-center align-middle\">
<form action=\"/poll?code={}&sessionid={}\" method=\"post\">
{}
<button type=\"submit\" name=\"submit\" value=\"{}\" onclick=\"on_submit()\">Continue</button>
</form>
</div>", "", code, sessionid, content.unwrap().content, session.step-1);
//TODO: display error message
return Ok(content::Html(templates::get_main(&template_content, vec!("style/bootstrap.css".to_string(), "style/global.css".to_string(), "style/poll.css".to_string()), vec!("script/poll.js".to_string()))))
}
}
Loading…
Cancel
Save