From: Andrea Zagli Date: Sat, 11 Feb 2023 10:13:32 +0000 (+0100) Subject: Refactoring started. X-Git-Url: https://saetta.ns0.it/gitweb?a=commitdiff_plain;h=14d78d845c93b80656efcd9b487eb6f14b8ac847;p=rust%2Fzakform Refactoring started. --- diff --git a/examples/form.rs b/examples/form.rs index 2e560cd..1754850 100644 --- a/examples/form.rs +++ b/examples/form.rs @@ -1,5 +1,7 @@ extern crate zakform; +use zakform::TField; + use zakform::filters; use std::collections::HashMap; @@ -43,17 +45,10 @@ struct AppState { settings: Settings, } -#[derive(Serialize,Deserialize)] -struct FormData { - name: String, - notes: String, - sex: String, -} - -async fn index_post( +async fn index( data: web::Data, - form: web::Form, ) -> Result { + let mut s = String::new(); s.push_str("\n"); @@ -63,93 +58,27 @@ async fn index_post( let mut f = zakform::Form::new(); - let strform = serde_json::to_string(&form).unwrap(); - println!("{:#?}",strform); - let map: HashMap = serde_json::from_str(&strform).unwrap(); - - let mut fi = zakform::Field::new(zakform::FType::Text, "name"); - fi.set_label("Name"); - fi.set_value(map.get(fi.name().as_str()).unwrap().as_str()); - fi.add_filter(filters::filter_uppercase); - fi.filter(); - fi.set_template(r#"{% if label %}
- {% endif %} - 0 %}maxlength="{{ maxlen }}"{% endif %} {% if invisible %}style="display: none;"{% endif %}/> - {% if help %}
{{ help }}
{% endif %} - {% if label %}
{% endif %}"#); - f.add_field(fi); - - let mut fi = zakform::Field::new(zakform::FType::TextArea, "notes"); - fi.set_label("Notes"); - fi.set_rows(15); - fi.set_value(map.get(fi.name().as_str()).unwrap().as_str()); - fi.add_filter(filters::filter_trim); - fi.filter(); - f.add_field(fi); - - let mut fi = zakform::Field::new(zakform::FType::Select, "sex"); - fi.set_label("Sex"); - fi.add_option(zakform::FOption{value: String::from("M"), label: String::from("Male")}); - fi.add_option(zakform::FOption{value: String::from("F"), label: String::from("Female")}); - fi.set_value(map.get(fi.name().as_str()).unwrap().as_str()); - f.add_field(fi); - - let fs = f.fields(); - for fi in fs { - s.push_str(fi.render().as_str()); - } - - let js: HashMap = serde_json::from_str(f.as_json_string().as_str()).unwrap(); - println!("{:#?}", js); - - s.push_str(r#""#); - - s.push_str("\n"); - - s.push_str("\n"); - s.push_str(""); - - Ok(HttpResponse::Ok().body(s)) -} - -async fn index( - data: web::Data, -) -> Result { - - let mut s = String::new(); - - s.push_str("\n"); - s.push_str("\n"); + let mut fi = zakform::FieldText::new("text"); + f.add_field(zakform::TFields::TFieldText(fi)); - s.push_str(r#"
"#); + let mut fi = zakform::FieldRadio::new("radio"); + fi.add_option(zakform::FOption{ value: String::from("F"), label: String::from("Female") }); + fi.add_option(zakform::FOption{ value: String::from("M"), label: String::from("Male") }); - let mut f = zakform::Form::new(); + let single = fi.render_single(1); - let mut fi = zakform::Field::new(zakform::FType::Text, "name"); - fi.set_label("Name"); - fi.set_template(r#"{% if label %}
- {% endif %} - 0 %}maxlength="{{ maxlen }}"{% endif %} {% if invisible %}style="display: none;"{% endif %}/> - {% if help %}
{{ help }}
{% endif %} - {% if label %}
{% endif %}"#); - f.add_field(fi); - - let mut fi = zakform::Field::new(zakform::FType::TextArea, "notes"); - fi.set_label("Notes"); - fi.set_rows(15); - f.add_field(fi); - - let mut fi = zakform::Field::new(zakform::FType::Select, "sex"); - fi.set_label("Sex"); - fi.add_option(zakform::FOption{value: String::from("M"), label: String::from("Male")}); - fi.add_option(zakform::FOption{value: String::from("F"), label: String::from("Female")}); - f.add_field(fi); + f.add_field(zakform::TFields::TFieldRadio(fi)); let fs = f.fields(); for fi in fs { - s.push_str(fi.render().as_str()); + match fi { + zakform::TFields::TFieldText(fi) => { s.push_str(fi.render().as_str()); }, + zakform::TFields::TFieldRadio(fi) => { s.push_str(fi.render().as_str()); }, + } } + s.push_str(&single); + s.push_str(r#""#); s.push_str("
\n"); @@ -181,8 +110,7 @@ async fn main() -> std::io::Result<()> { })) .wrap(middleware::Logger::default()) // enable logger .service(web::resource("/") - .route(web::get().to(index)) - .route(web::post().to(index_post))) + .route(web::get().to(index))) .service(web::scope("").wrap(error_handlers())) }) .bind((appstate.settings.http.bind_ip, appstate.settings.http.bind_port))? diff --git a/src/lib.rs b/src/lib.rs index 764c1b1..5fe8d55 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,209 +1,168 @@ -use serde_derive::{Serialize,Deserialize}; +use serde_derive::{Serialize}; -use tera::Tera; +use std::default::Default; pub mod filters; -pub enum FType { - Text, - TextArea, - Check, - Radio, - Select, -} - -pub struct Field { - ftype: FType, +#[derive(Default)] +struct Field { name: String, label: String, - maxlen: i32, disabled: bool, invisible: bool, - rows: i32, help: String, value: String, - options: Vec, tmpl: tera::Tera, filters: Vec, } -#[derive(Serialize)] -pub struct FOption { - pub value: String, - pub label: String, +pub trait TField { + fn new(name: &str) -> Self; + + fn render(&self) -> String; } -impl Field { - pub fn new(ftype: FType, name: &str) -> Field { - let mut f = Field { - ftype: ftype, - name: String::from(name), - label: String::from(name), - maxlen: 0, - disabled: false, - invisible: false, - rows: 0, - help: String::new(), - value: String::new(), - options: Vec::new(), - tmpl: Tera::default(), - filters: vec![], - }; - - match f.ftype { - FType::Text => { - f.tmpl.add_raw_template("field", r#"{% if label %}
- {% endif %} - 0 %}maxlength="{{ maxlen }}"{% endif %} {% if invisible %}style="display: none;"{% endif %}/> - {% if help %}
{{ help }}
{% endif %} - {% if label %}
{% endif %}"#); - }, - FType::TextArea => { - f.rows = 5; +#[derive(Default)] +pub struct FieldText { + field: Field, + maxlen: i32, +} + +impl TField for FieldText { + fn new(name: &str) -> Self { + let mut f: FieldText = Default::default(); - f.tmpl.add_raw_template("field", r#"{% if label %}
+ f.field.name = String::from(name); + f.field.label = String::from(name); + + match f.field.tmpl.add_raw_template("field", r#"{% if label %}
{% endif %} - - {% if help %}
{{ help }}
{% endif %} - {% if label %}
{% endif %}"#); - }, - FType::Check => { - f.tmpl.add_raw_template("field", r#"
- - {% if label %}{% endif %} - {% if help %}
{{ help }}
{% endif %} -
"#); - }, - FType::Radio => { - match f.tmpl.add_raw_template("field", r#"{% if label %}
-
{% endif %} - {% for o in options %} -
- - -
- {% endfor %} + 0 %}maxlength="{{ maxlen }}"{% endif %} {% if invisible %}style="display: none;"{% endif %}/> {% if help %}
{{ help }}
{% endif %} {% if label %}
{% endif %}"#) { Err(e) => { println!("{:?}", e) }, _ => {}, }; - }, - FType::Select => { - f.tmpl.add_raw_template("field", r#"{% if label %}
-
{% endif %} - - {% if help %}
{{ help }}
{% endif %} - {% if label %}
{% endif %}"#); - }, - } f } - pub fn name(&self) -> String { - String::from(self.name.as_str()) - } - - pub fn label(&self) -> String { - String::from(self.label.as_str()) - } - - pub fn set_label(&mut self, label: &str) { - self.label = String::from(label); - } + fn render(&self) -> String { + let mut s = String::new(); - pub fn maxlen(&self) -> i32 { - self.maxlen - } + let mut context = tera::Context::new(); + context.insert("name", &self.field.name); + context.insert("label", &self.field.label); + context.insert("maxlen", &self.maxlen); + context.insert("disabled", &self.field.disabled); + context.insert("invisible", &self.field.invisible); + context.insert("help", &self.field.help); + context.insert("value", &self.field.value); + s.push_str(self.field.tmpl.render("field", &context).unwrap().as_str()); - pub fn set_maxlen(&mut self, maxlen: i32) { - self.maxlen = maxlen; + s } +} - pub fn disabled(&self) -> bool { - self.disabled - } +#[derive(Serialize)] +pub struct FOption { + pub value: String, + pub label: String, +} - pub fn set_disabled(&mut self, disabled: bool) { - self.disabled = disabled; - } +#[derive(Default)] +pub struct FieldRadio { + field: Field, + options: Vec, +} - pub fn invisible(&self) -> bool { - self.invisible - } +impl TField for FieldRadio { + fn new(name: &str) -> Self { + let mut f: FieldRadio = Default::default(); - pub fn set_invisible(&mut self, invisible: bool) { - self.invisible = invisible; - } + f.field.name = String::from(name); + f.field.label = String::from(name); - pub fn rows(&self) -> i32 { - self.rows - } + match f.field.tmpl.add_raw_template("field", r#"{% if label %}
+
{% endif %} + {% for o in options %} +
+ + +
+ {% endfor %} + {% if help %}
{{ help }}
{% endif %} + {% if label %}
{% endif %}"#) { +Err(e) => { println!("{:?}", e) }, +_ => {}, +}; - pub fn set_rows(&mut self, rows: i32) { - self.rows = rows; - } + match f.field.tmpl.add_raw_template("field_single", r#"
+ + +
"#) { +Err(e) => { println!("{:?}", e) }, +_ => {}, +}; - pub fn help(&self) -> String { - String::from(self.help.as_str()) + f } - pub fn set_help(&mut self, help: &str) { - self.help = String::from(help); - } + fn render(&self) -> String { + let mut s = String::new(); - pub fn value(&self) -> String { - String::from(self.value.as_str()) - } + let mut context = tera::Context::new(); + context.insert("name", &self.field.name); + context.insert("label", &self.field.label); + context.insert("disabled", &self.field.disabled); + context.insert("invisible", &self.field.invisible); + context.insert("help", &self.field.help); + context.insert("value", &self.field.value); + context.insert("options", &self.options); + s.push_str(self.field.tmpl.render("field", &context).unwrap().as_str()); - pub fn set_value(&mut self, value: &str) { - self.value = String::from(value); + s } +} +impl FieldRadio { pub fn add_option(&mut self, option: FOption) { self.options.push(option); } - pub fn set_template(&mut self, template: &str) { - self.tmpl.add_raw_template("field", template); - } + pub fn render_single(&self, idx: usize) -> String { + let mut s = String::new(); - pub fn add_filter(&mut self, filter: filters::Filter) { - self.filters.push(filter); - } + let mut context = tera::Context::new(); + + context.insert("name", &self.field.name); + context.insert("help", &self.field.help); + + let opt = &self.options[idx]; + context.insert("label", &opt.label); + context.insert("value", &opt.value); - pub fn filter(&mut self) { - for f in &self.filters { - self.value = (f)(&self.value); + if opt.value == self.field.value { + context.insert("checked", "checked"); + } else { + context.insert("checked", ""); } - } - pub fn render(&self) -> String { - let mut s = String::new(); + context.insert("idx", &idx); - let mut context = tera::Context::new(); - context.insert("name", &self.name); - context.insert("label", &self.label); - context.insert("maxlen", &self.maxlen); - context.insert("disabled", &self.disabled); - context.insert("invisible", &self.invisible); - context.insert("rows", &self.rows); - context.insert("help", &self.help); - context.insert("value", &self.value); - context.insert("options", &self.options); - s.push_str(self.tmpl.render("field", &context).unwrap().as_str()); + s.push_str(self.field.tmpl.render("field_single", &context).unwrap().as_str()); s } } +pub enum TFields { + TFieldText(FieldText), + TFieldRadio(FieldRadio), +} + pub struct Form { - fields: Vec + fields: Vec, } impl Form { @@ -213,34 +172,11 @@ impl Form { } } - pub fn add_field(&mut self, field: Field) { + pub fn add_field(&mut self, field: TFields) { self.fields.push(field); } - pub fn fields(&self) -> &Vec { + pub fn fields(&self) -> &Vec { &self.fields } - - pub fn get_field(&mut self, field_name: &str) -> Result<&mut Field, ()> { - for f in &mut self.fields { - if f.name.as_str() == field_name { - return Ok(f); - } - } - - Err(()) - } - - pub fn as_json_string(&mut self) -> String { - let mut s = String::from("{"); - - for f in &mut self.fields { - s.push_str(format!(r#""{}": "{}","#, f.name, f.value).as_str()); - } - - s.truncate(s.len() - 1); - s.push_str("}"); - - s - } }