]> saetta.ns0.it Git - rust/zakform/commitdiff
First commit. Started form and field structs.
authorAndrea Zagli <azagli@libero.it>
Fri, 6 Jan 2023 08:00:55 +0000 (09:00 +0100)
committerAndrea Zagli <azagli@libero.it>
Fri, 6 Jan 2023 08:00:55 +0000 (09:00 +0100)
.gitignore [new file with mode: 0644]
Cargo.toml [new file with mode: 0644]
examples/app.toml.dist [new file with mode: 0644]
examples/form.rs [new file with mode: 0644]
src/lib.rs [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..4e89a98
--- /dev/null
@@ -0,0 +1,4 @@
+/target
+/Cargo.lock
+*.~*~
+examples/*.toml
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644 (file)
index 0000000..10aa291
--- /dev/null
@@ -0,0 +1,16 @@
+[package]
+name = "zakform"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+tera = "1.8.0"
+
+
+[dev-dependencies]
+serde = "1"
+serde_derive = "1"
+config = "0.13"
+actix-web = "4"
diff --git a/examples/app.toml.dist b/examples/app.toml.dist
new file mode 100644 (file)
index 0000000..44041c4
--- /dev/null
@@ -0,0 +1,3 @@
+[http]
+bind_ip="10.0.0.101"
+bind_port=9090
diff --git a/examples/form.rs b/examples/form.rs
new file mode 100644 (file)
index 0000000..a2bb4cf
--- /dev/null
@@ -0,0 +1,120 @@
+extern crate zakform;
+
+use config::{Config, ConfigError};
+use serde_derive::Deserialize;
+
+use actix_web::{
+    body::BoxBody,
+    dev::ServiceResponse,
+    error,
+    http::{header::ContentType, StatusCode},
+    middleware::{self, ErrorHandlerResponse, ErrorHandlers},
+    web, App, Error, HttpResponse, HttpServer, Responder, Result,
+};
+
+#[derive(Debug, Deserialize)]
+#[allow(unused)]
+struct Http {
+       bind_ip: String,
+       bind_port: u16,
+}
+
+#[derive(Debug, Deserialize)]
+#[allow(unused)]
+struct Settings {
+       http: Http,
+}
+
+impl Settings {
+       fn new() -> Result<Self, ConfigError> {
+               let s = Config::builder()
+                       .add_source(config::File::with_name("examples/app"))
+                       .build()?;
+
+               s.try_deserialize()
+       }
+}
+
+struct AppState {
+       settings: Settings,
+}
+
+async fn index(
+    data: web::Data<AppState>,
+) -> Result<impl Responder, Error> {
+
+       let mut s = String::new();
+
+       let mut f = zakform::Form::new();
+
+       let mut fi = zakform::Field::new(zakform::FType::Text, "name");
+       fi.set_label("Name");
+       s.push_str(fi.render().as_str());
+       f.add_field(fi);
+
+       let mut fi = zakform::Field::new(zakform::FType::TextArea, "notes");
+       fi.set_label("Notes");
+       s.push_str(fi.render().as_str());
+       f.add_field(fi);
+
+       Ok(HttpResponse::Ok().body(s))
+}
+
+#[actix_web::main]
+async fn main() -> std::io::Result<()> {
+
+       let appstate: AppState = AppState {
+               settings: Settings::new().unwrap(),
+       };
+
+       // Print out our settings
+       println!(
+               "{:?}",
+               appstate.settings
+       );
+
+    println!("Listening on: {}:{}, open browser and visit have a try!", appstate.settings.http.bind_ip, appstate.settings.http.bind_port);
+    HttpServer::new(move || {
+        App::new()
+            .app_data(web::Data::new(AppState {
+                               settings: Settings::new().unwrap(),
+                       }))
+            .wrap(middleware::Logger::default()) // enable logger
+            .service(web::resource("/").route(web::get().to(index)))
+            .service(web::scope("").wrap(error_handlers()))
+    })
+    .bind((appstate.settings.http.bind_ip, appstate.settings.http.bind_port))?
+    .run()
+    .await
+}
+
+// Custom error handlers, to return HTML responses when an error occurs.
+fn error_handlers() -> ErrorHandlers<BoxBody> {
+    ErrorHandlers::new().handler(StatusCode::NOT_FOUND, not_found)
+}
+
+// Error handler for a 404 Page not found error.
+fn not_found<B>(res: ServiceResponse<B>) -> Result<ErrorHandlerResponse<BoxBody>> {
+    let response = get_error_response(&res, "Page not found");
+    Ok(ErrorHandlerResponse::Response(ServiceResponse::new(
+        res.into_parts().0,
+        response.map_into_left_body(),
+    )))
+}
+
+// Generic error handler.
+fn get_error_response<B>(res: &ServiceResponse<B>, error: &str) -> HttpResponse {
+    let request = res.request();
+
+    // Provide a fallback to a simple plain text response in case an error occurs during the
+    // rendering of the error page.
+    let fallback = |e: &str| {
+        HttpResponse::build(res.status())
+            .content_type(ContentType::plaintext())
+            .body(e.to_string())
+    };
+
+    HttpResponse::build(res.status())
+            .content_type(ContentType::html())
+            .body("")
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644 (file)
index 0000000..0079073
--- /dev/null
@@ -0,0 +1,59 @@
+pub enum FType {
+       Text,
+       TextArea
+}
+
+pub struct Field {
+       ftype: FType,
+       name: String,
+       label: String,
+}
+
+impl Field {
+       pub fn new(ftype: FType, name: &str) -> Field {
+               Field {
+                       ftype: ftype,
+                       name: String::from(name),
+                       label: String::from(name),
+               }
+       }
+
+       pub fn label(&self) -> String {
+               String::from(self.label.as_str())
+       }
+
+       pub fn set_label(&mut self, label: &str) {
+               self.label = String::from(label);
+       }
+
+       pub fn render(&self) -> String {
+               let mut s = String::new();
+
+               match &self.ftype {
+                       FType::Text => {
+                               s.push_str(format!("Text => Name: {}, Label: {}\n", self.name, self.label).as_str());
+                       },
+                       FType::TextArea => {
+                               s.push_str(format!("TextArea => Name: {}, Label: {}\n", self.name, self.label).as_str());
+                       },
+               }
+
+               s
+       }
+}
+
+pub struct Form {
+       fields: Vec<Field>
+}
+
+impl Form {
+       pub fn new() -> Form {
+               Form {
+                       fields: vec![],
+               }
+       }
+
+       pub fn add_field(&mut self, field: Field) {
+               self.fields.push(field);
+       }
+}