Skip to main content

ravenrs_app_report/
lib.rs

1//! Reports of the lists of a business application: an action that lays out a list and shows it in
2//! the document viewer, from where it prints and exports.
3//!
4//! ```
5//! use ravenrs_app::{Application, EntityInfo, FieldInfo, FieldKind};
6//! use ravenrs_app_report::ReportModule;
7//! use ravenrs_app_ui::SystemModule;
8//!
9//! let account = EntityInfo::new("Account")
10//!     .navigation("Records")
11//!     .field(FieldInfo::new("id", FieldKind::Integer).key())
12//!     .field(FieldInfo::new("name", FieldKind::Text));
13//! let application = Application::builder("Accounts")
14//!     .module(SystemModule::new())
15//!     .module(ReportModule::new("Report"))
16//!     .entity(account)
17//!     .build()?;
18//! # let _ = application;
19//! # Ok::<(), ravenrs_app::ModelError>(())
20//! ```
21
22use std::rc::Rc;
23
24mod analytics;
25mod stored;
26
27pub use analytics::{ANALYTICS_DASHBOARD, ANALYTICS_TILE, AnalyticsModule, analytics_entities};
28pub use stored::{PT_BR, REPORT_DEFINITION, ReportWords, StoredReportsModule, report_entity};
29
30use ravenrs_app::{Action, ActionCategory, Module, TargetScope, ViewController, ViewKind};
31use ravenrs_app_ui::Session;
32use ravenrs_grid_export::document_of;
33use ravenrs_report_viewer::{DocumentViewer, ViewerState};
34use ravenrs_widgets::AnyView;
35
36/// The id of the action that shows the report of a list.
37pub const REPORT: &str = "ListReport";
38
39/// How tall the viewer is, inside its window.
40const VIEWER_HEIGHT: f32 = 640.0;
41
42struct ReportController {
43    caption: String,
44}
45
46impl ViewController for ReportController {
47    fn id(&self) -> &str {
48        "ListReport"
49    }
50
51    fn scope(&self) -> TargetScope {
52        TargetScope::any().view_kind(ViewKind::List)
53    }
54
55    fn actions(&self) -> Vec<Action> {
56        vec![
57            Action::simple(REPORT, self.caption.clone())
58                .category(ActionCategory::Export)
59                .icon("table")
60                .on_execute(|cx| {
61                    let session =
62                        Session::of(cx).ok_or_else(|| "this action needs the screens".to_owned())?;
63                    let view = cx.view.as_ref().ok_or_else(|| "this action needs a list".to_owned())?;
64                    let table = session.list_table(view).ok_or_else(|| view.id.clone())?;
65                    let title = table.title.clone();
66                    let document = Rc::new(document_of(&table));
67                    let state = ViewerState::new();
68                    session.present(title, move || {
69                        let viewer = DocumentViewer::new(document.clone(), &state);
70                        Box::new(ravenrs_widgets::ViewExt::height(viewer, VIEWER_HEIGHT)) as AnyView
71                    });
72                    Ok(())
73                }),
74        ]
75    }
76}
77
78/// Gives every list an action that shows it as a report.
79#[derive(Clone, Debug)]
80pub struct ReportModule {
81    caption: String,
82}
83
84impl ReportModule {
85    /// With this word on the action.
86    pub fn new(caption: impl Into<String>) -> Self {
87        Self { caption: caption.into() }
88    }
89}
90
91impl Module for ReportModule {
92    fn name(&self) -> &str {
93        "Reports"
94    }
95
96    fn view_controllers(&self) -> Vec<Box<dyn ViewController>> {
97        vec![Box::new(ReportController { caption: self.caption.clone() })]
98    }
99}