Skip to content

Commit

Permalink
chore(dev): fix navigation; add report template appendices
Browse files Browse the repository at this point in the history
  • Loading branch information
esteinig committed Feb 14, 2025
1 parent 222c8b9 commit 45afbfb
Show file tree
Hide file tree
Showing 12 changed files with 310 additions and 103 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
testing/
.nextflow/
templates/report/report.pdf
cerebro/stack/report-wasm/tests/

# Triggered dev builds
trigger
Expand Down
26 changes: 18 additions & 8 deletions app/src/lib/components/data/sample/Test.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@
let reportTemplateSchema: ReportTemplateSchema = {
template_id: "",
template_name: "",
preamble: "",
introduction: "",
contact_name: "",
contact_email: "",
legal_disclaimer: "",
Expand All @@ -128,11 +130,7 @@
signatures: []
}
$: {
if (compiler) {
compileSVG(reportSchema);
}
}
$: if (compiler) compileSVG(reportSchema);
</script>

Expand All @@ -145,10 +143,23 @@
<form>
<div class="p-4">


<div id="reportIntroduction" class="py-8">
<p class="opacity-40 text-regular">Prelude text</p>
<div class="grid grid-cols-1 sm:grid-cols-1 md:grid-cols-1 gap-6 w-3/4 pt-4">
<label class="label">
<span class="text-xs opacity-60">Preamble</span>
<textarea class="textarea text-xs" rows="4" bind:value={reportTemplateSchema.preamble} placeholder="Preamble" required={false} />
</label>
<label class="label">
<span class="text-xs opacity-60">Introduction</span>
<textarea class="textarea text-xs" rows="4" bind:value={reportTemplateSchema.introduction} placeholder="Introduction" required={false} />
</label>
</div>
</div>

<div id="reportConfigurationAuthorisation" class="py-8">

<p class="opacity-40 text-regular">Contact details</p>

<div class="grid grid-cols-1 sm:grid-cols-1 md:grid-cols-2 gap-6 w-3/4 pb-12 pt-4">
<label class="label">
<span class="text-xs opacity-60">Name</span>
Expand All @@ -159,7 +170,6 @@
<input class="input text-xs" bind:value={reportTemplateSchema.contact_email} placeholder="Contact email" required={true} />
</label>
</div>

</div>

<div id="reportConfigurationAuthorisation" class="py-8">
Expand Down
2 changes: 2 additions & 0 deletions app/src/lib/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1867,6 +1867,8 @@ export type PatientResult = {
export type ReportTemplateSchema = {
template_id: string;
template_name: string;
preamble: string;
introduction: string;
contact_name: string;
contact_email: string;
legal_disclaimer: string;
Expand Down
6 changes: 4 additions & 2 deletions cerebro/stack/report-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ typst-svg = "0.12.0"
wasm-bindgen = "0.2.99"
serde-wasm-bindgen = "0.6.5"

# CLI feature
# Command-line interface feature
clap = { version = "4", optional = true, features = ["derive", "env", "unstable-styles", "wrap_help"] }
anstyle = { version = "1", optional = true }
toml = { version = "0.8.20", optional = true}
uuid = { version = "1.13.1", features = ["v4"] }


[features]
default = []
cli = ["clap", "anstyle"]
cli = ["clap", "anstyle", "toml"]
32 changes: 24 additions & 8 deletions cerebro/stack/report-wasm/src/compiler.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use chrono::{Datelike, Timelike};
use typst::layout::Abs;
use typst_pdf::PdfStandards;

#[cfg(feature = "cli")]
Expand All @@ -10,7 +11,7 @@ use wasm_bindgen::prelude::*;
use crate::report::ReportConfig;

use crate::world::SystemWorld;
use crate::report::{PathogenDetectionReport, ReportType, TemplateManager};
use crate::report::{PathogenDetectionReport, ReportType, TemplateFormat, TemplateManager};


#[cfg(feature = "cli")]
Expand All @@ -29,10 +30,16 @@ impl CommandLineReportCompiler {
report_type,
})
}
pub fn report(&mut self, config: &Path) -> anyhow::Result<String> {
pub fn report(&mut self, config: &Path, format: TemplateFormat) -> anyhow::Result<String> {

let report = match self.report_type {
ReportType::PathogenDetection => PathogenDetectionReport::from_json(config)?
ReportType::PathogenDetection => {
match format {
TemplateFormat::Json => PathogenDetectionReport::from_json(config)?,
TemplateFormat::Toml => PathogenDetectionReport::from_toml(config)?
}

}
};

// Render the template for the selected report type
Expand All @@ -41,10 +48,19 @@ impl CommandLineReportCompiler {
anyhow::anyhow!("failed to render report template: {}", e.to_string())
})
}
pub fn template(&self, text: &str, output: &Path) -> anyhow::Result<()> {
std::fs::write(output, text).map_err(|e| {
anyhow::anyhow!("failed to write template to file: {:?}", e)
})
pub fn typst(&mut self, text: &str, output: &Path) -> anyhow::Result<()> {

std::fs::write(output, text).map_err(|e| anyhow::anyhow!("Failed to write Typst file: {:?}", e))
}
pub fn svg(&mut self, text: &str, vpath: String, output: &Path) -> anyhow::Result<()> {

let document = self.world.compile(text.to_string(), vpath, None)?;

let padding = Abs::pt(12.0);

let svg_data = typst_svg::svg_merged(&document, padding);

std::fs::write(output, svg_data).map_err(|e| anyhow::anyhow!("Failed to write SVG file: {:?}", e))
}
pub fn pdf(&mut self, text: &str, vpath: String, output: &Path) -> anyhow::Result<()> {

Expand All @@ -67,7 +83,7 @@ impl CommandLineReportCompiler {
let pdf_data = typst_pdf::pdf(&document, &options)
.map_err(|_| anyhow::anyhow!("failed to create PDF with Typst"))?;

std::fs::write(output, pdf_data).map_err(|e| anyhow::anyhow!("Failed to write PDF: {:?}", e))
std::fs::write(output, pdf_data).map_err(|e| anyhow::anyhow!("Failed to write PDF file: {:?}", e))
}
}
}
Expand Down
Empty file.
78 changes: 47 additions & 31 deletions cerebro/stack/report-wasm/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ mod report;
#[cfg(feature = "cli")]
mod world;


#[cfg(feature = "cli")]
use std::path::PathBuf;

#[cfg(feature = "cli")]
use clap::{Args, Parser, Subcommand};
use report::TemplateFormat;
#[cfg(feature = "cli")]
use report::ReportType;

use report::{ReportFormat, ReportType, PathogenDetectionReport};
#[cfg(feature = "cli")]
use compiler::CommandLineReportCompiler;

#[cfg(feature = "cli")]
/// Cerebro: clinical report compiler for production
Expand All @@ -31,37 +31,44 @@ pub struct Cli {
#[cfg(feature = "cli")]
#[derive(Debug, Subcommand)]
pub enum Commands {
/// Compile a report from configuration file (.json)
/// Compile a report (JSON | TOML)
Compile(CompileArgs),
/// Compile a report from configuration file (.json)
/// Output a report template (JSON | TOML)
Template(TemplateArgs),
}

#[cfg(feature = "cli")]
#[derive(Debug, Args)]
pub struct CompileArgs {
/// Report template
#[clap(long, short = 'r')]
pub report: ReportType,
/// Report template configuration (.json)
/// Report output file
#[clap(long, short = 'o')]
pub output: PathBuf,
/// Report configuration
#[clap(long, short = 'c')]
pub config: PathBuf,
/// Compile report to PDF (.pdf)
#[clap(long, short = 'p')]
pub pdf: Option<PathBuf>,
/// Compile report to template (.typ)
#[clap(long, short = 'o')]
pub template: Option<PathBuf>,
/// Report template format
#[clap(long, short = 't', default_value="json")]
pub template: TemplateFormat,
/// Output format
#[clap(long, short = 'f', default_value="pdf")]
pub format: ReportFormat,
/// Report type
#[clap(long, short = 'r', default_value="pathogen-detection")]
pub report: ReportType,
}

#[cfg(feature = "cli")]
#[derive(Debug, Args)]
pub struct TemplateArgs {
/// Report template
#[clap(long, short = 'r')]
/// Report template output (.json | .toml)
#[clap(long, short = 'o')]
pub output: PathBuf,
/// Report template format
#[clap(long, short = 't', default_value="json")]
pub template: TemplateFormat,
/// Report type
#[clap(long, short = 'r', default_value="pathogen-detection")]
pub report: ReportType,
/// Report configuration template (.json)
#[clap(long, short = 'c')]
pub config: PathBuf,
}

#[cfg(feature = "cli")]
Expand All @@ -88,23 +95,32 @@ fn main() -> anyhow::Result<()> {

match cli.command {
Commands::Compile( args ) => {
let mut compiler = crate::compiler::CommandLineReportCompiler::new(

let mut compiler = CommandLineReportCompiler::new(
String::from("/"), args.report
)?;

let report = compiler.report(&args.config)?;

if let Some(ref path) = args.pdf {
compiler.pdf(&report, "pdf.typ".to_string(), &path)?;
}
if let Some(ref path) = args.template {
compiler.template(&report, path)?;
let report = compiler.report(&args.config, args.template)?;

match args.format {
ReportFormat::Pdf => {
compiler.pdf(&report, String::from("/report"), &args.output)?;
},
ReportFormat::Svg => {
compiler.svg(&report, String::from("/report"), &args.output)?;
},
ReportFormat::Typst => {
compiler.typst(&report, &args.output)?;
},
}
},
Commands::Template( args ) => {
match args.report {
ReportType::PathogenDetection => {
crate::report::PathogenDetectionReport::default().to_json_file(&args.config)?;
match args.template {
TemplateFormat::Json => PathogenDetectionReport::default().to_json(&args.output)?,
TemplateFormat::Toml => PathogenDetectionReport::default().to_toml(&args.output)?,
}
}
}
}
Expand All @@ -116,4 +132,4 @@ fn main() -> anyhow::Result<()> {
#[cfg(not(feature = "cli"))]
fn main() {
eprintln!("Command-line interface feature is not enabled. You can enable it with: `--features cli`.");
}
}
Loading

0 comments on commit 45afbfb

Please sign in to comment.