gitlab_time_report_cli/
print_table.rs

1//! Contains functions to print the generated tables from the library to the console.
2
3#![cfg(not(tarpaulin_include))]
4
5use cli_table::format::Justify;
6use cli_table::{Cell, CellStruct, Style, Table, TableStruct, print_stdout};
7use gitlab_time_report::model::{Label, TimeLog};
8use gitlab_time_report::tables;
9use regex::Regex;
10use std::collections::HashSet;
11
12/// Create a table from cells and column titles.
13fn create_table(table_data: Vec<Vec<CellStruct>>, column_titles: &[&str]) -> TableStruct {
14    let titles: Vec<_> = column_titles
15        .iter()
16        .map(|title| title.cell().bold(true))
17        .collect();
18    table_data.table().title(titles)
19}
20
21/// Print a table and handle errors
22fn print_table(table: TableStruct) {
23    print_stdout(table).unwrap_or_else(|err| {
24        eprintln!("Error printing table: {err}");
25        std::process::exit(4);
26    });
27}
28
29/// Transform a `Vec<Vec<String>>` from the Library to a `Vec<Vec<CellStruct>>`
30/// used by the `cli_table` crate. The first column is left-aligned, all others right-aligned.
31fn to_cell_vec(table: Vec<Vec<String>>) -> Vec<Vec<CellStruct>> {
32    let is_duration = Regex::new(r"^[0-9]{2,}h [0-9]{2}m$").expect("Regex pattern should compile");
33    table
34        .into_iter()
35        .map(|row| {
36            row.into_iter()
37                // Check if the cell is a duration cell
38                .map(|cell| match is_duration.is_match(&cell) {
39                    true => cell.cell().justify(Justify::Right),
40                    false => cell.cell(),
41                })
42                .collect()
43        })
44        .collect()
45}
46
47/// Print a table with the total time spent per selected label.
48pub fn print_total_time_by_label(
49    time_logs: &[TimeLog],
50    label_filter: Option<&HashSet<String>>,
51    label_others: Option<&Label>,
52) {
53    let (table_data, table_header) =
54        tables::populate_table_timelogs_by_label(time_logs, label_filter, label_others);
55    let table_data_cells = to_cell_vec(table_data);
56
57    let table = create_table(table_data_cells, table_header);
58    println!("\nTime Spent per Label:");
59    print_table(table);
60}
61
62/// Print a table with the total time spent per milestone.
63pub fn print_total_time_by_milestone(time_logs: &[TimeLog]) {
64    let (table_data, table_header) = tables::populate_table_timelogs_by_milestone(time_logs);
65    let table_data_cells = to_cell_vec(table_data);
66
67    let table = create_table(table_data_cells, table_header);
68    println!("\nTime Spent per Milestone:");
69    print_table(table);
70}
71
72/// Print a table of today's, yesterday's, this week's and this month's time spent by user.
73pub fn print_timelogs_in_timeframes_by_user(time_logs: &[TimeLog]) {
74    let (table_data, table_header) =
75        tables::populate_table_timelogs_in_timeframes_by_user(time_logs);
76
77    // Convert the returned data to the correct format used with cli_table.
78    let table_data_cells = to_cell_vec(table_data);
79
80    let table = create_table(table_data_cells, table_header);
81    println!("\nTime Spent per User:");
82    print_table(table);
83}
84
85/// Print a table of today's time logs.
86pub fn print_todays_timelogs(time_logs: &[TimeLog]) {
87    let (table_data, table_header) = tables::populate_table_todays_timelogs(time_logs);
88    println!("\nToday's Time Logs:");
89    if table_data.is_empty() {
90        println!("No time logs found for today.");
91        return;
92    }
93    let table_data_cells = to_cell_vec(table_data);
94    let table = create_table(table_data_cells, table_header);
95    print_table(table);
96}