Skip to content

Commit

Permalink
Options to select team and have a default one
Browse files Browse the repository at this point in the history
  • Loading branch information
alexsnaps committed Aug 16, 2022
1 parent c0be770 commit ef9fc7a
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 41 deletions.
23 changes: 23 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,26 @@
use serde::Deserialize;
use std::collections::HashMap;

const DEFAULT_DATE_FMT: &str = "%a %b %d %H:%M";

#[derive(Deserialize)]
pub struct Config {
pub teams: HashMap<String, Vec<Member>>,
date_format: Option<String>,
default_team: Option<String>,
}

impl Config {
pub fn date_format(&self) -> &str {
self.date_format.as_deref().unwrap_or(DEFAULT_DATE_FMT)
}

pub fn default_team(&self) -> Option<&Vec<Member>> {
match &self.default_team {
Some(name) => self.teams.get(name),
None => None,
}
}
}

#[derive(Deserialize)]
Expand All @@ -38,6 +55,9 @@ mod tests {
fn reads_config_alright() {
let config: Config = toml::from_str(
r#"
date_format = "%c"
default_team = "wcgw"
[[teams.wcgw]]
name = "Alex"
location = "America/Montreal"
Expand All @@ -53,6 +73,9 @@ mod tests {
)
.unwrap();

assert_eq!(config.date_format(), "%c");
assert_eq!(config.default_team, Some("wcgw".to_owned()));

assert_eq!(config.teams.len(), 2);
assert!(config.teams.contains_key("wcgw"));
assert!(config.teams.contains_key("managers"));
Expand Down
123 changes: 82 additions & 41 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

use crate::config::Config;
use chrono::Local;
use crate::config::{Config, Member};
use chrono::{DateTime, Local};
use chrono_english::{parse_date_string, Dialect};
use std::cmp::Ordering;
use std::collections::HashSet;
Expand All @@ -37,6 +37,7 @@ fn main() {
.short('c')
.long("config")
.help("The config file to use")
.display_order(4)
.takes_value(true)
.default_value(default_config().as_str()),
)
Expand All @@ -45,28 +46,49 @@ fn main() {
.short('l')
.long("by-location")
.help("Group by locations")
.display_order(3)
.takes_value(false),
)
.arg(
clap::Arg::new("ALL")
.long("all")
.help("Print all teams")
.display_order(2)
.takes_value(false),
)
.arg(
clap::Arg::new("TEAM")
.short('t')
.long("team")
.help("Print specific team")
.display_order(1)
.conflicts_with("ALL")
.takes_value(true),
)
.trailing_var_arg(true)
.arg(clap::Arg::new("DATE").multiple_occurrences(true).help("Date to parse"))
.arg(
clap::Arg::new("DATE")
.multiple_occurrences(true)
.help("Date to parse")
.default_value("now"),
)
.get_matches();

let config_src = matches.value_of("CONFIG").unwrap();
let config: Config = match File::open(config_src) {
let cfg_src = matches.value_of("CONFIG").unwrap();
let cfg: Config = match File::open(cfg_src) {
Ok(mut file) => {
let mut data = String::with_capacity(1024);
match file.read_to_string(&mut data) {
Ok(_) => match toml::from_str(&data) {
Ok(cfg) => cfg,
Err(err) => exit!(1, "Couldn't parse config file '{}': {}", config_src, err),
Err(err) => exit!(1, "Couldn't parse config file '{}': {}", cfg_src, err),
},
Err(err) => exit!(1, "Couldn't read config file '{}': {}", config_src, err),
Err(err) => exit!(1, "Couldn't read config file '{}': {}", cfg_src, err),
}
},
Err(err) => exit!(1, "Couldn't open config file '{}': {}", config_src, err),
Err(err) => exit!(1, "Couldn't open config file '{}': {}", cfg_src, err),
};

let teams = config.teams.len();
let location_grouping = matches.is_present("LOCATIONS");

let date = if let Some(date) = matches.values_of("DATE") {
Expand All @@ -79,43 +101,62 @@ fn main() {
Local::now()
};

for (team, members) in config.teams {
if teams > 1 {
let team = if let Some(team) = matches.value_of("TEAM") {
cfg.teams.get(team)
} else {
cfg.default_team()
};

let left_header = if location_grouping { "Location" } else { "Team member" };
if team.is_none() || matches.is_present("ALL") {
for (team, members) in &cfg.teams {
println!("\n => Team {}", team);
let lines = team_to_lines(&cfg, location_grouping, date, members);
print_timezones(left_header, "Time", lines);
}
let mut lines: Vec<(String, String)> = Vec::new();
if location_grouping {
let locations: HashSet<chrono_tz::Tz> = members.iter().map(|m| m.location).collect();
let mut locations: Vec<chrono_tz::Tz> = locations.into_iter().collect();
locations.sort_by(|a, b| {
let one = date.with_timezone(a);
let two = date.with_timezone(b);
match one.date_naive().cmp(&two.date_naive()) {
Ordering::Less => Ordering::Less,
Ordering::Equal => one.time().cmp(&two.time()),
Ordering::Greater => Ordering::Greater,
}
});
for location in locations {
lines.push((
location.to_string(),
date.with_timezone(&location).format("%a %b %d %H:%M").to_string(),
));
}
} else {
for member in members {
lines.push((
format!("{} ({})", member.name, member.location),
date
.with_timezone(&member.location)
.format("%a %b %d %H:%M")
.to_string(),
));
} else {
let lines = team_to_lines(&cfg, location_grouping, date, team.unwrap());
print_timezones(left_header, "Time", lines);
}
}

fn team_to_lines(
cfg: &Config,
location_grouping: bool,
date: DateTime<Local>,
members: &Vec<Member>,
) -> Vec<(String, String)> {
let mut lines: Vec<(String, String)> = Vec::new();
if location_grouping {
let locations: HashSet<chrono_tz::Tz> = members.iter().map(|m| m.location).collect();
let mut locations: Vec<chrono_tz::Tz> = locations.into_iter().collect();
locations.sort_by(|a, b| {
let one = date.with_timezone(a);
let two = date.with_timezone(b);
match one.date_naive().cmp(&two.date_naive()) {
Ordering::Less => Ordering::Less,
Ordering::Equal => one.time().cmp(&two.time()),
Ordering::Greater => Ordering::Greater,
}
});
for location in locations {
lines.push((
location.to_string(),
date.with_timezone(&location).format(cfg.date_format()).to_string(),
));
}
} else {
for member in members {
lines.push((
format!("{} ({})", member.name, member.location),
date
.with_timezone(&member.location)
.format(cfg.date_format())
.to_string(),
));
}
let left_header = if location_grouping { "Location" } else { "Team member" };
print_timezones(left_header, "Time", lines);
}
lines
}

fn full_version() -> String {
Expand Down

0 comments on commit ef9fc7a

Please sign in to comment.