display all, full, sheet and current active
This commit is contained in:
parent
a29c3c40ab
commit
bfe80c10e1
|
@ -1,5 +1,6 @@
|
|||
use std::convert::TryFrom;
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
|
||||
use clap::ArgMatches;
|
||||
|
||||
|
@ -11,12 +12,31 @@ use crate::config::Config;
|
|||
|
||||
use super::Command;
|
||||
|
||||
enum Sheet {
|
||||
All,
|
||||
Full,
|
||||
Sheet(String),
|
||||
}
|
||||
|
||||
impl FromStr for Sheet {
|
||||
type Err = error::Error;
|
||||
|
||||
fn from_str(name: &str) -> error::Result<Sheet> {
|
||||
Ok(match name {
|
||||
"all" => Sheet::All,
|
||||
"full" => Sheet::Full,
|
||||
name => Sheet::Sheet(name.into()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Args {
|
||||
ids: bool,
|
||||
start: Option<Time>,
|
||||
end: Option<Time>,
|
||||
format: Formatter,
|
||||
grep: Option<String>,
|
||||
sheet: Option<Sheet>,
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
|
||||
|
@ -29,6 +49,7 @@ impl<'a> TryFrom<&'a ArgMatches<'a>> for Args {
|
|||
end: matches.value_of("at").map(|s| s.parse()).transpose()?,
|
||||
format: matches.value_of("format").unwrap().parse()?,
|
||||
grep: matches.value_of("grep").map(|s| s.into()),
|
||||
sheet: matches.value_of("sheet").map(|s| s.parse()).transpose()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -44,8 +65,17 @@ impl<'a> Command<'a> for DisplayCommand {
|
|||
D: Database,
|
||||
W: Write,
|
||||
{
|
||||
let sheets_to_display = match args.sheet {
|
||||
Some(Sheet::All) => db.entries_all_visible()?,
|
||||
Some(Sheet::Full) => db.entries_full()?,
|
||||
Some(Sheet::Sheet(name)) => db.entries_by_sheet(&name)?,
|
||||
None => {
|
||||
let current_sheet = db.current_sheet()?.unwrap_or("default".into());
|
||||
|
||||
args.format.print_formatted(db.entries_by_sheet(¤t_sheet)?, out)
|
||||
db.entries_by_sheet(¤t_sheet)?
|
||||
}
|
||||
};
|
||||
|
||||
args.format.print_formatted(sheets_to_display, out)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,11 +37,10 @@ impl<'a> Command<'a> for InCommand {
|
|||
W: Write,
|
||||
{
|
||||
let at = args.at.unwrap_or(Time::now());
|
||||
|
||||
let note = if let Some(note) = args.note {
|
||||
note
|
||||
} else {
|
||||
editor::get_string()?
|
||||
editor::get_string(config)?
|
||||
};
|
||||
|
||||
db.entry_insert(at, note)?;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::path::Path;
|
||||
|
||||
use rusqlite::{Connection, ToSql};
|
||||
use rusqlite::{Connection, ToSql, types::{FromSql, ValueRef, FromSqlResult}};
|
||||
use chrono::DateTime;
|
||||
|
||||
use crate::error;
|
||||
use crate::models::{Entry, Meta};
|
||||
|
@ -16,10 +17,18 @@ pub trait Database {
|
|||
|
||||
// Entry queries
|
||||
|
||||
fn entries_by_sheet(&mut self, sheet: &str) -> error::Result<Vec<Entry>> {
|
||||
fn entries_by_sheet(&self, sheet: &str) -> error::Result<Vec<Entry>> {
|
||||
self.entry_query("select * from entries where sheet=?1", &[&sheet])
|
||||
}
|
||||
|
||||
fn entries_all_visible(&self) -> error::Result<Vec<Entry>> {
|
||||
self.entry_query("select * from entries where sheet not like '!_%' escape \"!\"", &[])
|
||||
}
|
||||
|
||||
fn entries_full(&self) -> error::Result<Vec<Entry>> {
|
||||
self.entry_query("select * from entries", &[])
|
||||
}
|
||||
|
||||
fn entry_insert(&mut self, at: Time, note: String) -> error::Result<()> {
|
||||
self.execute("", &[])
|
||||
}
|
||||
|
@ -86,3 +95,9 @@ impl Database for SqliteDatabase {
|
|||
Ok(results)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromSql for Time {
|
||||
fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self> {
|
||||
Ok(DateTime::column_result(value)?.into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::error;
|
||||
use crate::config::Config;
|
||||
|
||||
pub fn get_string() -> error::Result<String> {
|
||||
pub fn get_string(config: &Config) -> error::Result<String> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
|
|
@ -28,6 +28,9 @@ pub enum Error {
|
|||
|
||||
#[error("Could not parse datetime: {0}")]
|
||||
DateTimeParseError(#[from] chrono::format::ParseError),
|
||||
|
||||
#[error("IOError: {0}")]
|
||||
IOError(#[from] std::io::Error)
|
||||
}
|
||||
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
|
|
@ -18,7 +18,7 @@ impl Formatter {
|
|||
match &self {
|
||||
Formatter::Text => {
|
||||
for entry in entries {
|
||||
writeln!(out, "{:?}", entry);
|
||||
writeln!(out, "{:?}", entry)?;
|
||||
}
|
||||
}
|
||||
Formatter::Custom(name) => {
|
||||
|
@ -41,3 +41,35 @@ impl FromStr for Formatter {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::types::Time;
|
||||
|
||||
#[test]
|
||||
fn test_text_output() {
|
||||
let formatter = Formatter::Text;
|
||||
let mut output = Vec::new();
|
||||
let entries = vec![
|
||||
Entry::new_sample(1, Time::new(2008, 10, 3, 12, 0, 0), Some(Time::new(2008, 10, 3, 14, 0, 0))),
|
||||
Entry::new_sample(2, Time::new(2008, 10, 3, 12, 0, 0), Some(Time::new(2008, 10, 3, 14, 0, 0))),
|
||||
Entry::new_sample(3, Time::new(2008, 10, 5, 16, 0, 0), Some(Time::new(2008, 10, 3, 18, 0, 0))),
|
||||
Entry::new_sample(4, Time::new(2008, 10, 5, 18, 0, 0), None),
|
||||
];
|
||||
|
||||
formatter.print_formatted(entries, &mut output).unwrap();
|
||||
|
||||
assert_eq!(String::from_utf8_lossy(&output), "Timesheet: SpecSheet
|
||||
Day Start End Duration Notes
|
||||
Fri Oct 03, 2008 12:00:00 - 14:00:00 2:00:00 entry 1
|
||||
16:00:00 - 18:00:00 2:00:00 entry 2
|
||||
4:00:00
|
||||
Sun Oct 05, 2008 16:00:00 - 18:00:00 2:00:00 entry 3
|
||||
18:00:00 - 2:00:00 entry 4
|
||||
4:00:00
|
||||
-----------------------------------------------------------
|
||||
Total 8:00:00
|
||||
");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,9 +106,7 @@ fn main() {
|
|||
|
||||
.subcommand(SubCommand::with_name("display")
|
||||
.visible_alias("d")
|
||||
.about("Display the current timesheet or a specific. Pass `all' as SHEET
|
||||
to display all unarchived sheets or `full' to display archived and
|
||||
unarchived sheets.")
|
||||
.about("Display the current timesheet or a specific. Pass `all' as SHEET to display all unarchived sheets or `full' to display archived and unarchived sheets.")
|
||||
.arg(Arg::with_name("ids")
|
||||
.short("v").long("ids")
|
||||
.help("Print database ids (for use with edit)"))
|
||||
|
@ -129,6 +127,9 @@ fn main() {
|
|||
.short("g").long("grep")
|
||||
.takes_value(true).value_name("REGEXP")
|
||||
.help("Include entries where the note matches this regexp."))
|
||||
.arg(Arg::with_name("sheet")
|
||||
.takes_value(true).value_name("SHEET")
|
||||
.help("The sheet to display. Pass 'all' to see entries from all sheets or 'full' to see hidden entries"))
|
||||
)
|
||||
|
||||
.subcommand(SubCommand::with_name("in")
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use chrono::{DateTime, Utc};
|
||||
use crate::types::Time;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Entry {
|
||||
pub id: u64,
|
||||
pub note: String,
|
||||
pub start: DateTime<Utc>,
|
||||
pub end: DateTime<Utc>,
|
||||
pub start: Time,
|
||||
pub end: Option<Time>,
|
||||
pub sheet: String,
|
||||
}
|
||||
|
||||
|
@ -15,3 +15,15 @@ pub struct Meta {
|
|||
pub key: String,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
impl Entry {
|
||||
#[cfg(test)]
|
||||
pub fn new_sample(id: u64, start: Time, end: Option<Time>) -> Entry {
|
||||
Entry {
|
||||
id,
|
||||
note: format!("entry {}", id),
|
||||
start, end,
|
||||
sheet: "default".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
20
src/types.rs
20
src/types.rs
|
@ -1,12 +1,28 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use chrono::{DateTime, Utc, TimeZone};
|
||||
|
||||
use crate::error;
|
||||
|
||||
pub struct Time;
|
||||
/// A time in UTC.
|
||||
///
|
||||
/// Just a wrapper around Chrono::Utc
|
||||
#[derive(Debug)]
|
||||
pub struct Time(DateTime<Utc>);
|
||||
|
||||
impl Time {
|
||||
pub fn now() -> Time {
|
||||
Time
|
||||
Time(Utc::now())
|
||||
}
|
||||
|
||||
pub fn new(y: i32, mo: u32, d: u32, h: u32, mi: u32, s: u32) -> Time {
|
||||
Time(Utc.ymd(y, mo, d).and_hms(h, mi, s))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DateTime<Utc>> for Time {
|
||||
fn from(dt: DateTime<Utc>) -> Time {
|
||||
Time(dt)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue