Fix CSV upload
continuous-integration/drone/push Build is passing Details

main
Julius 2022-12-23 20:22:38 +01:00
parent a38b47c223
commit 5303be8aca
Signed by: j00lz
GPG Key ID: AF241B0AA237BBA2
5 changed files with 483 additions and 270 deletions

653
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -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"

View File

@ -14,5 +14,3 @@ services:
restart: always
ports:
- "4567:8080"
links:
- db

View File

@ -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))

View File

@ -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);
}