initial-frontend-work #2
							
								
								
									
										99
									
								
								backend/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										99
									
								
								backend/Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -213,6 +213,12 @@ dependencies = [
 | 
				
			|||||||
 "winapi 0.3.9",
 | 
					 "winapi 0.3.9",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "const-sha1"
 | 
				
			||||||
 | 
					version = "0.2.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "fb58b6451e8c2a812ad979ed1d83378caa5e927eef2622017a45f251457c2c9d"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "const_fn"
 | 
					name = "const_fn"
 | 
				
			||||||
version = "0.4.9"
 | 
					version = "0.4.9"
 | 
				
			||||||
@ -551,9 +557,11 @@ dependencies = [
 | 
				
			|||||||
 "diesel_migrations",
 | 
					 "diesel_migrations",
 | 
				
			||||||
 "jsonwebtoken",
 | 
					 "jsonwebtoken",
 | 
				
			||||||
 "libsqlite3-sys",
 | 
					 "libsqlite3-sys",
 | 
				
			||||||
 | 
					 "local-ip-address",
 | 
				
			||||||
 "password-hash",
 | 
					 "password-hash",
 | 
				
			||||||
 "rand_core",
 | 
					 "rand_core",
 | 
				
			||||||
 "rocket",
 | 
					 "rocket",
 | 
				
			||||||
 | 
					 "rocket_cors",
 | 
				
			||||||
 "rocket_dyn_templates",
 | 
					 "rocket_dyn_templates",
 | 
				
			||||||
 "rocket_sync_db_pools",
 | 
					 "rocket_sync_db_pools",
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
@ -861,6 +869,19 @@ dependencies = [
 | 
				
			|||||||
 "vcpkg",
 | 
					 "vcpkg",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "local-ip-address"
 | 
				
			||||||
 | 
					version = "0.4.4"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "8b143c6ef86e36328caa40a7578e95d1544aca8a1740235fd2b416a69441a5c7"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "libc",
 | 
				
			||||||
 | 
					 "memalloc",
 | 
				
			||||||
 | 
					 "neli",
 | 
				
			||||||
 | 
					 "thiserror",
 | 
				
			||||||
 | 
					 "windows",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "lock_api"
 | 
					name = "lock_api"
 | 
				
			||||||
version = "0.4.6"
 | 
					version = "0.4.6"
 | 
				
			||||||
@ -915,6 +936,12 @@ version = "0.1.9"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
 | 
					checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "memalloc"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "df39d232f5c40b0891c10216992c2f250c054105cb1e56f0fc9032db6203ecc1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "memchr"
 | 
					name = "memchr"
 | 
				
			||||||
version = "2.4.1"
 | 
					version = "2.4.1"
 | 
				
			||||||
@ -1034,6 +1061,16 @@ dependencies = [
 | 
				
			|||||||
 "version_check",
 | 
					 "version_check",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "neli"
 | 
				
			||||||
 | 
					version = "0.5.3"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "9053554eb5dcb7e10d9cdab1206965bde870eed5d0d341532ca035e3ba221508"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "byteorder",
 | 
				
			||||||
 | 
					 "libc",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "net2"
 | 
					name = "net2"
 | 
				
			||||||
version = "0.2.37"
 | 
					version = "0.2.37"
 | 
				
			||||||
@ -1534,6 +1571,22 @@ dependencies = [
 | 
				
			|||||||
 "unicode-xid",
 | 
					 "unicode-xid",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "rocket_cors"
 | 
				
			||||||
 | 
					version = "0.6.0-alpha1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "3f5aa2c9cdb5dabbbf38bd4fb0038844cc47598399fed70fc938185679154793"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "log",
 | 
				
			||||||
 | 
					 "regex",
 | 
				
			||||||
 | 
					 "rocket",
 | 
				
			||||||
 | 
					 "serde",
 | 
				
			||||||
 | 
					 "serde_derive",
 | 
				
			||||||
 | 
					 "unicase",
 | 
				
			||||||
 | 
					 "unicase_serde",
 | 
				
			||||||
 | 
					 "url",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "rocket_dyn_templates"
 | 
					name = "rocket_dyn_templates"
 | 
				
			||||||
version = "0.1.0-rc.1"
 | 
					version = "0.1.0-rc.1"
 | 
				
			||||||
@ -2177,6 +2230,25 @@ dependencies = [
 | 
				
			|||||||
 "version_check",
 | 
					 "version_check",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "unicase"
 | 
				
			||||||
 | 
					version = "2.6.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "version_check",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "unicase_serde"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "6ef53697679d874d69f3160af80bc28de12730a985d57bdf2b47456ccb8b11f1"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "serde",
 | 
				
			||||||
 | 
					 "unicase",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "unicode-bidi"
 | 
					name = "unicode-bidi"
 | 
				
			||||||
version = "0.3.7"
 | 
					version = "0.3.7"
 | 
				
			||||||
@ -2417,6 +2489,33 @@ version = "0.4.0"
 | 
				
			|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 | 
					checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "windows"
 | 
				
			||||||
 | 
					version = "0.18.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "68088239696c06152844eadc03d262f088932cce50c67e4ace86e19d95e976fe"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "const-sha1",
 | 
				
			||||||
 | 
					 "windows_gen",
 | 
				
			||||||
 | 
					 "windows_macros",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "windows_gen"
 | 
				
			||||||
 | 
					version = "0.18.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "cf583322dc423ee021035b358e535015f7fd163058a31e2d37b99a939141121d"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "windows_macros"
 | 
				
			||||||
 | 
					version = "0.18.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "58acfb8832e9f707f8997bd161e537a1c1f603e60a5bd9c3cf53484fdcc998f3"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "syn",
 | 
				
			||||||
 | 
					 "windows_gen",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "ws2_32-sys"
 | 
					name = "ws2_32-sys"
 | 
				
			||||||
version = "0.2.1"
 | 
					version = "0.2.1"
 | 
				
			||||||
 | 
				
			|||||||
@ -21,4 +21,5 @@ rand_core = { version = "0.6", features = ["std"] }
 | 
				
			|||||||
diesel-derive-enum = { version = "1.1", features = ["sqlite"] }
 | 
					diesel-derive-enum = { version = "1.1", features = ["sqlite"] }
 | 
				
			||||||
jsonwebtoken = "8.1"
 | 
					jsonwebtoken = "8.1"
 | 
				
			||||||
validator = { version = "0.14", features = ["derive"] }
 | 
					validator = { version = "0.14", features = ["derive"] }
 | 
				
			||||||
 | 
					rocket_cors = "0.6.0-alpha1"
 | 
				
			||||||
 | 
					local-ip-address = "0.4"
 | 
				
			||||||
 | 
				
			|||||||
@ -45,13 +45,12 @@ fn rocket() -> _ {
 | 
				
			|||||||
        .attach(Template::fairing())
 | 
					        .attach(Template::fairing())
 | 
				
			||||||
        .attach(AdHoc::on_ignite("Run Migrations", schema::run_migrations))
 | 
					        .attach(AdHoc::on_ignite("Run Migrations", schema::run_migrations))
 | 
				
			||||||
        .attach(AdHoc::config::<AppConfig>())
 | 
					        .attach(AdHoc::config::<AppConfig>())
 | 
				
			||||||
 | 
					        .attach(site::make_cors())
 | 
				
			||||||
        .mount(
 | 
					        .mount(
 | 
				
			||||||
            "/",
 | 
					            "/",
 | 
				
			||||||
            routes![
 | 
					            routes![
 | 
				
			||||||
                site::index,
 | 
					                site::index,
 | 
				
			||||||
                site::gamenights,
 | 
					                site::files
 | 
				
			||||||
                site::add_game_night,
 | 
					 | 
				
			||||||
                site::register
 | 
					 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .mount(
 | 
					        .mount(
 | 
				
			||||||
 | 
				
			|||||||
@ -1,90 +1,43 @@
 | 
				
			|||||||
use crate::schema;
 | 
					use rocket::fs::NamedFile;
 | 
				
			||||||
use rocket::request::FlashMessage;
 | 
					use rocket::http::Method;
 | 
				
			||||||
use rocket::response::Redirect;
 | 
					use rocket_cors::{AllowedHeaders, AllowedOrigins, Cors, CorsOptions};
 | 
				
			||||||
use rocket_dyn_templates::Template;
 | 
					use std::io;
 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					use std::path::{Path, PathBuf};
 | 
				
			||||||
use std::borrow::Cow;
 | 
					use local_ip_address::local_ip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Serialize, Deserialize, Debug)]
 | 
					
 | 
				
			||||||
struct FlashData {
 | 
					pub fn make_cors() -> Cors {
 | 
				
			||||||
    has_data: bool,
 | 
					    let allowed_origins = AllowedOrigins::some_exact(&[
 | 
				
			||||||
    kind: Cow<'static, str>,
 | 
					        "http://localhost:3000",
 | 
				
			||||||
    message: Cow<'static, str>,
 | 
					        "http://127.0.0.1:3000",
 | 
				
			||||||
 | 
					        &format!("http://{}:8000",local_ip().unwrap())[..],
 | 
				
			||||||
 | 
					        "http://localhost:8000",
 | 
				
			||||||
 | 
					        "http://0.0.0.0:8000",
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    CorsOptions {
 | 
				
			||||||
 | 
					        allowed_origins,
 | 
				
			||||||
 | 
					        allowed_methods: vec![Method::Get].into_iter().map(From::from).collect(), // 1.
 | 
				
			||||||
 | 
					        allowed_headers: AllowedHeaders::some(&[
 | 
				
			||||||
 | 
					            "Authorization",
 | 
				
			||||||
 | 
					            "Accept",
 | 
				
			||||||
 | 
					            "Access-Control-Allow-Origin",
 | 
				
			||||||
 | 
					        ]),
 | 
				
			||||||
 | 
					        allow_credentials: true,
 | 
				
			||||||
 | 
					        ..Default::default()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    .to_cors()
 | 
				
			||||||
 | 
					    .expect("error while building CORS")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl FlashData {
 | 
					#[get("/<file..>", rank = 10)]
 | 
				
			||||||
    const EMPTY: Self = Self {
 | 
					pub async fn files(file: PathBuf) -> Option<NamedFile> {
 | 
				
			||||||
        has_data: false,
 | 
					    NamedFile::open(Path::new("../frontend/build/").join(file))
 | 
				
			||||||
        message: Cow::Borrowed(""),
 | 
					        .await
 | 
				
			||||||
        kind: Cow::Borrowed(""),
 | 
					        .ok()
 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Serialize, Deserialize, Debug)]
 | 
					 | 
				
			||||||
struct GameNightsData {
 | 
					 | 
				
			||||||
    gamenights: Vec<schema::GameNight>,
 | 
					 | 
				
			||||||
    flash: FlashData,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[get("/gamenights")]
 | 
					 | 
				
			||||||
pub async fn gamenights(conn: schema::DbConn) -> Template {
 | 
					 | 
				
			||||||
    let gamenights = schema::get_all_gamenights(conn).await;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let data = GameNightsData {
 | 
					 | 
				
			||||||
        gamenights: gamenights,
 | 
					 | 
				
			||||||
        flash: FlashData::EMPTY,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Template::render("gamenights", &data)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[get("/")]
 | 
					#[get("/")]
 | 
				
			||||||
pub async fn index() -> Redirect {
 | 
					pub async fn index() -> io::Result<NamedFile> {
 | 
				
			||||||
    Redirect::to(uri!(gamenights))
 | 
					    NamedFile::open("../frontend/build/index.html").await
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Serialize, Deserialize, Debug)]
 | 
					 | 
				
			||||||
struct GameNightAddData {
 | 
					 | 
				
			||||||
    post_url: String,
 | 
					 | 
				
			||||||
    flash: FlashData,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[get("/gamenight/add")]
 | 
					 | 
				
			||||||
pub async fn add_game_night(flash: Option<FlashMessage<'_>>) -> Template {
 | 
					 | 
				
			||||||
    let flash_data = match flash {
 | 
					 | 
				
			||||||
        None => FlashData::EMPTY,
 | 
					 | 
				
			||||||
        Some(flash) => FlashData {
 | 
					 | 
				
			||||||
            has_data: true,
 | 
					 | 
				
			||||||
            message: Cow::Owned(flash.message().to_string()),
 | 
					 | 
				
			||||||
            kind: Cow::Owned(flash.kind().to_string()),
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let data = GameNightAddData {
 | 
					 | 
				
			||||||
        post_url: "/api/gamenight".to_string(),
 | 
					 | 
				
			||||||
        flash: flash_data,
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Template::render("gamenight_add", &data)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Serialize, Deserialize, Debug)]
 | 
					 | 
				
			||||||
struct RegisterData {
 | 
					 | 
				
			||||||
    flash: FlashData,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[get("/register")]
 | 
					 | 
				
			||||||
pub async fn register(flash: Option<FlashMessage<'_>>) -> Template {
 | 
					 | 
				
			||||||
    let flash_data = match flash {
 | 
					 | 
				
			||||||
        None => FlashData::EMPTY,
 | 
					 | 
				
			||||||
        Some(flash) => FlashData {
 | 
					 | 
				
			||||||
            has_data: true,
 | 
					 | 
				
			||||||
            message: Cow::Owned(flash.message().to_string()),
 | 
					 | 
				
			||||||
            kind: Cow::Owned(flash.kind().to_string()),
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let data = RegisterData { flash: flash_data };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Template::render("register", &data)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1571
									
								
								frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1571
									
								
								frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -15,7 +15,11 @@
 | 
				
			|||||||
    "start": "react-scripts start",
 | 
					    "start": "react-scripts start",
 | 
				
			||||||
    "build": "react-scripts build",
 | 
					    "build": "react-scripts build",
 | 
				
			||||||
    "test": "react-scripts test",
 | 
					    "test": "react-scripts test",
 | 
				
			||||||
    "eject": "react-scripts eject"
 | 
					    "eject": "react-scripts eject",
 | 
				
			||||||
 | 
					    "watch": "npm-watch"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "watch": {
 | 
				
			||||||
 | 
					    "build": "src/"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "eslintConfig": {
 | 
					  "eslintConfig": {
 | 
				
			||||||
    "extends": [
 | 
					    "extends": [
 | 
				
			||||||
@ -34,5 +38,8 @@
 | 
				
			|||||||
      "last 1 firefox version",
 | 
					      "last 1 firefox version",
 | 
				
			||||||
      "last 1 safari version"
 | 
					      "last 1 safari version"
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "devDependencies": {
 | 
				
			||||||
 | 
					    "npm-watch": "^0.11.0"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,7 @@
 | 
				
			|||||||
      work correctly both with client-side routing and a non-root public URL.
 | 
					      work correctly both with client-side routing and a non-root public URL.
 | 
				
			||||||
      Learn how to configure a non-root public URL by running `npm run build`.
 | 
					      Learn how to configure a non-root public URL by running `npm run build`.
 | 
				
			||||||
    -->
 | 
					    -->
 | 
				
			||||||
    <title>React App</title>
 | 
					    <title>It's gamenight</title>
 | 
				
			||||||
  </head>
 | 
					  </head>
 | 
				
			||||||
  <body>
 | 
					  <body>
 | 
				
			||||||
    <noscript>You need to enable JavaScript to run this app.</noscript>
 | 
					    <noscript>You need to enable JavaScript to run this app.</noscript>
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,19 @@
 | 
				
			|||||||
  color: #61dafb;
 | 
					  color: #61dafb;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fieldset label {
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					  text-align: left;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					input {
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					input[type=submit] {
 | 
				
			||||||
 | 
					  margin:5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@keyframes App-logo-spin {
 | 
					@keyframes App-logo-spin {
 | 
				
			||||||
  from {
 | 
					  from {
 | 
				
			||||||
    transform: rotate(0deg);
 | 
					    transform: rotate(0deg);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,25 +1,99 @@
 | 
				
			|||||||
import logo from './logo.svg';
 | 
					import logo from './logo.svg';
 | 
				
			||||||
import './App.css';
 | 
					import './App.css';
 | 
				
			||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import MenuBar from './components/MenuBar';
 | 
				
			||||||
 | 
					import Login from './components/Login';
 | 
				
			||||||
 | 
					import Gamenights from "./components/Gamenights"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function App() {
 | 
					class App extends React.Component {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(props) {
 | 
				
			||||||
 | 
					    super(props)
 | 
				
			||||||
 | 
					    this.handleLogin = this.handleLogin.bind(this);
 | 
				
			||||||
 | 
					    this.onLogout = this.onLogout.bind(this);
 | 
				
			||||||
 | 
					    this.state = {
 | 
				
			||||||
 | 
					      user: null,
 | 
				
			||||||
 | 
					      token: null,
 | 
				
			||||||
 | 
					      gamenights: null
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  componentDidUpdate(prevProps, prevState) {
 | 
				
			||||||
 | 
					    console.log("component update?")
 | 
				
			||||||
 | 
					    if (prevState.token !== this.state.token) {
 | 
				
			||||||
 | 
					      const requestOptions = {
 | 
				
			||||||
 | 
					        method: 'GET',
 | 
				
			||||||
 | 
					        headers: { 'Authorization': `bearer: ${this.state.token}` },
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      fetch('api/gamenights', requestOptions)
 | 
				
			||||||
 | 
					        .then(response => response.json())
 | 
				
			||||||
 | 
					        .then(data => {
 | 
				
			||||||
 | 
					          if(data.result === "Ok") {
 | 
				
			||||||
 | 
					            this.setState((state, props) => ({
 | 
				
			||||||
 | 
					              gamenights: data.gamenights
 | 
				
			||||||
 | 
					            }));
 | 
				
			||||||
 | 
					          } else {
 | 
				
			||||||
 | 
					            this.setState((state, props) => ({
 | 
				
			||||||
 | 
					              flash_data: {
 | 
				
			||||||
 | 
					                type: "Error",
 | 
				
			||||||
 | 
					                message: data.message
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }));
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          console.log(this.state)
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  render() {
 | 
				
			||||||
 | 
					    if(this.state.token === null) {
 | 
				
			||||||
      return (
 | 
					      return (
 | 
				
			||||||
        <div className="App">
 | 
					        <div className="App">
 | 
				
			||||||
      <header className="App-header">
 | 
					          <Login onChange={this.handleLogin}/>
 | 
				
			||||||
        <img src={logo} className="App-logo" alt="logo" />
 | 
					 | 
				
			||||||
        <p>
 | 
					 | 
				
			||||||
          Edit <code>src/App.js</code> and save to reload.
 | 
					 | 
				
			||||||
        </p>
 | 
					 | 
				
			||||||
        <a
 | 
					 | 
				
			||||||
          className="App-link"
 | 
					 | 
				
			||||||
          href="https://reactjs.org"
 | 
					 | 
				
			||||||
          target="_blank"
 | 
					 | 
				
			||||||
          rel="noopener noreferrer"
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
          Learn React
 | 
					 | 
				
			||||||
        </a>
 | 
					 | 
				
			||||||
      </header>
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      return (
 | 
				
			||||||
 | 
					        <div className="App">
 | 
				
			||||||
 | 
					          <MenuBar user={this.state.user} onLogout={this.onLogout}/>
 | 
				
			||||||
 | 
					          <Gamenights />
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  onLogout() {
 | 
				
			||||||
 | 
					    this.setState((state, props) => ({
 | 
				
			||||||
 | 
					      user: null,
 | 
				
			||||||
 | 
					      token: null,
 | 
				
			||||||
 | 
					      flash_data: null
 | 
				
			||||||
 | 
					    }));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleLogin(input) {
 | 
				
			||||||
 | 
					    const requestOptions = {
 | 
				
			||||||
 | 
					      method: 'POST',
 | 
				
			||||||
 | 
					      headers: { 'Content-Type': 'application/json' },
 | 
				
			||||||
 | 
					      body: JSON.stringify(input)
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    fetch('api/login', requestOptions)
 | 
				
			||||||
 | 
					      .then(response => response.json())
 | 
				
			||||||
 | 
					      .then(data => {
 | 
				
			||||||
 | 
					        if(data.result === "Ok") {
 | 
				
			||||||
 | 
					          this.setState((state, props) => ({
 | 
				
			||||||
 | 
					            token: data.jwt
 | 
				
			||||||
 | 
					          }));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          this.setState((state, props) => ({
 | 
				
			||||||
 | 
					            flash_data: {
 | 
				
			||||||
 | 
					              type: "Error",
 | 
				
			||||||
 | 
					              message: data.message
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        console.log(this.state)
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default App;
 | 
					export default App;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										21
									
								
								frontend/src/components/Gamenights.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								frontend/src/components/Gamenights.jsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class Gamenights extends React.Component {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(props) {
 | 
				
			||||||
 | 
					    super(props);
 | 
				
			||||||
 | 
					    this.state = {
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  render() {
 | 
				
			||||||
 | 
					    let gamenights = this.props.gamenights.map(g => 
 | 
				
			||||||
 | 
					      (<li>{g.name}</li>)
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <ul>
 | 
				
			||||||
 | 
					        {gamenights}
 | 
				
			||||||
 | 
					      </ul>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										56
									
								
								frontend/src/components/Login.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								frontend/src/components/Login.jsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class Login extends React.Component {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(props) {
 | 
				
			||||||
 | 
					    super(props);
 | 
				
			||||||
 | 
					    this.state = {
 | 
				
			||||||
 | 
					      username: "",
 | 
				
			||||||
 | 
					      password: "",
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.handleUsernameChange = this.handleUsernameChange.bind(this);
 | 
				
			||||||
 | 
					    this.handlePasswordChange = this.handlePasswordChange.bind(this);
 | 
				
			||||||
 | 
					    this.handleLogin = this.handleLogin.bind(this);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  render() {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <div className="Login-Component">
 | 
				
			||||||
 | 
					        <form onSubmit={this.handleLogin}>
 | 
				
			||||||
 | 
					          <fieldset>
 | 
				
			||||||
 | 
					            <legend>Login</legend>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <label for="username">Username:</label>
 | 
				
			||||||
 | 
					            <input id="username" name="username" type="text"
 | 
				
			||||||
 | 
					              value={this.state.username}
 | 
				
			||||||
 | 
					              onChange={this.handleUsernameChange} />
 | 
				
			||||||
 | 
					            <label for="password">Password:</label>
 | 
				
			||||||
 | 
					            <input id="password" name="password" type="password"
 | 
				
			||||||
 | 
					              value={this.state.password}
 | 
				
			||||||
 | 
					              onChange={this.handlePasswordChange} />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <input type="submit" value="Submit" />
 | 
				
			||||||
 | 
					          </fieldset>
 | 
				
			||||||
 | 
					        </form>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleUsernameChange(event) {
 | 
				
			||||||
 | 
					    this.setState((state, props) => ({
 | 
				
			||||||
 | 
					      username: event.target.value
 | 
				
			||||||
 | 
					    }));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handlePasswordChange(event) {
 | 
				
			||||||
 | 
					    this.setState((state, props) => ({
 | 
				
			||||||
 | 
					      password: event.target.value
 | 
				
			||||||
 | 
					    }));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  handleLogin(event) {
 | 
				
			||||||
 | 
					    this.props.onChange({ username: this.state.username, password: this.state.password });
 | 
				
			||||||
 | 
					    event.preventDefault();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										25
									
								
								frontend/src/components/MenuBar.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								frontend/src/components/MenuBar.jsx
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class MenuBar extends React.Component {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  constructor(props) {
 | 
				
			||||||
 | 
					    super(props);
 | 
				
			||||||
 | 
					    this.state = {};
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  render() {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					      <ul>
 | 
				
			||||||
 | 
					        <li>
 | 
				
			||||||
 | 
					          <a>Gamenight</a>
 | 
				
			||||||
 | 
					        </li>
 | 
				
			||||||
 | 
					        <li>
 | 
				
			||||||
 | 
					          <a>User</a>
 | 
				
			||||||
 | 
					        </li>
 | 
				
			||||||
 | 
					        <li>
 | 
				
			||||||
 | 
					          <button onClick={this.props.onLogout}>Logout</button>
 | 
				
			||||||
 | 
					        </li>
 | 
				
			||||||
 | 
					      </ul>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user