This commit is contained in:
parent
a38b47c223
commit
5303be8aca
653
Cargo.lock
generated
653
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -13,7 +13,8 @@ sqlx = { version = "0.5.13", features = ["runtime-tokio-rustls", "postgres", "ch
|
|||
tokio = { version = "1.19.2", features = ["full"] }
|
||||
uuid = { version = "0.8", features = ["serde", "v4"] }
|
||||
tower-http = { version = "0.3.4", features = ["fs", "trace"] }
|
||||
serde = { version = "1.0.137", features = ["derive"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
rand = "0.8.5"
|
||||
argon2 = "0.4.0"
|
||||
axum-extra = { version = "0.3.4", features = ["cookie"] }
|
||||
regex = "1.7.0"
|
||||
|
|
|
@ -14,5 +14,3 @@ services:
|
|||
restart: always
|
||||
ports:
|
||||
- "4567:8080"
|
||||
links:
|
||||
- db
|
||||
|
|
46
src/main.rs
46
src/main.rs
|
@ -13,6 +13,7 @@ use axum::{
|
|||
use axum_extra::extract::{cookie::Cookie, CookieJar};
|
||||
use db::{Database, Db, Party, Ticket, User};
|
||||
use rand::Rng;
|
||||
use regex::Regex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::postgres::PgPoolOptions;
|
||||
use tower_http::services::ServeDir;
|
||||
|
@ -405,6 +406,50 @@ async fn stats(
|
|||
Json(StatResponse { total, inside })
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct CSVScan {
|
||||
party: i32,
|
||||
csv: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct CSVScanResponse {
|
||||
scanned: i32,
|
||||
with_coins: i32,
|
||||
total: i32,
|
||||
}
|
||||
|
||||
async fn tickets_csv(
|
||||
_: User,
|
||||
Extension(pool): Extension<Database>,
|
||||
Json(csv_scan): Json<CSVScan>,
|
||||
) -> impl IntoResponse {
|
||||
let llnr_regex = Regex::new(r".*(\d{6}).*").unwrap();
|
||||
let coins_regex = Regex::new(r".*COINS.*").unwrap();
|
||||
let party = csv_scan.party;
|
||||
let mut total = 0;
|
||||
let mut with_coins = 0;
|
||||
let mut scanned = 0;
|
||||
for l in csv_scan.csv.lines() {
|
||||
total += 1;
|
||||
if let Some(captures) = llnr_regex.captures(l) {
|
||||
if let Some(llnr) = captures.get(1) {
|
||||
let has_coins = coins_regex.is_match(l);
|
||||
pool.add_ticket(party, llnr.as_str(), has_coins).await;
|
||||
scanned += 1;
|
||||
if has_coins {
|
||||
with_coins += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Json(CSVScanResponse {
|
||||
scanned,
|
||||
with_coins,
|
||||
total,
|
||||
})
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let url = if let Some(url) = std::env::var("DATABASE_URL").ok() {
|
||||
|
@ -438,6 +483,7 @@ async fn main() {
|
|||
.route("/party/:id/export", get(export_party))
|
||||
.route("/party/:id/lijst", get(party_goers))
|
||||
.route("/api/ticket", get(get_tickets).post(scan_card))
|
||||
.route("/api/csv", post(tickets_csv))
|
||||
.route("/api/ticket/delete", post(remove_ticket))
|
||||
.route("/api/party", get(get_party_by_name).post(create_party))
|
||||
.route("/api/party/list", get(get_parties))
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
onclick="reselect()">Start
|
||||
Scannen</button> </p>
|
||||
<div class="columns">
|
||||
<video autoplay playsinline controls="false" class="column col-12"></video>
|
||||
<video autoplay playsinline controls="false" class="column col-12" id="webcam_holder" hidden></video>
|
||||
</div>
|
||||
<h4><span id="last-scanned">Nog geen gescand</span></h4>
|
||||
<h3><span id="scan-status">Nog geen gescand</span></h3>
|
||||
|
@ -184,6 +184,7 @@
|
|||
const videoSelect = document.querySelector("select#videoSource");
|
||||
|
||||
function start_scanning() {
|
||||
document.getElementById("webcam_holder").hidden = false;
|
||||
navigator.mediaDevices
|
||||
.enumerateDevices()
|
||||
.then(gotDevices)
|
||||
|
@ -272,30 +273,28 @@
|
|||
function upload_csv() {
|
||||
let file = document.getElementById("file-selector").files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
let num = 0;
|
||||
reader.onload = (evt) => {
|
||||
let result = evt.target.result;
|
||||
result = result.replace("\r\n", "\n").replace("\r", "\n");
|
||||
for (let line of result.split("\n")) {
|
||||
let llnr_a = "";
|
||||
let coins = false;
|
||||
for (let llnr of line.split(",")) {
|
||||
if (llnr.length === 6 && !isNaN(llnr)) {
|
||||
llnr_a = llnr;
|
||||
}
|
||||
if (llnr === "COINS") {
|
||||
coins = true;
|
||||
}
|
||||
}
|
||||
console.log(llnr_a, coins);
|
||||
if (llnr_a !== "") {
|
||||
num++;
|
||||
scan_ticket(llnr_a, coins);
|
||||
}
|
||||
}
|
||||
document.getElementById("import-result").innerHTML = `${num} leerlingen geïmporteerd!`
|
||||
}
|
||||
set_scan_status("CSV uploaden...");
|
||||
// upload file contents to server
|
||||
let reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
let contents = e.target.result;
|
||||
let party_id = +document.getElementById("party_id").value;
|
||||
fetch("/api/csv", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({
|
||||
party: party_id,
|
||||
csv: contents,
|
||||
})
|
||||
}).then(function (response) {
|
||||
return response.json();
|
||||
}).then(function (data) {
|
||||
console.log(data)
|
||||
set_scan_status(`CSV geupload: ${data.total} regels, waarvan ${data.scanned} leerlingen, ${data.with_coins} met muntjes`);
|
||||
});
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue