all reference forms and health apis are done

This commit is contained in:
Chris Cochrun 2024-01-08 15:20:33 -06:00
parent 65f186fadc
commit 3f8b9cb5d8
10 changed files with 630 additions and 29 deletions

View file

@ -6,15 +6,22 @@
const form = document.getElementById('form'); const form = document.getElementById('form');
const data = new FormData(form); const data = new FormData(form);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() { // For use in dev
if (this.readyState == 4 && this.status == 200) { // Can now start using this in production IF,
// Logic directing where to send the user after form submission based on results. // I get the server running on the server
/* let base = "https://api.tfcconnection.org/health-form"; */
let base = "http://localhost:4242/church-form";
fetch(base, {
method: "POST",
body: data
}).then((res) => {
console.log(res);
if (res.ok) {
window.location.href = '/thankyou/'; window.location.href = '/thankyou/';
}; }
}; });
xhr.open("POST", "https://n8n.tfcconnection.org/webhook/mt-church-form");
xhr.send(data);
console.log(data); console.log(data);
console.log("Hallo!"); console.log("Hallo!");
return false; return false;

View file

@ -6,15 +6,21 @@
const form = document.getElementById('form'); const form = document.getElementById('form');
const data = new FormData(form); const data = new FormData(form);
var xhr = new XMLHttpRequest(); // For use in dev
xhr.onreadystatechange = function() { // Can now start using this in production IF,
if (this.readyState == 4 && this.status == 200) { // I get the server running on the server
// Logic directing where to send the user after form submission based on results. /* let base = "https://api.tfcconnection.org/health-form"; */
let base = "http://localhost:4242/parent-form";
fetch(base, {
method: "POST",
body: data
}).then((res) => {
console.log(res);
if (res.ok) {
window.location.href = '/thankyou/'; window.location.href = '/thankyou/';
}; }
}; });
xhr.open("POST", "https://n8n.tfcconnection.org/webhook/mt-parent-form");
xhr.send(data);
console.log(data); console.log(data);
console.log("Hallo!"); console.log("Hallo!");
return false; return false;

View file

@ -6,15 +6,21 @@
const form = document.getElementById('form'); const form = document.getElementById('form');
const data = new FormData(form); const data = new FormData(form);
var xhr = new XMLHttpRequest(); // For use in dev
xhr.onreadystatechange = function() { // Can now start using this in production IF,
if (this.readyState == 4 && this.status == 200) { // I get the server running on the server
// Logic directing where to send the user after form submission based on results. /* let base = "https://api.tfcconnection.org/health-form"; */
let base = "http://localhost:4242/teacher-form";
fetch(base, {
method: "POST",
body: data
}).then((res) => {
console.log(res);
if (res.ok) {
window.location.href = '/thankyou/'; window.location.href = '/thankyou/';
}; }
}; });
xhr.open("POST", "https://n8n.tfcconnection.org/webhook/mt-teacher-form");
xhr.send(data);
console.log(data); console.log(data);
console.log("Hallo!"); console.log("Hallo!");
return false; return false;

191
src/api/church_form.rs Normal file
View file

@ -0,0 +1,191 @@
use actix_multipart::form::{text::Text, MultipartForm};
use actix_web::{post, HttpResponse};
use lettre::{
message::MultiPart,
transport::smtp::authentication::{Credentials, Mechanism},
Message, SmtpTransport, Transport,
};
#[derive(Debug, MultipartForm, Default)]
struct ChurchForm {
#[multipart(rename = "firstname")]
first_name: Option<Text<String>>,
#[multipart(rename = "lastname")]
last_name: Option<Text<String>>,
#[multipart(rename = "studentfirstname")]
student_first_name: Option<Text<String>>,
#[multipart(rename = "studentlastname")]
student_last_name: Option<Text<String>>,
relationship: Option<Text<String>>,
#[multipart(rename = "walk-with-jesus")]
walk: Option<Text<String>>,
commitment: Option<Text<String>>,
teachable: Option<Text<String>>,
#[multipart(rename = "pos-characteristics")]
positive: Option<Text<String>>,
#[multipart(rename = "neg-characteristics")]
negative: Option<Text<String>>,
#[multipart(rename = "extra-info")]
notes: Option<Text<String>>,
}
#[post("/church-form")]
pub async fn church_form(MultipartForm(form): MultipartForm<ChurchForm>) -> HttpResponse {
let first = form.first_name.as_ref().unwrap().0.clone();
let last = form.last_name.as_ref().unwrap().0.clone();
let student = format!(
"{} {}",
form.student_first_name.as_ref().unwrap().0.clone(),
form.student_last_name.as_ref().unwrap().0.clone()
);
let email_subject = format!(
"{} {} filled out a Church Reference form for {}!",
first, last, student
);
let relationship = form
.relationship
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let walk = form
.walk
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let positive = form
.positive
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let negative = form
.negative
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let commitment = form
.commitment
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let teachable = form
.teachable
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let notes = form
.notes
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
log::info!("{first} {last} filled out a Church Reference form!");
let email = markup::new! {
@markup::doctype()
html {
head {
title { @format!("{} {} filled out a Church Reference form for {}!", first, last, student) }
style {
"table { border-collapse: collapse; width: 100% }"
"td, th { padding: 8px }"
"td { text-align: left; width: 70%; word-wrap: break-word }"
"th { text-align: right; border-right: 1px solid #ddd }"
"tr { border-bottom: 1px solid #ddd }"
"h1 { text-align: center }"
}
}
body {
h1 { @format!("Church Reference form for {}!", student) }
hr;
table {
tr {
th { "Name" }
td { @format!("{} {}", first, last) }
}
tr {
th { "Student" }
td { @student }
}
tr {
th { "Relationship to teen" }
td { @relationship }
}
tr {
th { "Walk with Jesus" }
td { @walk }
}
tr {
th { "Commitment to church" }
td { @commitment }
}
tr {
th { "Teachable spirit" }
td { @teachable }
}
tr {
th { "Positive Attributes" }
td { @positive }
}
tr {
th { "Negaitive Attributes" }
td { @negative }
}
tr {
th { "Other Notes" }
td { @notes }
}
}
}
}
};
let multi = MultiPart::alternative_plain_html(String::from("Testing"), email.to_string());
if let Ok(m) = Message::builder()
.from(
"TFC ADMIN <no-reply@mail.tfcconnection.org>"
.parse()
.unwrap(),
)
.to("Chris Cochrun <chris@tfcconnection.org>".parse().unwrap())
.to("Ethan Rose <ethan@tfcconnection.org>".parse().unwrap())
.subject(email_subject)
.multipart(multi)
{
let sender = SmtpTransport::relay("mail.tfcconnection.org")
.ok()
.unwrap()
.credentials(Credentials::new(
"no-reply@mail.tfcconnection.org".to_owned(),
"r9f36mNZFtiW4f".to_owned(),
))
.authentication(vec![Mechanism::Plain])
.build();
match sender.send(&m) {
Ok(res) => log::info!("{:?}", res),
Err(e) => log::info!("{e}"),
}
} else {
log::info!("Email incorrect");
}
HttpResponse::Ok().body("hi")
}

View file

@ -410,11 +410,13 @@ pub async fn health_form(MultipartForm(form): MultipartForm<HealthForm>) -> Http
}; };
let mut path: Option<String> = Some(String::from("")); let mut path: Option<String> = Some(String::from(""));
let mut file_exists = false; let mut file_exists = false;
let mut filename = String::from("");
log::info!("{:?}", form); log::info!("{:?}", form);
log::info!("{:?}", file_exists); log::info!("{:?}", file_exists);
if let Some(f) = form.file { if let Some(f) = form.file {
if let Some(file) = f.file_name { if let Some(file) = f.file_name {
if let Some(ext) = file.rsplit(".").next() { if let Some(ext) = file.rsplit(".").next() {
filename = format!("{}.{}", filename_noext, ext);
path = Some(format!("./tmp/{}.{}", filename_noext, ext)); path = Some(format!("./tmp/{}.{}", filename_noext, ext));
} else { } else {
path = Some(format!("./tmp/{}", file)); path = Some(format!("./tmp/{}", file));
@ -436,8 +438,7 @@ pub async fn health_form(MultipartForm(form): MultipartForm<HealthForm>) -> Http
let multi = if file_exists { let multi = if file_exists {
let filebody = fs::read(path.clone().unwrap_or_default()); let filebody = fs::read(path.clone().unwrap_or_default());
let content_type = ContentType::parse("image/jpg").unwrap(); let content_type = ContentType::parse("image/jpg").unwrap();
let attachment = let attachment = Attachment::new(filename).body(filebody.unwrap(), content_type);
Attachment::new(path.unwrap_or_default()).body(filebody.unwrap(), content_type);
log::info!("{:?}", attachment); log::info!("{:?}", attachment);
MultiPart::alternative_plain_html(String::from("Testing"), email.to_string()) MultiPart::alternative_plain_html(String::from("Testing"), email.to_string())
.singlepart(attachment) .singlepart(attachment)
@ -452,7 +453,7 @@ pub async fn health_form(MultipartForm(form): MultipartForm<HealthForm>) -> Http
.unwrap(), .unwrap(),
) )
.to("Chris Cochrun <chris@tfcconnection.org>".parse().unwrap()) .to("Chris Cochrun <chris@tfcconnection.org>".parse().unwrap())
// .to("Ethan Rose <ethan@tfcconnection.org>".parse().unwrap()) .to("Ethan Rose <ethan@tfcconnection.org>".parse().unwrap())
.subject(email_subject) .subject(email_subject)
.multipart(multi) .multipart(multi)
{ {

View file

@ -1,2 +1,5 @@
pub mod church_form;
pub mod health_form; pub mod health_form;
pub mod mt_form; pub mod mt_form;
pub mod parent_form;
pub mod teacher_form;

View file

@ -459,11 +459,13 @@ pub async fn mt_form(MultipartForm(form): MultipartForm<MtForm>) -> HttpResponse
}; };
let mut path: Option<String> = Some(String::from("")); let mut path: Option<String> = Some(String::from(""));
let mut file_exists = false; let mut file_exists = false;
let mut filename = String::from("");
log::info!("{:?}", form); log::info!("{:?}", form);
log::info!("{:?}", file_exists); log::info!("{:?}", file_exists);
if let Some(f) = form.file { if let Some(f) = form.file {
if let Some(file) = f.file_name { if let Some(file) = f.file_name {
if let Some(ext) = file.rsplit(".").next() { if let Some(ext) = file.rsplit(".").next() {
filename = format!("{}.{}", filename_noext, ext);
path = Some(format!("./tmp/{}.{}", filename_noext, ext)); path = Some(format!("./tmp/{}.{}", filename_noext, ext));
} else { } else {
path = Some(format!("./tmp/{}", file)); path = Some(format!("./tmp/{}", file));
@ -485,8 +487,7 @@ pub async fn mt_form(MultipartForm(form): MultipartForm<MtForm>) -> HttpResponse
let multi = if file_exists { let multi = if file_exists {
let filebody = fs::read(path.clone().unwrap_or_default()); let filebody = fs::read(path.clone().unwrap_or_default());
let content_type = ContentType::parse("image/jpg").unwrap(); let content_type = ContentType::parse("image/jpg").unwrap();
let attachment = let attachment = Attachment::new(filename).body(filebody.unwrap(), content_type);
Attachment::new(path.unwrap_or_default()).body(filebody.unwrap(), content_type);
log::info!("{:?}", attachment); log::info!("{:?}", attachment);
MultiPart::alternative_plain_html(String::from("Testing"), email.to_string()) MultiPart::alternative_plain_html(String::from("Testing"), email.to_string())
.singlepart(attachment) .singlepart(attachment)

204
src/api/parent_form.rs Normal file
View file

@ -0,0 +1,204 @@
use actix_multipart::form::{text::Text, MultipartForm};
use actix_web::{post, HttpResponse};
use lettre::{
message::MultiPart,
transport::smtp::authentication::{Credentials, Mechanism},
Message, SmtpTransport, Transport,
};
#[derive(Debug, MultipartForm, Default)]
struct ParentForm {
#[multipart(rename = "firstname")]
first_name: Option<Text<String>>,
#[multipart(rename = "lastname")]
last_name: Option<Text<String>>,
#[multipart(rename = "studentfirstname")]
student_first_name: Option<Text<String>>,
#[multipart(rename = "studentlastname")]
student_last_name: Option<Text<String>>,
email: Option<Text<String>>,
authority: Option<Text<String>>,
positive: Option<Text<String>>,
negative: Option<Text<String>>,
#[multipart(rename = "family-relation")]
family_relation: Option<Text<String>>,
#[multipart(rename = "previous-trip-info")]
previous_trip_info: Option<Text<String>>,
#[multipart(rename = "trip-feelings")]
trip_feelings: Option<Text<String>>,
#[multipart(rename = "extra-info")]
notes: Option<Text<String>>,
}
#[post("/parent-form")]
pub async fn parent_form(MultipartForm(form): MultipartForm<ParentForm>) -> HttpResponse {
let first = form.first_name.as_ref().unwrap().0.clone();
let last = form.last_name.as_ref().unwrap().0.clone();
let student = format!(
"{} {}",
form.student_first_name.as_ref().unwrap().0.clone(),
form.student_last_name.as_ref().unwrap().0.clone()
);
let email_subject = format!(
"{} {} filled out a parent form for {}!",
first, last, student
);
let email = form
.email
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let authority = form
.authority
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let positive = form
.positive
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let negative = form
.negative
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let family = form
.family_relation
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let previous_trip_info = form
.previous_trip_info
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let feelings = form
.trip_feelings
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let notes = form
.notes
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
log::info!("{first} {last} filled out a parent form!");
let email = markup::new! {
@markup::doctype()
html {
head {
title { @format!("{} {} filled out a Parent Reference form for {}!", first, last, student) }
style {
"table { border-collapse: collapse; width: 100% }"
"td, th { padding: 8px }"
"td { text-align: left; width: 70%; word-wrap: break-word }"
"th { text-align: right; border-right: 1px solid #ddd }"
"tr { border-bottom: 1px solid #ddd }"
"h1 { text-align: center }"
}
}
body {
h1 { @format!("Parent Reference form for {}!", student) }
hr;
table {
tr {
th { "Name" }
td { @format!("{} {}", first, last) }
}
tr {
th { "Student" }
td { @student }
}
tr {
th { "Email" }
td { @email }
}
tr {
th { "Response to authority" }
td { @authority }
}
tr {
th { "Positive Attributes" }
td { @positive }
}
tr {
th { "Negaitive Attributes" }
td { @negative }
}
tr {
th { "Relations to Family" }
td { @family }
}
tr {
th { "Previous trip info" }
td { @previous_trip_info }
}
tr {
th { "Feelings about the trip" }
td { @feelings }
}
tr {
th { "Other Notes" }
td { @notes }
}
}
}
}
};
let multi = MultiPart::alternative_plain_html(String::from("Testing"), email.to_string());
if let Ok(m) = Message::builder()
.from(
"TFC ADMIN <no-reply@mail.tfcconnection.org>"
.parse()
.unwrap(),
)
.to("Chris Cochrun <chris@tfcconnection.org>".parse().unwrap())
.to("Ethan Rose <ethan@tfcconnection.org>".parse().unwrap())
.subject(email_subject)
.multipart(multi)
{
let sender = SmtpTransport::relay("mail.tfcconnection.org")
.ok()
.unwrap()
.credentials(Credentials::new(
"no-reply@mail.tfcconnection.org".to_owned(),
"r9f36mNZFtiW4f".to_owned(),
))
.authentication(vec![Mechanism::Plain])
.build();
match sender.send(&m) {
Ok(res) => log::info!("{:?}", res),
Err(e) => log::info!("{e}"),
}
} else {
log::info!("Email incorrect");
}
HttpResponse::Ok().body("hi")
}

176
src/api/teacher_form.rs Normal file
View file

@ -0,0 +1,176 @@
use actix_multipart::form::{text::Text, MultipartForm};
use actix_web::{post, HttpResponse};
use lettre::{
message::MultiPart,
transport::smtp::authentication::{Credentials, Mechanism},
Message, SmtpTransport, Transport,
};
#[derive(Debug, MultipartForm, Default)]
struct TeacherForm {
#[multipart(rename = "firstname")]
first_name: Option<Text<String>>,
#[multipart(rename = "lastname")]
last_name: Option<Text<String>>,
#[multipart(rename = "studentfirstname")]
student_first_name: Option<Text<String>>,
#[multipart(rename = "studentlastname")]
student_last_name: Option<Text<String>>,
relationship: Option<Text<String>>,
attitudes: Option<Text<String>>,
positive: Option<Text<String>>,
negative: Option<Text<String>>,
#[multipart(rename = "team-challenges")]
team: Option<Text<String>>,
#[multipart(rename = "extra-info")]
notes: Option<Text<String>>,
}
#[post("/teacher-form")]
pub async fn teacher_form(MultipartForm(form): MultipartForm<TeacherForm>) -> HttpResponse {
let first = form.first_name.as_ref().unwrap().0.clone();
let last = form.last_name.as_ref().unwrap().0.clone();
let student = format!(
"{} {}",
form.student_first_name.as_ref().unwrap().0.clone(),
form.student_last_name.as_ref().unwrap().0.clone()
);
let email_subject = format!(
"{} {} filled out a teacher form for {}!",
first, last, student
);
let relationship = form
.relationship
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let attitudes = form
.attitudes
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let positive = form
.positive
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let negative = form
.negative
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let team = form
.team
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
let notes = form
.notes
.as_ref()
.unwrap_or(&Text {
0: String::from(""),
})
.0
.clone();
log::info!("{first} {last} filled out a teacher form!");
let email = markup::new! {
@markup::doctype()
html {
head {
title { @format!("{} {} filled out a teacher form for {}!", first, last, student) }
style {
"table { border-collapse: collapse; width: 100% }"
"td, th { padding: 8px }"
"td { text-align: left; width: 70%; word-wrap: break-word }"
"th { text-align: right; border-right: 1px solid #ddd }"
"tr { border-bottom: 1px solid #ddd }"
"h1 { text-align: center }"
}
}
body {
h1 { @format!("Teacher Reference form for {}!", student) }
hr;
table {
tr {
th { "Name" }
td { @format!("{} {}", first, last) }
}
tr {
th { "Student" }
td { @student }
}
tr {
th { "Relationship to teen" }
td { @relationship }
}
tr {
th { "Attitude in classroom" }
td { @attitudes }
}
tr {
th { "Positive Attributes" }
td { @positive }
}
tr {
th { "Negaitive Attributes" }
td { @negative }
}
tr {
th { "Teamwork" }
td { @team }
}
tr {
th { "Other Notes" }
td { @notes }
}
}
}
}
};
let multi = MultiPart::alternative_plain_html(String::from("Testing"), email.to_string());
if let Ok(m) = Message::builder()
.from(
"TFC ADMIN <no-reply@mail.tfcconnection.org>"
.parse()
.unwrap(),
)
.to("Chris Cochrun <chris@tfcconnection.org>".parse().unwrap())
.to("Ethan Rose <ethan@tfcconnection.org>".parse().unwrap())
.subject(email_subject)
.multipart(multi)
{
let sender = SmtpTransport::relay("mail.tfcconnection.org")
.ok()
.unwrap()
.credentials(Credentials::new(
"no-reply@mail.tfcconnection.org".to_owned(),
"r9f36mNZFtiW4f".to_owned(),
))
.authentication(vec![Mechanism::Plain])
.build();
match sender.send(&m) {
Ok(res) => log::info!("{:?}", res),
Err(e) => log::info!("{e}"),
}
} else {
log::info!("Email incorrect");
}
HttpResponse::Ok().body("hi")
}

View file

@ -2,8 +2,11 @@ mod api;
use actix_multipart::form::tempfile::TempFileConfig; use actix_multipart::form::tempfile::TempFileConfig;
use actix_web::{middleware, App, HttpServer}; use actix_web::{middleware, App, HttpServer};
use api::church_form::church_form;
use api::health_form::health_form; use api::health_form::health_form;
use api::mt_form::mt_form; use api::mt_form::mt_form;
use api::parent_form::parent_form;
use api::teacher_form::teacher_form;
#[actix_web::main] #[actix_web::main]
async fn main() -> std::io::Result<()> { async fn main() -> std::io::Result<()> {
@ -20,6 +23,9 @@ async fn main() -> std::io::Result<()> {
.app_data(TempFileConfig::default().directory("./tmp")) .app_data(TempFileConfig::default().directory("./tmp"))
.service(mt_form) .service(mt_form)
.service(health_form) .service(health_form)
.service(parent_form)
.service(teacher_form)
.service(church_form)
}) })
.bind(("127.0.0.1", 4242))? .bind(("127.0.0.1", 4242))?
.workers(2) .workers(2)