From 9f5460f27f07f15ed87a152bd685d7e1882f7736 Mon Sep 17 00:00:00 2001 From: Araozu Date: Tue, 14 Nov 2023 16:39:15 -0500 Subject: [PATCH] Scan UI changes. Rename files to be processed with unix timestamp --- backend/src/controller/scans/mod.rs | 70 ++++++++++++++++++++---- frontend/src/Scans/index.tsx | 82 ++++++++++++++++++++++++++--- 2 files changed, 134 insertions(+), 18 deletions(-) diff --git a/backend/src/controller/scans/mod.rs b/backend/src/controller/scans/mod.rs index 8b2552c..93d71e6 100644 --- a/backend/src/controller/scans/mod.rs +++ b/backend/src/controller/scans/mod.rs @@ -3,9 +3,11 @@ use printpdf::{Mm, PdfDocument}; use rocket::{http::Status, serde::json::Json}; use serde::Serialize; use std::{ + f32::consts::E, fs::{self, File}, io::BufWriter, path::PathBuf, + time::{SystemTime, UNIX_EPOCH}, }; const SCAN_PATH: &str = "/srv/srv/shares/eegsac/ESCANEOS/"; @@ -14,14 +16,13 @@ const SCAN_PATH: &str = "/srv/srv/shares/eegsac/ESCANEOS/"; #[derive(Serialize)] enum ScanInfo { /// The url has both DNI & id - Full(String, i32), + Full(String, i32, String), /// The url only has a DNI - Partial(String), + Partial(String, String), /// Te url is invalid Error(String), } - #[get("/scans/detect")] pub async fn detect_scans() -> (Status, Json>>) { let files = match get_valid_files() { @@ -50,6 +51,20 @@ fn get_valid_files() -> Result, String> { let mut result = Vec::::new(); + /* + TODO: The system will detect info from an image. + If successful, that image will be renamed to: + eeg_.jpg + and the timestamp will be sent to the frontend + along with the detected info. + + Then the frontend will send back the list of timestamps & info + and the backend will do the conversion. + + This way, we can ensure that only the images sent to & from the FE + can be converted. + */ + for p in paths { let p = match p { Ok(p) => p, @@ -83,13 +98,12 @@ fn get_valid_files() -> Result, String> { if filename.ends_with(".jpg") && filename.starts_with("eeg") { result.push(file_path); - } + }; } Ok(result) } - /// Detects the QR code data from every file fn get_details_from_paths(paths: Vec) -> Vec<(PathBuf, ScanInfo)> { paths @@ -99,7 +113,19 @@ fn get_details_from_paths(paths: Vec) -> Vec<(PathBuf, ScanInfo)> { } fn get_image_info(path: PathBuf) -> ScanInfo { - let img = image::open(path).unwrap(); + let img = image::open(&path).unwrap(); + + // get unix timestamp now + // Get current time in seconds + let current_time = SystemTime::now().duration_since(UNIX_EPOCH); + let current_time = match current_time { + Ok(t) => t, + Err(err) => { + eprintln!("Error obteniendo hora actual: {:?}", err); + return ScanInfo::Error("Error obteniendo hora actual: TIME WENT BACKWARDS.".into()); + } + }; + let current_ms = current_time.as_millis(); // Get width & height let width = img.width(); @@ -142,14 +168,36 @@ fn get_image_info(path: PathBuf) -> ScanInfo { let iid = url.chars().skip(equals_pos + 1).collect::(); match iid.parse() { - Ok(v) => ScanInfo::Full(dni, v), - Err(_) => ScanInfo::Error( - "QR invalido: El iid no es un número.".into(), - ), + Ok(v) => { + // Rename file + let mut new_path = path.clone(); + new_path.set_file_name(format!("eeg_{}.jpg", current_ms)); + + match fs::rename(path, new_path) { + Ok(_) => ScanInfo::Full(dni, v, current_ms.to_string()), + Err(err) => { + eprintln!("Error renombrando archivo: {:?}", err); + + ScanInfo::Error("Error renombrando archivo.".into()) + } + } + } + Err(_) => ScanInfo::Error("QR invalido: El iid no es un número.".into()), } } None => { - return ScanInfo::Partial(url.chars().skip(31).collect()); + // Rename file + let mut new_path = path.clone(); + new_path.set_file_name(format!("eeg_{}.jpg", current_ms)); + + match fs::rename(path, new_path) { + Ok(_) => ScanInfo::Partial(url.chars().skip(31).collect(), current_ms.to_string()), + Err(err) => { + eprintln!("Error renombrando archivo: {:?}", err); + + ScanInfo::Error("Error renombrando archivo.".into()) + } + } } } } diff --git a/frontend/src/Scans/index.tsx b/frontend/src/Scans/index.tsx index f0c2d43..8ef9c16 100644 --- a/frontend/src/Scans/index.tsx +++ b/frontend/src/Scans/index.tsx @@ -1,12 +1,52 @@ +import { For, createMemo, createSignal } from "solid-js"; import { FilledButton } from "../components/FilledButton"; import { FilledCard } from "../components/FilledCard"; +import { LoadingIcon } from "../icons/LoadingIcon"; import { MagnifyingGlassIcon } from "../icons/MagnifyingGlassIcon"; +import { LoadingStatus, useLoading } from "../utils/functions"; + +/** + * Represents the data about the scans that were detected. + * Serialization & Deserialization is done by the backend. + */ +interface ScanData { + Ok: Array<[string, ScanResult]>, +} + +type ScanResult = +| {Full: [string, number, string]} +| {Partial: [string, string]} +| {Error: string}; + +function dataFromScanResult(result: ScanResult) { + if ("Full" in result) { + return `DNI: ${result.Full[0]}, iid: ${result.Full[1]}`; + } else if ("Partial" in result) { + return `DNI: ${result.Partial}`; + } else if ("Error" in result) { + return `Error: ${result.Error}`; + } +} export function Scans() { + const {status, setStatus, error, setError} = useLoading(); + const [scanData, setScanData] = createSignal(null); + + const loading = createMemo(() => status() === LoadingStatus.Loading); + const detectScans = () => { + setStatus(LoadingStatus.Loading); + fetch(`${import.meta.env.VITE_BACKEND_URL}/api/scans/detect`) .then((res) => res.json()) - .then(console.log); + .then((data) => { + setStatus(LoadingStatus.Ok); + setScanData(data); + }) + .catch((err) => { + setStatus(LoadingStatus.Error); + console.error(err); + }); }; return ( @@ -63,8 +103,7 @@ export function Scans() { - -
+

Detectar escaneos @@ -86,16 +125,26 @@ export function Scans() {
+ + + + Detectar escaneos @@ -103,14 +152,33 @@ export function Scans() {

+ +

Escaneos detectados

-
- :D +
+ + {([path, result]) => ( +

+ + {path.substring(path.lastIndexOf("/") + 1)} + +
+ {dataFromScanResult(result)} +

+ )} +
+ +

+ Al convertir los escaneos a PDF, se eliminan los archivos JPG. +
+ La lista de escaneos a convertir puede haber cambiado desde + la última vez que se realizó la detección. +