Export result to txt/docx
This commit is contained in:
3
src-tauri/.gitignore
vendored
3
src-tauri/.gitignore
vendored
@@ -5,3 +5,6 @@
|
||||
# Generated by Tauri
|
||||
# will have schema files for capabilities auto-completion
|
||||
/gen/schemas
|
||||
|
||||
|
||||
schedule.*
|
||||
89
src-tauri/Cargo.lock
generated
89
src-tauri/Cargo.lock
generated
@@ -552,6 +552,12 @@ dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "color_quant"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||
|
||||
[[package]]
|
||||
name = "combine"
|
||||
version = "4.6.7"
|
||||
@@ -846,6 +852,21 @@ dependencies = [
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "docx-rs"
|
||||
version = "0.4.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f21be13b97bd2924f30323d674f5a8db382964972825abd93f30d08f21dad98"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"image",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 1.0.69",
|
||||
"xml-rs",
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dpi"
|
||||
version = "0.1.2"
|
||||
@@ -1344,6 +1365,16 @@ dependencies = [
|
||||
"wasip2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gif"
|
||||
version = "0.13.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ae047235e33e2829703574b54fdec96bfbad892062d97fed2f76022287de61b"
|
||||
dependencies = [
|
||||
"color_quant",
|
||||
"weezl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gio"
|
||||
version = "0.18.4"
|
||||
@@ -1769,6 +1800,22 @@ dependencies = [
|
||||
"icu_properties",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.24.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder",
|
||||
"color_quant",
|
||||
"gif",
|
||||
"jpeg-decoder",
|
||||
"num-traits",
|
||||
"png",
|
||||
"tiff",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
@@ -1896,6 +1943,12 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
|
||||
|
||||
[[package]]
|
||||
name = "jpeg-decoder"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00810f1d8b74be64b13dbf3db89ac67740615d6c891f0e7b6179326533011a07"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.83"
|
||||
@@ -3170,6 +3223,7 @@ name = "rota"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"docx-rs",
|
||||
"itertools",
|
||||
"log",
|
||||
"rand 0.9.2",
|
||||
@@ -4163,6 +4217,17 @@ dependencies = [
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiff"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"jpeg-decoder",
|
||||
"weezl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.44"
|
||||
@@ -4817,6 +4882,12 @@ dependencies = [
|
||||
"windows-core 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "weezl"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
@@ -5357,6 +5428,12 @@ dependencies = [
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xml-rs"
|
||||
version = "0.8.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f"
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.8.1"
|
||||
@@ -5515,6 +5592,18 @@ dependencies = [
|
||||
"syn 2.0.111",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "0.6.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"crc32fast",
|
||||
"crossbeam-utils",
|
||||
"flate2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant"
|
||||
version = "5.8.0"
|
||||
|
||||
@@ -28,3 +28,4 @@ rstest = "0.26.1"
|
||||
tauri-plugin-log = "2"
|
||||
log = "0.4.29"
|
||||
rand = "0.9.2"
|
||||
docx-rs = "0.4.18"
|
||||
|
||||
@@ -1,21 +1,18 @@
|
||||
// here lies the logic for the export of the final schedule into docx/pdf formats
|
||||
|
||||
use std::{fs::File, io::Write};
|
||||
|
||||
use docx_rs::{Docx, Paragraph, Run, RunFonts, Table, TableCell, TableRow};
|
||||
use log::info;
|
||||
|
||||
use crate::{
|
||||
config::UserConfig,
|
||||
schedule::MonthlySchedule,
|
||||
slot::{month_to_greek, weekday_to_greek, Day, ShiftPosition, Slot},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FileType {
|
||||
Txt,
|
||||
Json,
|
||||
Csv,
|
||||
Doc,
|
||||
Pdf,
|
||||
Docx,
|
||||
}
|
||||
|
||||
pub trait Export {
|
||||
@@ -26,10 +23,7 @@ impl Export for MonthlySchedule {
|
||||
fn export(&self, file_type: FileType, config: &UserConfig) {
|
||||
match file_type {
|
||||
FileType::Txt => self.export_as_txt(config),
|
||||
FileType::Csv => self.export_as_csv(config),
|
||||
FileType::Json => self.export_as_json(config),
|
||||
FileType::Doc => self.export_as_doc(config),
|
||||
FileType::Pdf => self.export_as_pdf(config),
|
||||
FileType::Docx => self.export_as_doc(config),
|
||||
};
|
||||
|
||||
// TODO: make this env var from a config file? Option to change this in-app
|
||||
@@ -49,32 +43,155 @@ impl MonthlySchedule {
|
||||
.write_all(self.pretty_print(config).as_bytes())
|
||||
.expect("Failed to write to buffer");
|
||||
|
||||
writer
|
||||
.write_all(self.report(config).as_bytes())
|
||||
.expect("Failed to write to buffer");
|
||||
|
||||
writer.flush().expect("Failed to flush buffer");
|
||||
info!("im here");
|
||||
"ok".to_string()
|
||||
}
|
||||
|
||||
pub fn export_as_csv(&self, config: &UserConfig) -> String {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn export_as_json(&self, config: &UserConfig) -> String {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn export_as_doc(&self, config: &UserConfig) -> String {
|
||||
todo!()
|
||||
let path = std::path::Path::new("./schedule.docx");
|
||||
let file = std::fs::File::create(path).unwrap();
|
||||
|
||||
let header = Table::new(vec![
|
||||
TableRow::new(vec![TableCell::new().add_paragraph(
|
||||
Paragraph::new()
|
||||
.add_run(Run::new().bold().add_text("Εφημερίες Ακτινολογικό"))
|
||||
.fonts(RunFonts::new().ascii("Arial")),
|
||||
)]),
|
||||
TableRow::new(vec![TableCell::new().add_paragraph(
|
||||
Paragraph::new()
|
||||
.add_run(Run::new().bold().add_text(format!(
|
||||
"Μήνας {} {}",
|
||||
month_to_greek(config.month.number_from_month()),
|
||||
config.year
|
||||
)))
|
||||
.fonts(RunFonts::new().ascii("Arial")),
|
||||
)]),
|
||||
TableRow::new(vec![TableCell::new().add_paragraph(
|
||||
Paragraph::new()
|
||||
.add_run(Run::new().bold().add_text(""))
|
||||
.fonts(RunFonts::new().ascii("Arial")),
|
||||
)]),
|
||||
TableRow::new(vec![TableCell::new().add_paragraph(
|
||||
Paragraph::new()
|
||||
.add_run(
|
||||
Run::new()
|
||||
.bold()
|
||||
.add_text("ΠΑΝΕΠΙΣΤΗΜΙΑΚΟ ΓΕΝΙΚΟ ΝΟΣΟΚΟΜΕΙΟ ΙΩΑΝΝΙΝΩΝ"),
|
||||
)
|
||||
.fonts(RunFonts::new().ascii("Arial")),
|
||||
)]),
|
||||
]);
|
||||
|
||||
let mut doc = Docx::new().add_table(header);
|
||||
|
||||
let mut residents_table = Table::new(vec![]);
|
||||
|
||||
for d in 1..=config.total_days() {
|
||||
let day = Day(d);
|
||||
let is_weekend = day.is_weekend(config.month.number_from_month(), config.year);
|
||||
let slot_first = Slot::new(Day(d), ShiftPosition::First);
|
||||
let slot_first_res_id = self.get_resident_id(&slot_first);
|
||||
let res_name_1 = config
|
||||
.residents
|
||||
.iter()
|
||||
.find(|r| Some(&r.id) == slot_first_res_id)
|
||||
.map(|r| r.name.as_str())
|
||||
.unwrap();
|
||||
|
||||
let res_name_2 = if day.is_open_shift() {
|
||||
let slot_second = Slot::new(Day(d), ShiftPosition::Second);
|
||||
let slot_second_res_id = self.get_resident_id(&slot_second);
|
||||
config
|
||||
.residents
|
||||
.iter()
|
||||
.find(|r| Some(&r.id) == slot_second_res_id)
|
||||
.map(|r| r.name.as_str())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let make_run = |text: &str| {
|
||||
let mut run = Run::new().add_text(text);
|
||||
if is_weekend {
|
||||
run = run.bold();
|
||||
}
|
||||
run
|
||||
};
|
||||
|
||||
let residents_table_row = TableRow::new(vec![
|
||||
TableCell::new().add_paragraph(
|
||||
Paragraph::new()
|
||||
.add_run(make_run(&format!("{d}")))
|
||||
.fonts(RunFonts::new().ascii("Arial")),
|
||||
),
|
||||
TableCell::new().add_paragraph(
|
||||
Paragraph::new()
|
||||
.add_run(make_run(weekday_to_greek(
|
||||
Day(d).weekday(config.month.number_from_month(), config.year),
|
||||
)))
|
||||
.fonts(RunFonts::new().ascii("Arial")),
|
||||
),
|
||||
TableCell::new().add_paragraph(
|
||||
Paragraph::new()
|
||||
.add_run(make_run(res_name_1))
|
||||
.fonts(RunFonts::new().ascii("Arial")),
|
||||
),
|
||||
TableCell::new().add_paragraph(
|
||||
Paragraph::new()
|
||||
.add_run(make_run(res_name_2.unwrap_or("")))
|
||||
.fonts(RunFonts::new().ascii("Arial")),
|
||||
),
|
||||
]);
|
||||
|
||||
residents_table = residents_table.add_row(residents_table_row);
|
||||
}
|
||||
|
||||
pub fn export_as_pdf(&self, config: &UserConfig) -> String {
|
||||
todo!()
|
||||
doc = doc.add_table(residents_table);
|
||||
|
||||
doc.build().pack(file).unwrap();
|
||||
|
||||
"just a string".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rstest::rstest;
|
||||
use rstest::{fixture, rstest};
|
||||
|
||||
use crate::{
|
||||
config::UserConfig, generator::backtracking, resident::Resident, schedule::MonthlySchedule,
|
||||
slot::Slot,
|
||||
};
|
||||
|
||||
#[fixture]
|
||||
fn schedule() -> MonthlySchedule {
|
||||
MonthlySchedule::new()
|
||||
}
|
||||
|
||||
#[fixture]
|
||||
fn config() -> UserConfig {
|
||||
let mut config = UserConfig::default().with_residents(vec![
|
||||
Resident::new("1", "Στέφανος"),
|
||||
Resident::new("2", "Ιορδάνης"),
|
||||
Resident::new("3", "Μαρία"),
|
||||
Resident::new("4", "Βεατρίκη"),
|
||||
Resident::new("5", "Τάκης"),
|
||||
Resident::new("6", "Μάκης"),
|
||||
]);
|
||||
config.calculate_workload_limits();
|
||||
config.calculate_holiday_limits();
|
||||
config.calculate_shift_type_fairness();
|
||||
config
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
pub fn xxxy() {}
|
||||
pub fn test_export_as_doc(mut schedule: MonthlySchedule, config: UserConfig) {
|
||||
backtracking(&mut schedule, Slot::default(), &config);
|
||||
schedule.export_as_doc(&config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ fn generate(config: UserConfigDTO, state: tauri::State<'_, AppState>) -> Monthly
|
||||
fn export(config: UserConfigDTO, state: tauri::State<'_, AppState>) {
|
||||
let config = UserConfig::from_dto(config);
|
||||
let schedule = state.schedule.lock().unwrap();
|
||||
schedule.export(FileType::Txt, &config);
|
||||
schedule.export(FileType::Docx, &config);
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
|
||||
@@ -128,6 +128,36 @@ pub enum ShiftPosition {
|
||||
Second,
|
||||
}
|
||||
|
||||
pub fn weekday_to_greek(weekday: Weekday) -> &'static str {
|
||||
match weekday {
|
||||
Weekday::Mon => "Δευτέρα",
|
||||
Weekday::Tue => "Τρίτη",
|
||||
Weekday::Wed => "Τετάρτη",
|
||||
Weekday::Thu => "Πέμπτη",
|
||||
Weekday::Fri => "Παρασκευή",
|
||||
Weekday::Sat => "Σάββατο",
|
||||
Weekday::Sun => "Κυριακή",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn month_to_greek(month: u32) -> &'static str {
|
||||
match month {
|
||||
1 => "Ιανουάριος",
|
||||
2 => "Φεβρουάριος",
|
||||
3 => "Μάρτιος",
|
||||
4 => "Απρίλιος",
|
||||
5 => "Μάιος",
|
||||
6 => "Ιούνιος",
|
||||
7 => "Ιούλιος",
|
||||
8 => "Αύγουστος",
|
||||
9 => "Σεπτέμβριος",
|
||||
10 => "Οκτώβριος",
|
||||
11 => "Νοέμβριος",
|
||||
12 => "Δεκέμβριος",
|
||||
_ => panic!("Unable to find translation for month {}", month),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rstest::rstest;
|
||||
|
||||
Reference in New Issue
Block a user