frontend init
This commit is contained in:
parent
57e0cb6a88
commit
8593af2441
4
.gitignore
vendored
4
.gitignore
vendored
@ -14,3 +14,7 @@ Cargo.lock
|
||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||
*.pdb
|
||||
|
||||
|
||||
.vscode
|
||||
|
||||
|
||||
|
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"eslint.enable": false,
|
||||
"standard.enable": false
|
||||
}
|
2289
Cargo.lock
generated
2289
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
12
Cargo.toml
12
Cargo.toml
@ -22,12 +22,14 @@ stv-rs = "0.3.0"
|
||||
|
||||
serde = "1.0"
|
||||
serde_derive = "1.0"
|
||||
serde_yaml = "0.7"
|
||||
serde_yaml = "0.9.34"
|
||||
serde_json = "1.0"
|
||||
base64 = "~0.7.0"
|
||||
futures = "0.1.16"
|
||||
hyper = "0.11.6"
|
||||
url = "1.5"
|
||||
base64 = "~0.22.1"
|
||||
futures = "0.3.30"
|
||||
hyper = "1.3.1"
|
||||
url = "2.5.0"
|
||||
|
||||
sqlx = "0.7.4"
|
||||
|
||||
[dev-dependencies]
|
||||
tokio-core = "*"
|
||||
|
480
flake.lock
generated
Normal file
480
flake.lock
generated
Normal file
@ -0,0 +1,480 @@
|
||||
{
|
||||
"nodes": {
|
||||
"cachix": {
|
||||
"inputs": {
|
||||
"devenv": "devenv_2",
|
||||
"flake-compat": [
|
||||
"devenv",
|
||||
"flake-compat"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"devenv",
|
||||
"nixpkgs"
|
||||
],
|
||||
"pre-commit-hooks": [
|
||||
"devenv",
|
||||
"pre-commit-hooks"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1712055811,
|
||||
"narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=",
|
||||
"owner": "cachix",
|
||||
"repo": "cachix",
|
||||
"rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "cachix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"devenv": {
|
||||
"inputs": {
|
||||
"cachix": "cachix",
|
||||
"flake-compat": "flake-compat_2",
|
||||
"nix": "nix_2",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"pre-commit-hooks": "pre-commit-hooks"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1716484006,
|
||||
"narHash": "sha256-2gtN5jf21HS9TAZXhf9G+OSUY1TQ/95n6clcuFjYQ58=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "800f19d1b999f89464fd8e0226abf4b3b444b0fa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"devenv_2": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"devenv",
|
||||
"cachix",
|
||||
"flake-compat"
|
||||
],
|
||||
"nix": "nix",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"poetry2nix": "poetry2nix",
|
||||
"pre-commit-hooks": [
|
||||
"devenv",
|
||||
"cachix",
|
||||
"pre-commit-hooks"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1708704632,
|
||||
"narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv",
|
||||
"rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"ref": "python-rewrite",
|
||||
"repo": "devenv",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"fenix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"rust-analyzer-src": "rust-analyzer-src"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1716618425,
|
||||
"narHash": "sha256-eZs7f4izo6t0AmOI1IAU6/ZbbXrxMPGdo+khe4hP3Rk=",
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"rev": "9a9fafd0c3f796b675acb2e16ae238d4fd2cbdb5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "fenix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1673956053,
|
||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_2": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1689068808,
|
||||
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_2": {
|
||||
"inputs": {
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"devenv",
|
||||
"pre-commit-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"nixpkgs": [
|
||||
"devenv",
|
||||
"cachix",
|
||||
"devenv",
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-regression": "nixpkgs-regression"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1712911606,
|
||||
"narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
|
||||
"owner": "domenkozar",
|
||||
"repo": "nix",
|
||||
"rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "domenkozar",
|
||||
"ref": "devenv-2.21",
|
||||
"repo": "nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-github-actions": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"devenv",
|
||||
"cachix",
|
||||
"devenv",
|
||||
"poetry2nix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1688870561,
|
||||
"narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"rev": "165b1650b753316aa7f1787f3005a8d2da0f5301",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix_2": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"devenv",
|
||||
"flake-compat"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"devenv",
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-regression": "nixpkgs-regression_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1712911606,
|
||||
"narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=",
|
||||
"owner": "domenkozar",
|
||||
"repo": "nix",
|
||||
"rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "domenkozar",
|
||||
"ref": "devenv-2.21",
|
||||
"repo": "nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1692808169,
|
||||
"narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9201b5ff357e781bf014d0330d18555695df7ba8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-regression": {
|
||||
"locked": {
|
||||
"lastModified": 1643052045,
|
||||
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-regression_2": {
|
||||
"locked": {
|
||||
"lastModified": 1643052045,
|
||||
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1710695816,
|
||||
"narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "614b4613980a522ba49f0d194531beddbb7220d3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-23.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1713361204,
|
||||
"narHash": "sha256-TA6EDunWTkc5FvDCqU3W2T3SFn0gRZqh6D/hJnM02MM=",
|
||||
"owner": "cachix",
|
||||
"repo": "devenv-nixpkgs",
|
||||
"rev": "285676e87ad9f0ca23d8714a6ab61e7e027020c6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"ref": "rolling",
|
||||
"repo": "devenv-nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1716509168,
|
||||
"narHash": "sha256-4zSIhSRRIoEBwjbPm3YiGtbd8HDWzFxJjw5DYSDy1n8=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "bfb7a882678e518398ce9a31a881538679f6f092",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"poetry2nix": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nix-github-actions": "nix-github-actions",
|
||||
"nixpkgs": [
|
||||
"devenv",
|
||||
"cachix",
|
||||
"devenv",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1692876271,
|
||||
"narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=",
|
||||
"owner": "nix-community",
|
||||
"repo": "poetry2nix",
|
||||
"rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "poetry2nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"pre-commit-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"devenv",
|
||||
"flake-compat"
|
||||
],
|
||||
"flake-utils": "flake-utils_2",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"devenv",
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1713775815,
|
||||
"narHash": "sha256-Wu9cdYTnGQQwtT20QQMg7jzkANKQjwBD9iccfGKkfls=",
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "2ac4dcbf55ed43f3be0bae15e181f08a57af24a4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"devenv": "devenv",
|
||||
"fenix": "fenix",
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
}
|
||||
},
|
||||
"rust-analyzer-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1716572615,
|
||||
"narHash": "sha256-mVUbarr4PNjERDk+uaoitPq7eL7De0ythZehezAzug8=",
|
||||
"owner": "rust-lang",
|
||||
"repo": "rust-analyzer",
|
||||
"rev": "a55e8bf09cdfc25066b77823cc98976a51af8a8b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rust-lang",
|
||||
"ref": "nightly",
|
||||
"repo": "rust-analyzer",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_2": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
111
src/api.rs
Normal file
111
src/api.rs
Normal file
@ -0,0 +1,111 @@
|
||||
#![feature(proc_macro_hygiene, decl_macro)]
|
||||
|
||||
#[macro_use] extern crate rocket;
|
||||
#[macro_use] extern crate rocket_contrib;
|
||||
#[macro_use] extern crate serde_derive;
|
||||
|
||||
use rocket::http::Status;
|
||||
use rocket_contrib::json::{Json, JsonValue};
|
||||
|
||||
// Define data models
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct User {
|
||||
id: String,
|
||||
username: String,
|
||||
password: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Authorization {
|
||||
to_date: String,
|
||||
from_date: String,
|
||||
user: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Election {
|
||||
id: String,
|
||||
username: String,
|
||||
name: String,
|
||||
description: String,
|
||||
start_date: String,
|
||||
end_date: String,
|
||||
items: Vec<ElectionItem>,
|
||||
}
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct ElectionItem {
|
||||
id: String,
|
||||
name: String,
|
||||
}
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct VoteItem {
|
||||
item: ElectionItem,
|
||||
value: f64,
|
||||
}
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Vote {
|
||||
authorization: Authorization,
|
||||
userid: String,
|
||||
data: Vec<VoteItem>,
|
||||
}
|
||||
|
||||
// Routes
|
||||
#[post("/auth/login", format = "application/json", data = "<credentials>")]
|
||||
fn login(credentials: Json<User>) -> JsonValue {
|
||||
// Authentication logic here
|
||||
json!({
|
||||
"token": "your_generated_token"
|
||||
})
|
||||
}
|
||||
|
||||
#[post("/auth/token", format = "application/json", data = "<token>")]
|
||||
fn generate_token(token: Json<Authorization>) -> JsonValue {
|
||||
// Token generation logic here
|
||||
json!({
|
||||
"token": "generated_token"
|
||||
})
|
||||
}
|
||||
|
||||
#[post("/elections/create", format = "application/json", data = "<election>")]
|
||||
fn create_election(election: Json<Election>) -> Result<JsonValue, Status> {
|
||||
// Election creation logic here
|
||||
Ok(json!(election))
|
||||
}
|
||||
|
||||
#[get("/elections/all")]
|
||||
fn get_all_elections() -> JsonValue {
|
||||
// Retrieve all elections logic here
|
||||
json!([
|
||||
// List of all existing elections
|
||||
])
|
||||
}
|
||||
|
||||
#[get("/elections/<id>")]
|
||||
fn get_election(id: String) -> JsonValue {
|
||||
// Retrieve single election logic here
|
||||
json!({
|
||||
"id": id,
|
||||
// Other election details
|
||||
})
|
||||
}
|
||||
|
||||
#[post("/elections/<id>", format = "application/json", data = "<vote>")]
|
||||
fn vote_in_election(id: String, vote: Json<Vote>) -> Result<JsonValue, Status> {
|
||||
// Voting logic here
|
||||
Ok(json!(vote))
|
||||
}
|
||||
|
||||
// Rocket fairings to set up CORS and other middlewares can be added here
|
||||
|
||||
fn main() {
|
||||
rocket::ignite()
|
||||
.mount("/api", routes![
|
||||
login,
|
||||
generate_token,
|
||||
create_election,
|
||||
get_all_elections,
|
||||
get_election,
|
||||
vote_in_election,
|
||||
])
|
||||
.launch();
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use hyper;
|
||||
use super::configuration::Configuration;
|
||||
|
||||
pub struct APIClient<C: hyper::client::Connect> {
|
||||
configuration: Rc<Configuration<C>>,
|
||||
default_api: Box<::apis::DefaultApi>,
|
||||
}
|
||||
|
||||
impl<C: hyper::client::Connect> APIClient<C> {
|
||||
pub fn new(configuration: Configuration<C>) -> APIClient<C> {
|
||||
let rc = Rc::new(configuration);
|
||||
|
||||
APIClient {
|
||||
configuration: rc.clone(),
|
||||
default_api: Box::new(::apis::DefaultApiClient::new(rc.clone())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default_api(&self) -> &::apis::DefaultApi{
|
||||
self.default_api.as_ref()
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* vote-rs API
|
||||
*
|
||||
* API for conducting electronic voting
|
||||
*
|
||||
* OpenAPI spec version: 0.0.1
|
||||
*
|
||||
* Generated by: https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
use hyper;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct Configuration<C: hyper::client::Connect> {
|
||||
pub base_path: String,
|
||||
pub user_agent: Option<String>,
|
||||
pub client: hyper::client::Client<C>,
|
||||
pub basic_auth: Option<BasicAuth>,
|
||||
pub oauth_access_token: Option<String>,
|
||||
pub api_key: Option<ApiKey>,
|
||||
// TODO: take an oauth2 token source, similar to the go one
|
||||
}
|
||||
|
||||
pub type BasicAuth = (String, Option<String>);
|
||||
|
||||
pub struct ApiKey {
|
||||
pub prefix: Option<String>,
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
impl<C: hyper::client::Connect> Configuration<C> {
|
||||
pub fn new(client: hyper::client::Client<C>) -> Configuration<C> {
|
||||
Configuration {
|
||||
base_path: "https://localhost/api".to_owned(),
|
||||
user_agent: Some("Swagger-Codegen/0.0.1/rust".to_owned()),
|
||||
client: client,
|
||||
basic_auth: None,
|
||||
oauth_access_token: None,
|
||||
api_key: None,
|
||||
}
|
||||
}
|
||||
}
|
@ -1,480 +0,0 @@
|
||||
/*
|
||||
* vote-rs API
|
||||
*
|
||||
* API for conducting electronic voting
|
||||
*
|
||||
* OpenAPI spec version: 0.0.1
|
||||
*
|
||||
* Generated by: https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
use std::rc::Rc;
|
||||
use std::borrow::Borrow;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use hyper;
|
||||
use serde_json;
|
||||
use futures;
|
||||
use futures::{Future, Stream};
|
||||
|
||||
use hyper::header::UserAgent;
|
||||
|
||||
use super::{Error, configuration};
|
||||
|
||||
pub struct DefaultApiClient<C: hyper::client::Connect> {
|
||||
configuration: Rc<configuration::Configuration<C>>,
|
||||
}
|
||||
|
||||
impl<C: hyper::client::Connect> DefaultApiClient<C> {
|
||||
pub fn new(configuration: Rc<configuration::Configuration<C>>) -> DefaultApiClient<C> {
|
||||
DefaultApiClient {
|
||||
configuration: configuration,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait DefaultApi {
|
||||
fn auth_login_post(&self, credentials: ::models::Credentials) -> Box<Future<Item = ::models::InlineResponse200, Error = Error<serde_json::Value>>>;
|
||||
fn auth_token_post(&self, authorization: &str, token: ::models::Authorization) -> Box<Future<Item = ::models::InlineResponse2001, Error = Error<serde_json::Value>>>;
|
||||
fn elections_all_get(&self, authorization: &str) -> Box<Future<Item = ::models::ElectionList, Error = Error<serde_json::Value>>>;
|
||||
fn elections_create_post(&self, authorization: &str, election: ::models::Election) -> Box<Future<Item = ::models::Election, Error = Error<serde_json::Value>>>;
|
||||
fn elections_id_get(&self, authorization: &str, id: &str) -> Box<Future<Item = ::models::Election, Error = Error<serde_json::Value>>>;
|
||||
fn elections_id_post(&self, authorization: &str, election: ::models::Vote) -> Box<Future<Item = ::models::Vote, Error = Error<serde_json::Value>>>;
|
||||
}
|
||||
|
||||
|
||||
impl<C: hyper::client::Connect>DefaultApi for DefaultApiClient<C> {
|
||||
fn auth_login_post(&self, credentials: ::models::Credentials) -> Box<Future<Item = ::models::InlineResponse200, Error = Error<serde_json::Value>>> {
|
||||
let configuration: &configuration::Configuration<C> = self.configuration.borrow();
|
||||
|
||||
let mut auth_headers = HashMap::<String, String>::new();
|
||||
let mut auth_query = HashMap::<String, String>::new();
|
||||
if let Some(ref apikey) = configuration.api_key {
|
||||
let key = apikey.key.clone();
|
||||
let val = match apikey.prefix {
|
||||
Some(ref prefix) => format!("{} {}", prefix, key),
|
||||
None => key,
|
||||
};
|
||||
auth_headers.insert("Authorization".to_owned(), val);
|
||||
};
|
||||
let method = hyper::Method::Post;
|
||||
|
||||
let query_string = {
|
||||
let mut query = ::url::form_urlencoded::Serializer::new(String::new());
|
||||
for (key, val) in &auth_query {
|
||||
query.append_pair(key, val);
|
||||
}
|
||||
query.finish()
|
||||
};
|
||||
let uri_str = format!("{}/auth/login?{}", configuration.base_path, query_string);
|
||||
|
||||
// TODO(farcaller): handle error
|
||||
// if let Err(e) = uri {
|
||||
// return Box::new(futures::future::err(e));
|
||||
// }
|
||||
let mut uri: hyper::Uri = uri_str.parse().unwrap();
|
||||
|
||||
let mut req = hyper::Request::new(method, uri);
|
||||
|
||||
if let Some(ref user_agent) = configuration.user_agent {
|
||||
req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone())));
|
||||
}
|
||||
|
||||
|
||||
for (key, val) in auth_headers {
|
||||
req.headers_mut().set_raw(key, val);
|
||||
}
|
||||
|
||||
let serialized = serde_json::to_string(&credentials).unwrap();
|
||||
req.headers_mut().set(hyper::header::ContentType::json());
|
||||
req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64));
|
||||
req.set_body(serialized);
|
||||
|
||||
// send request
|
||||
Box::new(
|
||||
configuration.client.request(req)
|
||||
.map_err(|e| Error::from(e))
|
||||
.and_then(|resp| {
|
||||
let status = resp.status();
|
||||
resp.body().concat2()
|
||||
.and_then(move |body| Ok((status, body)))
|
||||
.map_err(|e| Error::from(e))
|
||||
})
|
||||
.and_then(|(status, body)| {
|
||||
if status.is_success() {
|
||||
Ok(body)
|
||||
} else {
|
||||
Err(Error::from((status, &*body)))
|
||||
}
|
||||
})
|
||||
.and_then(|body| {
|
||||
let parsed: Result<::models::InlineResponse200, _> = serde_json::from_slice(&body);
|
||||
parsed.map_err(|e| Error::from(e))
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
fn auth_token_post(&self, authorization: &str, token: ::models::Authorization) -> Box<Future<Item = ::models::InlineResponse2001, Error = Error<serde_json::Value>>> {
|
||||
let configuration: &configuration::Configuration<C> = self.configuration.borrow();
|
||||
|
||||
let mut auth_headers = HashMap::<String, String>::new();
|
||||
let mut auth_query = HashMap::<String, String>::new();
|
||||
if let Some(ref apikey) = configuration.api_key {
|
||||
let key = apikey.key.clone();
|
||||
let val = match apikey.prefix {
|
||||
Some(ref prefix) => format!("{} {}", prefix, key),
|
||||
None => key,
|
||||
};
|
||||
auth_headers.insert("Authorization".to_owned(), val);
|
||||
};
|
||||
let method = hyper::Method::Post;
|
||||
|
||||
let query_string = {
|
||||
let mut query = ::url::form_urlencoded::Serializer::new(String::new());
|
||||
for (key, val) in &auth_query {
|
||||
query.append_pair(key, val);
|
||||
}
|
||||
query.finish()
|
||||
};
|
||||
let uri_str = format!("{}/auth/token?{}", configuration.base_path, query_string);
|
||||
|
||||
// TODO(farcaller): handle error
|
||||
// if let Err(e) = uri {
|
||||
// return Box::new(futures::future::err(e));
|
||||
// }
|
||||
let mut uri: hyper::Uri = uri_str.parse().unwrap();
|
||||
|
||||
let mut req = hyper::Request::new(method, uri);
|
||||
|
||||
if let Some(ref user_agent) = configuration.user_agent {
|
||||
req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone())));
|
||||
}
|
||||
|
||||
{
|
||||
let mut headers = req.headers_mut();
|
||||
headers.set_raw("Authorization", authorization);
|
||||
}
|
||||
|
||||
for (key, val) in auth_headers {
|
||||
req.headers_mut().set_raw(key, val);
|
||||
}
|
||||
|
||||
let serialized = serde_json::to_string(&token).unwrap();
|
||||
req.headers_mut().set(hyper::header::ContentType::json());
|
||||
req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64));
|
||||
req.set_body(serialized);
|
||||
|
||||
// send request
|
||||
Box::new(
|
||||
configuration.client.request(req)
|
||||
.map_err(|e| Error::from(e))
|
||||
.and_then(|resp| {
|
||||
let status = resp.status();
|
||||
resp.body().concat2()
|
||||
.and_then(move |body| Ok((status, body)))
|
||||
.map_err(|e| Error::from(e))
|
||||
})
|
||||
.and_then(|(status, body)| {
|
||||
if status.is_success() {
|
||||
Ok(body)
|
||||
} else {
|
||||
Err(Error::from((status, &*body)))
|
||||
}
|
||||
})
|
||||
.and_then(|body| {
|
||||
let parsed: Result<::models::InlineResponse2001, _> = serde_json::from_slice(&body);
|
||||
parsed.map_err(|e| Error::from(e))
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
fn elections_all_get(&self, authorization: &str) -> Box<Future<Item = ::models::ElectionList, Error = Error<serde_json::Value>>> {
|
||||
let configuration: &configuration::Configuration<C> = self.configuration.borrow();
|
||||
|
||||
let mut auth_headers = HashMap::<String, String>::new();
|
||||
let mut auth_query = HashMap::<String, String>::new();
|
||||
if let Some(ref apikey) = configuration.api_key {
|
||||
let key = apikey.key.clone();
|
||||
let val = match apikey.prefix {
|
||||
Some(ref prefix) => format!("{} {}", prefix, key),
|
||||
None => key,
|
||||
};
|
||||
auth_headers.insert("Authorization".to_owned(), val);
|
||||
};
|
||||
let method = hyper::Method::Get;
|
||||
|
||||
let query_string = {
|
||||
let mut query = ::url::form_urlencoded::Serializer::new(String::new());
|
||||
for (key, val) in &auth_query {
|
||||
query.append_pair(key, val);
|
||||
}
|
||||
query.finish()
|
||||
};
|
||||
let uri_str = format!("{}/elections/all?{}", configuration.base_path, query_string);
|
||||
|
||||
// TODO(farcaller): handle error
|
||||
// if let Err(e) = uri {
|
||||
// return Box::new(futures::future::err(e));
|
||||
// }
|
||||
let mut uri: hyper::Uri = uri_str.parse().unwrap();
|
||||
|
||||
let mut req = hyper::Request::new(method, uri);
|
||||
|
||||
if let Some(ref user_agent) = configuration.user_agent {
|
||||
req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone())));
|
||||
}
|
||||
|
||||
{
|
||||
let mut headers = req.headers_mut();
|
||||
headers.set_raw("Authorization", authorization);
|
||||
}
|
||||
|
||||
for (key, val) in auth_headers {
|
||||
req.headers_mut().set_raw(key, val);
|
||||
}
|
||||
|
||||
|
||||
// send request
|
||||
Box::new(
|
||||
configuration.client.request(req)
|
||||
.map_err(|e| Error::from(e))
|
||||
.and_then(|resp| {
|
||||
let status = resp.status();
|
||||
resp.body().concat2()
|
||||
.and_then(move |body| Ok((status, body)))
|
||||
.map_err(|e| Error::from(e))
|
||||
})
|
||||
.and_then(|(status, body)| {
|
||||
if status.is_success() {
|
||||
Ok(body)
|
||||
} else {
|
||||
Err(Error::from((status, &*body)))
|
||||
}
|
||||
})
|
||||
.and_then(|body| {
|
||||
let parsed: Result<::models::ElectionList, _> = serde_json::from_slice(&body);
|
||||
parsed.map_err(|e| Error::from(e))
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
fn elections_create_post(&self, authorization: &str, election: ::models::Election) -> Box<Future<Item = ::models::Election, Error = Error<serde_json::Value>>> {
|
||||
let configuration: &configuration::Configuration<C> = self.configuration.borrow();
|
||||
|
||||
let mut auth_headers = HashMap::<String, String>::new();
|
||||
let mut auth_query = HashMap::<String, String>::new();
|
||||
if let Some(ref apikey) = configuration.api_key {
|
||||
let key = apikey.key.clone();
|
||||
let val = match apikey.prefix {
|
||||
Some(ref prefix) => format!("{} {}", prefix, key),
|
||||
None => key,
|
||||
};
|
||||
auth_headers.insert("Authorization".to_owned(), val);
|
||||
};
|
||||
let method = hyper::Method::Post;
|
||||
|
||||
let query_string = {
|
||||
let mut query = ::url::form_urlencoded::Serializer::new(String::new());
|
||||
for (key, val) in &auth_query {
|
||||
query.append_pair(key, val);
|
||||
}
|
||||
query.finish()
|
||||
};
|
||||
let uri_str = format!("{}/elections/create?{}", configuration.base_path, query_string);
|
||||
|
||||
// TODO(farcaller): handle error
|
||||
// if let Err(e) = uri {
|
||||
// return Box::new(futures::future::err(e));
|
||||
// }
|
||||
let mut uri: hyper::Uri = uri_str.parse().unwrap();
|
||||
|
||||
let mut req = hyper::Request::new(method, uri);
|
||||
|
||||
if let Some(ref user_agent) = configuration.user_agent {
|
||||
req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone())));
|
||||
}
|
||||
|
||||
{
|
||||
let mut headers = req.headers_mut();
|
||||
headers.set_raw("Authorization", authorization);
|
||||
}
|
||||
|
||||
for (key, val) in auth_headers {
|
||||
req.headers_mut().set_raw(key, val);
|
||||
}
|
||||
|
||||
let serialized = serde_json::to_string(&election).unwrap();
|
||||
req.headers_mut().set(hyper::header::ContentType::json());
|
||||
req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64));
|
||||
req.set_body(serialized);
|
||||
|
||||
// send request
|
||||
Box::new(
|
||||
configuration.client.request(req)
|
||||
.map_err(|e| Error::from(e))
|
||||
.and_then(|resp| {
|
||||
let status = resp.status();
|
||||
resp.body().concat2()
|
||||
.and_then(move |body| Ok((status, body)))
|
||||
.map_err(|e| Error::from(e))
|
||||
})
|
||||
.and_then(|(status, body)| {
|
||||
if status.is_success() {
|
||||
Ok(body)
|
||||
} else {
|
||||
Err(Error::from((status, &*body)))
|
||||
}
|
||||
})
|
||||
.and_then(|body| {
|
||||
let parsed: Result<::models::Election, _> = serde_json::from_slice(&body);
|
||||
parsed.map_err(|e| Error::from(e))
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
fn elections_id_get(&self, authorization: &str, id: &str) -> Box<Future<Item = ::models::Election, Error = Error<serde_json::Value>>> {
|
||||
let configuration: &configuration::Configuration<C> = self.configuration.borrow();
|
||||
|
||||
let mut auth_headers = HashMap::<String, String>::new();
|
||||
let mut auth_query = HashMap::<String, String>::new();
|
||||
if let Some(ref apikey) = configuration.api_key {
|
||||
let key = apikey.key.clone();
|
||||
let val = match apikey.prefix {
|
||||
Some(ref prefix) => format!("{} {}", prefix, key),
|
||||
None => key,
|
||||
};
|
||||
auth_headers.insert("Authorization".to_owned(), val);
|
||||
};
|
||||
let method = hyper::Method::Get;
|
||||
|
||||
let query_string = {
|
||||
let mut query = ::url::form_urlencoded::Serializer::new(String::new());
|
||||
for (key, val) in &auth_query {
|
||||
query.append_pair(key, val);
|
||||
}
|
||||
query.finish()
|
||||
};
|
||||
let uri_str = format!("{}/elections/{id}?{}", configuration.base_path, query_string, id=id);
|
||||
|
||||
// TODO(farcaller): handle error
|
||||
// if let Err(e) = uri {
|
||||
// return Box::new(futures::future::err(e));
|
||||
// }
|
||||
let mut uri: hyper::Uri = uri_str.parse().unwrap();
|
||||
|
||||
let mut req = hyper::Request::new(method, uri);
|
||||
|
||||
if let Some(ref user_agent) = configuration.user_agent {
|
||||
req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone())));
|
||||
}
|
||||
|
||||
{
|
||||
let mut headers = req.headers_mut();
|
||||
headers.set_raw("Authorization", authorization);
|
||||
}
|
||||
|
||||
for (key, val) in auth_headers {
|
||||
req.headers_mut().set_raw(key, val);
|
||||
}
|
||||
|
||||
|
||||
// send request
|
||||
Box::new(
|
||||
configuration.client.request(req)
|
||||
.map_err(|e| Error::from(e))
|
||||
.and_then(|resp| {
|
||||
let status = resp.status();
|
||||
resp.body().concat2()
|
||||
.and_then(move |body| Ok((status, body)))
|
||||
.map_err(|e| Error::from(e))
|
||||
})
|
||||
.and_then(|(status, body)| {
|
||||
if status.is_success() {
|
||||
Ok(body)
|
||||
} else {
|
||||
Err(Error::from((status, &*body)))
|
||||
}
|
||||
})
|
||||
.and_then(|body| {
|
||||
let parsed: Result<::models::Election, _> = serde_json::from_slice(&body);
|
||||
parsed.map_err(|e| Error::from(e))
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
fn elections_id_post(&self, authorization: &str, election: ::models::Vote) -> Box<Future<Item = ::models::Vote, Error = Error<serde_json::Value>>> {
|
||||
let configuration: &configuration::Configuration<C> = self.configuration.borrow();
|
||||
|
||||
let mut auth_headers = HashMap::<String, String>::new();
|
||||
let mut auth_query = HashMap::<String, String>::new();
|
||||
if let Some(ref apikey) = configuration.api_key {
|
||||
let key = apikey.key.clone();
|
||||
let val = match apikey.prefix {
|
||||
Some(ref prefix) => format!("{} {}", prefix, key),
|
||||
None => key,
|
||||
};
|
||||
auth_headers.insert("Authorization".to_owned(), val);
|
||||
};
|
||||
let method = hyper::Method::Post;
|
||||
|
||||
let query_string = {
|
||||
let mut query = ::url::form_urlencoded::Serializer::new(String::new());
|
||||
for (key, val) in &auth_query {
|
||||
query.append_pair(key, val);
|
||||
}
|
||||
query.finish()
|
||||
};
|
||||
let uri_str = format!("{}/elections/{id}?{}", configuration.base_path, query_string);
|
||||
|
||||
// TODO(farcaller): handle error
|
||||
// if let Err(e) = uri {
|
||||
// return Box::new(futures::future::err(e));
|
||||
// }
|
||||
let mut uri: hyper::Uri = uri_str.parse().unwrap();
|
||||
|
||||
let mut req = hyper::Request::new(method, uri);
|
||||
|
||||
if let Some(ref user_agent) = configuration.user_agent {
|
||||
req.headers_mut().set(UserAgent::new(Cow::Owned(user_agent.clone())));
|
||||
}
|
||||
|
||||
{
|
||||
let mut headers = req.headers_mut();
|
||||
headers.set_raw("Authorization", authorization);
|
||||
}
|
||||
|
||||
for (key, val) in auth_headers {
|
||||
req.headers_mut().set_raw(key, val);
|
||||
}
|
||||
|
||||
let serialized = serde_json::to_string(&election).unwrap();
|
||||
req.headers_mut().set(hyper::header::ContentType::json());
|
||||
req.headers_mut().set(hyper::header::ContentLength(serialized.len() as u64));
|
||||
req.set_body(serialized);
|
||||
|
||||
// send request
|
||||
Box::new(
|
||||
configuration.client.request(req)
|
||||
.map_err(|e| Error::from(e))
|
||||
.and_then(|resp| {
|
||||
let status = resp.status();
|
||||
resp.body().concat2()
|
||||
.and_then(move |body| Ok((status, body)))
|
||||
.map_err(|e| Error::from(e))
|
||||
})
|
||||
.and_then(|(status, body)| {
|
||||
if status.is_success() {
|
||||
Ok(body)
|
||||
} else {
|
||||
Err(Error::from((status, &*body)))
|
||||
}
|
||||
})
|
||||
.and_then(|body| {
|
||||
let parsed: Result<::models::Vote, _> = serde_json::from_slice(&body);
|
||||
parsed.map_err(|e| Error::from(e))
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
use hyper;
|
||||
use serde;
|
||||
use serde_json;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error<T> {
|
||||
Hyper(hyper::Error),
|
||||
Serde(serde_json::Error),
|
||||
ApiError(ApiError<T>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ApiError<T> {
|
||||
pub code: hyper::StatusCode,
|
||||
pub content: Option<T>,
|
||||
}
|
||||
|
||||
impl<'de, T> From<(hyper::StatusCode, &'de [u8])> for Error<T>
|
||||
where T: serde::Deserialize<'de> {
|
||||
fn from(e: (hyper::StatusCode, &'de [u8])) -> Self {
|
||||
if e.1.len() == 0 {
|
||||
return Error::ApiError(ApiError{
|
||||
code: e.0,
|
||||
content: None,
|
||||
});
|
||||
}
|
||||
match serde_json::from_slice::<T>(e.1) {
|
||||
Ok(t) => Error::ApiError(ApiError{
|
||||
code: e.0,
|
||||
content: Some(t),
|
||||
}),
|
||||
Err(e) => {
|
||||
Error::from(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<hyper::Error> for Error<T> {
|
||||
fn from(e: hyper::Error) -> Self {
|
||||
return Error::Hyper(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<serde_json::Error> for Error<T> {
|
||||
fn from(e: serde_json::Error) -> Self {
|
||||
return Error::Serde(e)
|
||||
}
|
||||
}
|
||||
|
||||
use super::models::*;
|
||||
|
||||
mod default_api;
|
||||
pub use self::default_api::{ DefaultApi, DefaultApiClient };
|
||||
|
||||
pub mod configuration;
|
||||
pub mod client;
|
61
src/main.rs
61
src/main.rs
@ -1,61 +0,0 @@
|
||||
#[macro_use]
|
||||
extern crate rocket;
|
||||
|
||||
use rocket::form::Form;
|
||||
use rocket::response::Redirect;
|
||||
use rocket::State; // Add this line
|
||||
use rocket::fs::FileServer;
|
||||
use rocket::serde::json::Json;
|
||||
use rocket_dyn_templates::Template;
|
||||
use std::sync::Mutex;
|
||||
use std::collections::HashMap;
|
||||
use csv::Writer;
|
||||
|
||||
mod voting;
|
||||
|
||||
#[derive(rocket::FromForm)]
|
||||
struct Vote {
|
||||
option: String,
|
||||
}
|
||||
|
||||
type Votes = Mutex<Writer<std::fs::File>>;
|
||||
|
||||
#[post("/vote", data = "<vote>")]
|
||||
fn vote(vote: Form<Vote>, votes: &State<Votes>) -> Redirect {
|
||||
let mut writer = votes.lock().unwrap();
|
||||
writer.write_record(&[vote.option.clone()]).unwrap();
|
||||
writer.flush().unwrap();
|
||||
|
||||
Redirect::to("/")
|
||||
}
|
||||
|
||||
#[post("/results")]
|
||||
fn results() -> Json<HashMap<String, String>> {
|
||||
let election_data = voting::csv_to_election_data("votes.csv", 1, "Election".to_string());
|
||||
let blt = voting::election_data_to_blt(election_data);
|
||||
let results = voting::run_blt(blt);
|
||||
Json(results)
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
fn index() -> Template {
|
||||
let context: HashMap<&str, &str> = HashMap::new();
|
||||
Template::render("index", &context)
|
||||
}
|
||||
|
||||
#[launch]
|
||||
fn rocket() -> _ {
|
||||
let file = std::fs::OpenOptions::new()
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open("votes.csv")
|
||||
.unwrap();
|
||||
|
||||
let writer = csv::Writer::from_writer(file);
|
||||
|
||||
rocket::build()
|
||||
.attach(Template::fairing())
|
||||
.manage(Mutex::new(writer))
|
||||
.mount("/", routes![index, vote])
|
||||
.mount("/static", FileServer::from("static"))
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* vote-rs API
|
||||
*
|
||||
* API for conducting electronic voting
|
||||
*
|
||||
* OpenAPI spec version: 0.0.1
|
||||
*
|
||||
* Generated by: https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Authorization {
|
||||
#[serde(rename = "to_date")]
|
||||
to_date: Option<String>,
|
||||
#[serde(rename = "from_date")]
|
||||
from_date: Option<String>,
|
||||
#[serde(rename = "user")]
|
||||
user: Option<String>
|
||||
}
|
||||
|
||||
impl Authorization {
|
||||
pub fn new() -> Authorization {
|
||||
Authorization {
|
||||
to_date: None,
|
||||
from_date: None,
|
||||
user: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_to_date(&mut self, to_date: String) {
|
||||
self.to_date = Some(to_date);
|
||||
}
|
||||
|
||||
pub fn with_to_date(mut self, to_date: String) -> Authorization {
|
||||
self.to_date = Some(to_date);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn to_date(&self) -> Option<&String> {
|
||||
self.to_date.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_to_date(&mut self) {
|
||||
self.to_date = None;
|
||||
}
|
||||
|
||||
pub fn set_from_date(&mut self, from_date: String) {
|
||||
self.from_date = Some(from_date);
|
||||
}
|
||||
|
||||
pub fn with_from_date(mut self, from_date: String) -> Authorization {
|
||||
self.from_date = Some(from_date);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn from_date(&self) -> Option<&String> {
|
||||
self.from_date.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_from_date(&mut self) {
|
||||
self.from_date = None;
|
||||
}
|
||||
|
||||
pub fn set_user(&mut self, user: String) {
|
||||
self.user = Some(user);
|
||||
}
|
||||
|
||||
pub fn with_user(mut self, user: String) -> Authorization {
|
||||
self.user = Some(user);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn user(&self) -> Option<&String> {
|
||||
self.user.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_user(&mut self) {
|
||||
self.user = None;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* vote-rs API
|
||||
*
|
||||
* API for conducting electronic voting
|
||||
*
|
||||
* OpenAPI spec version: 0.0.1
|
||||
*
|
||||
* Generated by: https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Credentials {
|
||||
#[serde(rename = "username")]
|
||||
username: Option<String>,
|
||||
#[serde(rename = "password")]
|
||||
password: Option<String>
|
||||
}
|
||||
|
||||
impl Credentials {
|
||||
pub fn new() -> Credentials {
|
||||
Credentials {
|
||||
username: None,
|
||||
password: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_username(&mut self, username: String) {
|
||||
self.username = Some(username);
|
||||
}
|
||||
|
||||
pub fn with_username(mut self, username: String) -> Credentials {
|
||||
self.username = Some(username);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn username(&self) -> Option<&String> {
|
||||
self.username.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_username(&mut self) {
|
||||
self.username = None;
|
||||
}
|
||||
|
||||
pub fn set_password(&mut self, password: String) {
|
||||
self.password = Some(password);
|
||||
}
|
||||
|
||||
pub fn with_password(mut self, password: String) -> Credentials {
|
||||
self.password = Some(password);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn password(&self) -> Option<&String> {
|
||||
self.password.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_password(&mut self) {
|
||||
self.password = None;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,168 +0,0 @@
|
||||
/*
|
||||
* vote-rs API
|
||||
*
|
||||
* API for conducting electronic voting
|
||||
*
|
||||
* OpenAPI spec version: 0.0.1
|
||||
*
|
||||
* Generated by: https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Election {
|
||||
#[serde(rename = "id")]
|
||||
id: Option<String>,
|
||||
#[serde(rename = "username")]
|
||||
username: Option<String>,
|
||||
#[serde(rename = "name")]
|
||||
name: Option<String>,
|
||||
#[serde(rename = "description")]
|
||||
description: Option<String>,
|
||||
#[serde(rename = "start_date")]
|
||||
start_date: Option<String>,
|
||||
#[serde(rename = "end_date")]
|
||||
end_date: Option<String>,
|
||||
#[serde(rename = "items")]
|
||||
items: Option<Vec<::models::ElectionItem>>
|
||||
}
|
||||
|
||||
impl Election {
|
||||
pub fn new() -> Election {
|
||||
Election {
|
||||
id: None,
|
||||
username: None,
|
||||
name: None,
|
||||
description: None,
|
||||
start_date: None,
|
||||
end_date: None,
|
||||
items: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_id(&mut self, id: String) {
|
||||
self.id = Some(id);
|
||||
}
|
||||
|
||||
pub fn with_id(mut self, id: String) -> Election {
|
||||
self.id = Some(id);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn id(&self) -> Option<&String> {
|
||||
self.id.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_id(&mut self) {
|
||||
self.id = None;
|
||||
}
|
||||
|
||||
pub fn set_username(&mut self, username: String) {
|
||||
self.username = Some(username);
|
||||
}
|
||||
|
||||
pub fn with_username(mut self, username: String) -> Election {
|
||||
self.username = Some(username);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn username(&self) -> Option<&String> {
|
||||
self.username.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_username(&mut self) {
|
||||
self.username = None;
|
||||
}
|
||||
|
||||
pub fn set_name(&mut self, name: String) {
|
||||
self.name = Some(name);
|
||||
}
|
||||
|
||||
pub fn with_name(mut self, name: String) -> Election {
|
||||
self.name = Some(name);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<&String> {
|
||||
self.name.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_name(&mut self) {
|
||||
self.name = None;
|
||||
}
|
||||
|
||||
pub fn set_description(&mut self, description: String) {
|
||||
self.description = Some(description);
|
||||
}
|
||||
|
||||
pub fn with_description(mut self, description: String) -> Election {
|
||||
self.description = Some(description);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn description(&self) -> Option<&String> {
|
||||
self.description.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_description(&mut self) {
|
||||
self.description = None;
|
||||
}
|
||||
|
||||
pub fn set_start_date(&mut self, start_date: String) {
|
||||
self.start_date = Some(start_date);
|
||||
}
|
||||
|
||||
pub fn with_start_date(mut self, start_date: String) -> Election {
|
||||
self.start_date = Some(start_date);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn start_date(&self) -> Option<&String> {
|
||||
self.start_date.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_start_date(&mut self) {
|
||||
self.start_date = None;
|
||||
}
|
||||
|
||||
pub fn set_end_date(&mut self, end_date: String) {
|
||||
self.end_date = Some(end_date);
|
||||
}
|
||||
|
||||
pub fn with_end_date(mut self, end_date: String) -> Election {
|
||||
self.end_date = Some(end_date);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn end_date(&self) -> Option<&String> {
|
||||
self.end_date.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_end_date(&mut self) {
|
||||
self.end_date = None;
|
||||
}
|
||||
|
||||
pub fn set_items(&mut self, items: Vec<::models::ElectionItem>) {
|
||||
self.items = Some(items);
|
||||
}
|
||||
|
||||
pub fn with_items(mut self, items: Vec<::models::ElectionItem>) -> Election {
|
||||
self.items = Some(items);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn items(&self) -> Option<&Vec<::models::ElectionItem>> {
|
||||
self.items.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_items(&mut self) {
|
||||
self.items = None;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* vote-rs API
|
||||
*
|
||||
* API for conducting electronic voting
|
||||
*
|
||||
* OpenAPI spec version: 0.0.1
|
||||
*
|
||||
* Generated by: https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ElectionItem {
|
||||
#[serde(rename = "id")]
|
||||
id: Option<String>,
|
||||
#[serde(rename = "name")]
|
||||
name: Option<String>
|
||||
}
|
||||
|
||||
impl ElectionItem {
|
||||
pub fn new() -> ElectionItem {
|
||||
ElectionItem {
|
||||
id: None,
|
||||
name: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_id(&mut self, id: String) {
|
||||
self.id = Some(id);
|
||||
}
|
||||
|
||||
pub fn with_id(mut self, id: String) -> ElectionItem {
|
||||
self.id = Some(id);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn id(&self) -> Option<&String> {
|
||||
self.id.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_id(&mut self) {
|
||||
self.id = None;
|
||||
}
|
||||
|
||||
pub fn set_name(&mut self, name: String) {
|
||||
self.name = Some(name);
|
||||
}
|
||||
|
||||
pub fn with_name(mut self, name: String) -> ElectionItem {
|
||||
self.name = Some(name);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn name(&self) -> Option<&String> {
|
||||
self.name.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_name(&mut self) {
|
||||
self.name = None;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* vote-rs API
|
||||
*
|
||||
* API for conducting electronic voting
|
||||
*
|
||||
* OpenAPI spec version: 0.0.1
|
||||
*
|
||||
* Generated by: https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ElectionList {
|
||||
}
|
||||
|
||||
impl ElectionList {
|
||||
pub fn new() -> ElectionList {
|
||||
ElectionList {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* vote-rs API
|
||||
*
|
||||
* API for conducting electronic voting
|
||||
*
|
||||
* OpenAPI spec version: 0.0.1
|
||||
*
|
||||
* Generated by: https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct InlineResponse200 {
|
||||
#[serde(rename = "token")]
|
||||
token: Option<String>
|
||||
}
|
||||
|
||||
impl InlineResponse200 {
|
||||
pub fn new() -> InlineResponse200 {
|
||||
InlineResponse200 {
|
||||
token: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_token(&mut self, token: String) {
|
||||
self.token = Some(token);
|
||||
}
|
||||
|
||||
pub fn with_token(mut self, token: String) -> InlineResponse200 {
|
||||
self.token = Some(token);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn token(&self) -> Option<&String> {
|
||||
self.token.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_token(&mut self) {
|
||||
self.token = None;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* vote-rs API
|
||||
*
|
||||
* API for conducting electronic voting
|
||||
*
|
||||
* OpenAPI spec version: 0.0.1
|
||||
*
|
||||
* Generated by: https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct InlineResponse2001 {
|
||||
#[serde(rename = "token")]
|
||||
token: Option<String>
|
||||
}
|
||||
|
||||
impl InlineResponse2001 {
|
||||
pub fn new() -> InlineResponse2001 {
|
||||
InlineResponse2001 {
|
||||
token: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_token(&mut self, token: String) {
|
||||
self.token = Some(token);
|
||||
}
|
||||
|
||||
pub fn with_token(mut self, token: String) -> InlineResponse2001 {
|
||||
self.token = Some(token);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn token(&self) -> Option<&String> {
|
||||
self.token.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_token(&mut self) {
|
||||
self.token = None;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
mod authorization;
|
||||
pub use self::authorization::Authorization;
|
||||
mod credentials;
|
||||
pub use self::credentials::Credentials;
|
||||
mod election;
|
||||
pub use self::election::Election;
|
||||
mod election_item;
|
||||
pub use self::election_item::ElectionItem;
|
||||
mod election_list;
|
||||
pub use self::election_list::ElectionList;
|
||||
mod inline_response_200;
|
||||
pub use self::inline_response_200::InlineResponse200;
|
||||
mod inline_response_200_1;
|
||||
pub use self::inline_response_200_1::InlineResponse2001;
|
||||
mod user;
|
||||
pub use self::user::User;
|
||||
mod vote;
|
||||
pub use self::vote::Vote;
|
||||
mod vote_item;
|
||||
pub use self::vote_item::VoteItem;
|
||||
|
||||
// TODO(farcaller): sort out files
|
||||
pub struct File;
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* vote-rs API
|
||||
*
|
||||
* API for conducting electronic voting
|
||||
*
|
||||
* OpenAPI spec version: 0.0.1
|
||||
*
|
||||
* Generated by: https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct User {
|
||||
#[serde(rename = "id")]
|
||||
id: Option<String>,
|
||||
#[serde(rename = "username")]
|
||||
username: Option<String>,
|
||||
#[serde(rename = "password")]
|
||||
password: Option<String>
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub fn new() -> User {
|
||||
User {
|
||||
id: None,
|
||||
username: None,
|
||||
password: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_id(&mut self, id: String) {
|
||||
self.id = Some(id);
|
||||
}
|
||||
|
||||
pub fn with_id(mut self, id: String) -> User {
|
||||
self.id = Some(id);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn id(&self) -> Option<&String> {
|
||||
self.id.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_id(&mut self) {
|
||||
self.id = None;
|
||||
}
|
||||
|
||||
pub fn set_username(&mut self, username: String) {
|
||||
self.username = Some(username);
|
||||
}
|
||||
|
||||
pub fn with_username(mut self, username: String) -> User {
|
||||
self.username = Some(username);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn username(&self) -> Option<&String> {
|
||||
self.username.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_username(&mut self) {
|
||||
self.username = None;
|
||||
}
|
||||
|
||||
pub fn set_password(&mut self, password: String) {
|
||||
self.password = Some(password);
|
||||
}
|
||||
|
||||
pub fn with_password(mut self, password: String) -> User {
|
||||
self.password = Some(password);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn password(&self) -> Option<&String> {
|
||||
self.password.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_password(&mut self) {
|
||||
self.password = None;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
* vote-rs API
|
||||
*
|
||||
* API for conducting electronic voting
|
||||
*
|
||||
* OpenAPI spec version: 0.0.1
|
||||
*
|
||||
* Generated by: https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Vote {
|
||||
#[serde(rename = "authorization")]
|
||||
authorization: Option<::models::Authorization>,
|
||||
#[serde(rename = "userid")]
|
||||
userid: Option<String>,
|
||||
#[serde(rename = "data")]
|
||||
data: Option<Vec<::models::VoteItem>>
|
||||
}
|
||||
|
||||
impl Vote {
|
||||
pub fn new() -> Vote {
|
||||
Vote {
|
||||
authorization: None,
|
||||
userid: None,
|
||||
data: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_authorization(&mut self, authorization: ::models::Authorization) {
|
||||
self.authorization = Some(authorization);
|
||||
}
|
||||
|
||||
pub fn with_authorization(mut self, authorization: ::models::Authorization) -> Vote {
|
||||
self.authorization = Some(authorization);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn authorization(&self) -> Option<&::models::Authorization> {
|
||||
self.authorization.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_authorization(&mut self) {
|
||||
self.authorization = None;
|
||||
}
|
||||
|
||||
pub fn set_userid(&mut self, userid: String) {
|
||||
self.userid = Some(userid);
|
||||
}
|
||||
|
||||
pub fn with_userid(mut self, userid: String) -> Vote {
|
||||
self.userid = Some(userid);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn userid(&self) -> Option<&String> {
|
||||
self.userid.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_userid(&mut self) {
|
||||
self.userid = None;
|
||||
}
|
||||
|
||||
pub fn set_data(&mut self, data: Vec<::models::VoteItem>) {
|
||||
self.data = Some(data);
|
||||
}
|
||||
|
||||
pub fn with_data(mut self, data: Vec<::models::VoteItem>) -> Vote {
|
||||
self.data = Some(data);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn data(&self) -> Option<&Vec<::models::VoteItem>> {
|
||||
self.data.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_data(&mut self) {
|
||||
self.data = None;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* vote-rs API
|
||||
*
|
||||
* API for conducting electronic voting
|
||||
*
|
||||
* OpenAPI spec version: 0.0.1
|
||||
*
|
||||
* Generated by: https://github.com/swagger-api/swagger-codegen.git
|
||||
*/
|
||||
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct VoteItem {
|
||||
#[serde(rename = "item")]
|
||||
item: Option<::models::ElectionItem>,
|
||||
#[serde(rename = "value")]
|
||||
value: Option<f32>
|
||||
}
|
||||
|
||||
impl VoteItem {
|
||||
pub fn new() -> VoteItem {
|
||||
VoteItem {
|
||||
item: None,
|
||||
value: None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_item(&mut self, item: ::models::ElectionItem) {
|
||||
self.item = Some(item);
|
||||
}
|
||||
|
||||
pub fn with_item(mut self, item: ::models::ElectionItem) -> VoteItem {
|
||||
self.item = Some(item);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn item(&self) -> Option<&::models::ElectionItem> {
|
||||
self.item.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_item(&mut self) {
|
||||
self.item = None;
|
||||
}
|
||||
|
||||
pub fn set_value(&mut self, value: f32) {
|
||||
self.value = Some(value);
|
||||
}
|
||||
|
||||
pub fn with_value(mut self, value: f32) -> VoteItem {
|
||||
self.value = Some(value);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn value(&self) -> Option<&f32> {
|
||||
self.value.as_ref()
|
||||
}
|
||||
|
||||
pub fn reset_value(&mut self) {
|
||||
self.value = None;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,46 +6,46 @@
|
||||
<title>Create Election</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #1a1a1a;
|
||||
color: #f4f4f4;
|
||||
color: #9f9f9f;
|
||||
}
|
||||
.container {
|
||||
width: 400px;
|
||||
margin: 50px auto;
|
||||
padding: 20px;
|
||||
width: 25em;
|
||||
margin: 3.125em auto;
|
||||
padding: 1.25em;
|
||||
background-color: #2b2b2b;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 0.3125em;
|
||||
box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 1.25em;
|
||||
}
|
||||
input[type="text"],
|
||||
input[type="datetime-local"],
|
||||
textarea,
|
||||
input[type="submit"] {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
padding: 0.625em;
|
||||
margin-bottom: 0.625em;
|
||||
border: 0.0125em solid #868686;
|
||||
border-radius: 0.3125em;
|
||||
box-sizing: border-box;
|
||||
background-color: #2b2b2b;
|
||||
color: #f4f4f4;
|
||||
color: #9f9f9f;
|
||||
}
|
||||
textarea {
|
||||
height: 100px;
|
||||
height: 6.25em;
|
||||
background-color: #2b2b2b;
|
||||
color: #f4f4f4;
|
||||
color: #9f9f9f;
|
||||
}
|
||||
input[type="submit"] {
|
||||
background-color: #1a75ff; /* Darker blue */
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
border: 0px;
|
||||
}
|
||||
input[type="submit"]:hover {
|
||||
background-color: #145cbf; /* Even darker blue */
|
||||
|
138
src/templates/electionDetails.html
Normal file
138
src/templates/electionDetails.html
Normal file
@ -0,0 +1,138 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Election Details</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #1a1a1a;
|
||||
color: #9f9f9f;
|
||||
}
|
||||
h2 {
|
||||
grid-column: span 2;
|
||||
text-align: center;
|
||||
margin-bottom: 1.25em;
|
||||
}
|
||||
button {
|
||||
padding: 0.3125em 0.625em;
|
||||
border: none;
|
||||
border-radius: 0.3125em;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
width: 6em;
|
||||
}
|
||||
.detail {
|
||||
width: 48%; /* Adjust as needed */
|
||||
padding: 0.5em;
|
||||
background-color: #333; /* Dark gray */
|
||||
border-radius: 0.3125em;
|
||||
margin-bottom: 1em;
|
||||
box-sizing: border-box; /* Add this line */
|
||||
}
|
||||
|
||||
.detail.full-width {
|
||||
width: 100%; /* Full width */
|
||||
}
|
||||
.detail.full-heigth {
|
||||
height: 100%; /* Full height */
|
||||
min-height: 8.25em; /* Minimum height */
|
||||
}
|
||||
|
||||
.detail.dates {
|
||||
display: flex; /* Add this line */
|
||||
justify-content: space-between; /* Add this line */
|
||||
}
|
||||
|
||||
.detail label {
|
||||
font-weight: bold;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.detail span {
|
||||
color: #9f9f9f;
|
||||
}
|
||||
.go-btn {
|
||||
background-color: #4CAF50; /* Green */
|
||||
}
|
||||
.delete-btn {
|
||||
background-color: #f44336; /* Red */
|
||||
}
|
||||
.results-btn {
|
||||
background-color: #008CBA; /* Blue */
|
||||
}
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
width: 100%;
|
||||
margin-top: 1em;
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 50em;
|
||||
margin: 5em auto;
|
||||
padding: 3em;
|
||||
background-color: #2b2b2b;
|
||||
border-radius: 0.3125em;
|
||||
box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
#electionDetails {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h2>Election Details</h2>
|
||||
<div id="electionDetails">
|
||||
<!-- Election details will be inserted here dynamically -->
|
||||
</div>
|
||||
<div class="button-container">
|
||||
<button class="go-btn">Vote</button>
|
||||
<button class="delete-btn" onclick="confirmDelete()">Delete</button>
|
||||
<button class="results-btn" onclick="confirmResults()">Results</button>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function confirmDelete() {
|
||||
if (confirm("Are you sure you want to delete this election?")) {
|
||||
// Implement the logic to delete the election
|
||||
}
|
||||
}
|
||||
|
||||
function confirmResults() {
|
||||
if (confirm("Are you sure you want to view the results of this election?")) {
|
||||
// Implement the logic to view the results
|
||||
}
|
||||
}
|
||||
|
||||
// Dummy data for demonstration
|
||||
const election = { id: 1, name: "Election 1", username: "user", namespace: "namespace2", description: "Description 1", start_date: "2024-05-01T08:00", end_date: "2024-05-10T20:00" };
|
||||
|
||||
// Function to render election details
|
||||
function renderElectionDetails(election) {
|
||||
const detailsDiv = document.querySelector("#electionDetails");
|
||||
detailsDiv.innerHTML = `
|
||||
<div class="detail"><label>ID:</label> <span>${election.id}</span></div>
|
||||
<div class="detail"><label>User:</label> <span>${election.username}</span></div>
|
||||
<div class="detail"><label>Name:</label> <span>${election.name}</span></div>
|
||||
<div class="detail"><label>Namespace:</label> <span>${election.namespace}</span></div>
|
||||
<div class="detail full-width full-heigth"><label>Description:</label> <span>${election.description}</span></div>
|
||||
<div class="detail">Start Date:</label> <span>${new Date(election.start_date).toLocaleString()}</span></div>
|
||||
<div class="detail">End Date:</label> <span>${new Date(election.end_date).toLocaleString()}</span></div>
|
||||
`;
|
||||
}
|
||||
|
||||
// Initial rendering of election details
|
||||
renderElectionDetails(election);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -6,199 +6,108 @@
|
||||
<title>View Elections</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #1a1a1a;
|
||||
color: #f4f4f4;
|
||||
color: #9f9f9f;
|
||||
}
|
||||
.container {
|
||||
width: 800px;
|
||||
margin: 50px auto;
|
||||
padding: 20px;
|
||||
width: 60em;
|
||||
margin: 5em auto;
|
||||
padding: 3em;
|
||||
background-color: #2b2b2b;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 0.3125em;
|
||||
box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 1.25em;
|
||||
}
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
input[type="text"],
|
||||
input[type="submit"] {
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
background-color: #2b2b2b;
|
||||
color: #f4f4f4;
|
||||
}
|
||||
input[type="submit"] {
|
||||
background-color: #1a75ff; /* Darker blue */
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
input[type="submit"]:hover {
|
||||
background-color: #145cbf; /* Even darker blue */
|
||||
}
|
||||
table {
|
||||
#searchInput {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
color: #f4f4f4;
|
||||
}
|
||||
th, td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
th {
|
||||
background-color: #2b2b2b;
|
||||
}
|
||||
button {
|
||||
padding: 5px 10px;
|
||||
margin: 0 5px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
padding: 0.5em;
|
||||
margin-bottom: 4em;
|
||||
background-color: #363535;
|
||||
color: #9f9f9f;
|
||||
border: 0.0625em solid #9f9f9f;
|
||||
}
|
||||
|
||||
#searchForm {
|
||||
.card {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1em;
|
||||
background-color: #333;
|
||||
border-radius: 0.3125em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.go-btn {
|
||||
button {
|
||||
padding: 0.3125em 0.625em;
|
||||
margin: 0 0.3125em;
|
||||
border: none;
|
||||
border-radius: 0.3125em;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
.details-btn {
|
||||
background-color: #4CAF50; /* Green */
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
background-color: #f44336; /* Red */
|
||||
}
|
||||
|
||||
.results-btn {
|
||||
background-color: #008CBA; /* Blue */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h2>View Elections</h2>
|
||||
<form id="searchForm" action="#">
|
||||
<label for="search">Search by Name:</label>
|
||||
<input type="text" id="search" name="search" placeholder="Enter name to search">
|
||||
<input type="submit" value="Search">
|
||||
</form>
|
||||
<table id="electionsTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>User</th>
|
||||
<th>Namespace</th>
|
||||
<th>Description</th>
|
||||
<th>Start Date</th>
|
||||
<th>End Date</th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Election rows will be inserted here dynamically -->
|
||||
</tbody>
|
||||
</table>
|
||||
<input id="searchInput" type="text" placeholder="Search elections..." oninput="searchElections(this.value)">
|
||||
<div id="electionsContainer">
|
||||
<!-- Election cards will be inserted here dynamically -->
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
// Dummy data for demonstration
|
||||
const elections = [
|
||||
{ id: 1, name: "Election 1", username: "user", namespace: "namespace2", description: "Description 1", start_date: "2024-05-01T08:00", end_date: "2024-05-10T20:00" },
|
||||
{ id: 2, name: "Election 2", username: "user", namespace: "namespace", description: "Description 2", start_date: "2024-05-05T08:00", end_date: "2024-05-15T20:00" },
|
||||
{ id: 3, name: "Election 3", username: "user2", namespace: "namespace", description: "Description 3", start_date: "2024-05-10T08:00", end_date: "2024-05-20T20:00" }
|
||||
{ name: "Election 1", username: "user", namespace: "namespace2" },
|
||||
{ name: "Election 2", username: "user", namespace: "namespace" },
|
||||
{ name: "Election 3", username: "user2", namespace: "namespace" }
|
||||
];
|
||||
const currentUsername = "user";
|
||||
|
||||
// Function to render election rows
|
||||
function renderElections(elections) {
|
||||
const tableBody = document.querySelector("#electionsTable tbody");
|
||||
tableBody.innerHTML = "";
|
||||
const container = document.querySelector("#electionsContainer");
|
||||
container.innerHTML = "";
|
||||
elections.forEach(election => {
|
||||
const row = document.createElement("tr");
|
||||
row.innerHTML = `
|
||||
<td>${election.id}</td>
|
||||
<td>${election.name}</td>
|
||||
<td>${election.username}</td>
|
||||
<td>${election.namespace}</td>
|
||||
<td>${election.description}</td>
|
||||
<td>${new Date(election.start_date).toLocaleString()}</td>
|
||||
<td>${new Date(election.end_date).toLocaleString()}</td>
|
||||
<td><button class="go-btn" onclick="goToElection(${election.id})">Go to Election</button></td>
|
||||
${election.username === currentUsername ?
|
||||
`<td><button class="results-btn" onclick="if(confirm('Are you sure you want to view the results of this election?')) { viewResults(${election.id}) }">View Results</button></td>
|
||||
<td><button class="delete-btn" onclick="if(confirm('Are you sure you want to delete this election?')) { deleteElection(${election.id}) }">Delete</button></td>`
|
||||
: '<td></td><td></td>'}
|
||||
const card = document.createElement("div");
|
||||
card.className = "card";
|
||||
card.innerHTML = `
|
||||
<div>
|
||||
<h3>${election.name}</h3>
|
||||
<p>Created by ${election.username} in ${election.namespace}</p>
|
||||
</div>
|
||||
<div>
|
||||
<button class="details-btn" onclick="viewDetails('${election.name}')">Details</button>
|
||||
${election.username === currentUsername ?
|
||||
`<button class="delete-btn" onclick="if(confirm('Are you sure you want to delete this election?')) { deleteElection('${election.name}') }">Delete</button>`
|
||||
: ''}
|
||||
</div>
|
||||
`;
|
||||
tableBody.appendChild(row);
|
||||
container.appendChild(card);
|
||||
});
|
||||
}
|
||||
|
||||
// Get the search form and input field
|
||||
const searchForm = document.querySelector("#searchForm");
|
||||
const searchInput = document.querySelector("#search");
|
||||
|
||||
// Add an event listener to the form submission event
|
||||
searchForm.addEventListener("submit", function(event) {
|
||||
// Prevent the form from being submitted
|
||||
event.preventDefault();
|
||||
|
||||
// Get the search term
|
||||
const searchTerm = searchInput.value.trim().toLowerCase();
|
||||
|
||||
// Filter the elections based on the search term
|
||||
const filteredElections = elections.filter(election =>
|
||||
election.name.toLowerCase().includes(searchTerm) ||
|
||||
election.description.toLowerCase().includes(searchTerm) ||
|
||||
election.namespace.toLowerCase().includes(searchTerm) ||
|
||||
election.username.toLowerCase().includes(searchTerm)
|
||||
);
|
||||
|
||||
// Sort the elections so that the ones whose name includes the search term come first
|
||||
filteredElections.sort((a, b) => {
|
||||
const aNameIncludes = a.name.toLowerCase().includes(searchTerm);
|
||||
const bNameIncludes = b.name.toLowerCase().includes(searchTerm);
|
||||
|
||||
if (aNameIncludes && !bNameIncludes) {
|
||||
return -1;
|
||||
} else if (!aNameIncludes && bNameIncludes) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
|
||||
// Render the filtered elections
|
||||
renderElections(filteredElections);
|
||||
});
|
||||
|
||||
function goToElection(id) {
|
||||
// Implement the logic to go to the election page
|
||||
function searchElections(query) {
|
||||
const filtered = elections.filter(election => election.name.toLowerCase().includes(query.toLowerCase()));
|
||||
renderElections(filtered);
|
||||
}
|
||||
|
||||
function deleteElection(id) {
|
||||
function viewDetails(name) {
|
||||
// Implement the logic to view the details of the election
|
||||
}
|
||||
|
||||
function deleteElection(name) {
|
||||
// Implement the logic to delete the election
|
||||
}
|
||||
|
||||
function viewResults(id) {
|
||||
// Implement the logic to view the results of the election
|
||||
}
|
||||
|
||||
// Initial rendering of elections
|
||||
renderElections(elections);
|
||||
</script>
|
||||
</body>
|
||||
|
@ -6,40 +6,40 @@
|
||||
<title>Give Acces</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #1a1a1a;
|
||||
color: #f4f4f4;
|
||||
color: #9f9f9f;
|
||||
}
|
||||
.container {
|
||||
width: 300px;
|
||||
margin: 100px auto;
|
||||
padding: 20px;
|
||||
width: 20em;
|
||||
margin: 6.25em auto;
|
||||
padding: 2em;
|
||||
background-color: #2b2b2b;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 0.3125em;
|
||||
box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
input[type="text"],
|
||||
input[type="datetime-local"],
|
||||
input[type="submit"] {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
padding: 1em;
|
||||
margin-bottom: 0.625em;
|
||||
border: 0.0625em solid #9f9f9f;
|
||||
border-radius: 0.3125em;
|
||||
box-sizing: border-box;
|
||||
background-color: #2b2b2b;
|
||||
color: #f4f4f4;
|
||||
color: #9f9f9f;
|
||||
}
|
||||
input[type="submit"] {
|
||||
background-color: #1a75ff; /* Darker blue */
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
border: 0px;
|
||||
}
|
||||
input[type="submit"]:hover {
|
||||
background-color: #145cbf; /* Even darker blue */
|
||||
|
@ -6,40 +6,40 @@
|
||||
<title>Login</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #1a1a1a;
|
||||
color: #f4f4f4;
|
||||
color: #9f9f9f;
|
||||
}
|
||||
.container {
|
||||
width: 300px;
|
||||
margin: 100px auto;
|
||||
padding: 20px;
|
||||
width: 20em;
|
||||
margin: 6.25em auto;
|
||||
padding: 2em;
|
||||
background-color: #2b2b2b;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 0.3125em;
|
||||
box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 1.25em;
|
||||
}
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="submit"] {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
padding: 0.625em;
|
||||
margin-bottom: 0.625em;
|
||||
border: 0.0625em solid #9f9f9f;
|
||||
border-radius: 0.3125em;
|
||||
box-sizing: border-box;
|
||||
background-color: #2b2b2b;
|
||||
color: #f4f4f4;
|
||||
color: #9f9f9f;
|
||||
}
|
||||
input[type="submit"] {
|
||||
background-color: #1a75ff; /* Darker blue */
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
border: 0px;
|
||||
}
|
||||
input[type="submit"]:hover {
|
||||
background-color: #145cbf; /* Even darker blue */
|
||||
|
@ -6,48 +6,45 @@
|
||||
<title>Voting Page</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #1a1a1a;
|
||||
color: #f4f4f4;
|
||||
color: #9f9f9f;
|
||||
}
|
||||
.container {
|
||||
width: 600px;
|
||||
margin: 100px auto;
|
||||
padding: 20px;
|
||||
width: 50em;
|
||||
margin: 5em auto;
|
||||
padding: 2em;
|
||||
background-color: #2b2b2b;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 0.3125em;
|
||||
box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.election-card {
|
||||
margin-bottom: 20px;
|
||||
padding: 10px;
|
||||
margin-bottom: 1.25em;
|
||||
padding: 0.625em;
|
||||
background-color: #3b3b3b;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 0.3125em;
|
||||
box-shadow: 0 0.125em 0.3125em rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 1.25em;
|
||||
}
|
||||
.item {
|
||||
margin-bottom: 10px;
|
||||
margin-bottom: 0.625em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.item input[type="checkbox"] {
|
||||
margin-right: 10px;
|
||||
margin-right: 0.625em;
|
||||
background-color: #2b2b2b;
|
||||
color: #f4f4f4;
|
||||
color: #9f9f9f;
|
||||
}
|
||||
button {
|
||||
margin-left: 10px;
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
margin-left: 0.625em;
|
||||
padding: 0.625em;
|
||||
border: 0px;
|
||||
border-radius: 0.3125em;
|
||||
box-sizing: border-box;
|
||||
background-color: #1a75ff; /* Darker blue */
|
||||
color: white;
|
||||
|
Loading…
Reference in New Issue
Block a user