diff --git a/AUTHORS b/AUTHORS index ae8091e8..e8d0346b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -122,3 +122,4 @@ Thanks to the following, who submitted detailed bug reports and excellent sugges Beshoy Girgis Sergey Zhuravlevich catexis + Aniket Meshram diff --git a/ChangeLog b/ChangeLog index aa11e1fc..8cd517a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,8 @@ - #494 Expand annotations in summary (thanks to catexis) - #566 Set table width dynamically to terminal width +- #573 Filter summary based on ids + (thanks to Aniket Meshram) - #576 Fix quoting of tags in DOM output - Add ':today' hint - Refactor holidays/refresh script diff --git a/doc/man1/timew-summary.1.adoc b/doc/man1/timew-summary.1.adoc index df2b4929..7e3a26b4 100644 --- a/doc/man1/timew-summary.1.adoc +++ b/doc/man1/timew-summary.1.adoc @@ -6,10 +6,14 @@ timew-summary - display a time-tracking summary == SYNOPSIS [verse] *timew summary* [__] [__**...**] +*timew summary* [__**...**] == DESCRIPTION Displays a table summarizing tracked time, by default for the current day. -Accepts date ranges, or range hints, and tags for filtering. +Accepts date ranges (or range hints) and tags, or ids for filtering. + +When ids are given, date ranges are ignored. +Specifying both, tags and ids, is an error. == HINTS Apart from range hints (see **timew-hints**(7)), the summary report adheres to the following hints: diff --git a/src/commands/CmdSummary.cpp b/src/commands/CmdSummary.cpp index c73bcebd..5ee58799 100644 --- a/src/commands/CmdSummary.cpp +++ b/src/commands/CmdSummary.cpp @@ -25,6 +25,7 @@ //////////////////////////////////////////////////////////////////////////////// #include +#include #include #include #include @@ -53,16 +54,57 @@ int CmdSummary ( Range default_range = {}; expandIntervalHint (":" + report_hint, default_range); - auto range = cli.getRange (default_range); + auto ids = cli.getIds (); auto tags = cli.getTags (); - // Load the data. - IntervalFilterAndGroup filtering ({ - std::make_shared (range), - std::make_shared (tags) - }); + if (! ids.empty () && ! tags.empty ()) + { + throw std::string ("You cannot filter intervals by both, ids and tags."); + } - auto tracked = getTracked (database, rules, filtering); + Range range; + + std::vector tracked; + + if (! ids.empty ()) + { + auto filtering = IntervalFilterAllWithIds (ids); + tracked = getTracked (database, rules, filtering); + + if (tracked.size () != ids.size ()) + { + for (auto& id: ids) + { + bool found = false; + + for (auto& interval: tracked) + { + if (interval.id == id) + { + found = true; + break; + } + } + if (! found) + { + throw format ("ID '@{1}' does not correspond to any tracking.", id); + } + } + } + + range = Range {tracked.begin ()->end, tracked.end ()->start}; + } + else + { + range = cli.getRange (default_range); + + IntervalFilterAndGroup filtering ({ + std::make_shared (range), + std::make_shared (tags) + }); + + tracked = getTracked (database, rules, filtering); + } if (tracked.empty ()) { diff --git a/test/summary.t b/test/summary.t index cc0d4b8d..e35a778b 100755 --- a/test/summary.t +++ b/test/summary.t @@ -174,6 +174,24 @@ W10 2017-03-09 Thu @4 Tag1 8:43:08 9:38:15 0:55:07 0:55:07 0:55:07 """, out) + def test_with_id_filter(self): + """Summary should print data filtered by tag""" + self.t("track Tag1 2017-03-09T08:43:08 - 2017-03-09T09:38:15") + self.t("track Tag2 2017-03-09T11:38:39 - 2017-03-09T11:45:35") + self.t("track Tag2 Tag3 2017-03-09T11:46:21 - 2017-03-09T12:00:17") + self.t("track Tag2 Tag4 2017-03-09T12:01:49 - 2017-03-09T12:28:46") + + code, out, err = self.t("summary @2 @4 :ids") + + self.assertIn(""" +Wk Date Day ID Tags Start End Time Total +--- ---------- --- -- ---------- -------- -------- ------- ------- +W10 2017-03-09 Thu @4 Tag1 8:43:08 9:38:15 0:55:07 + @2 Tag2, Tag3 11:46:21 12:00:17 0:13:56 1:09:03 + + 1:09:03 +""", out) + def test_non_contiguous_with_tag_filter(self): """Summary should print data filtered by tag when tags are non-contiguous""" self.t("track Tag1 2017-03-09T08:43:08 - 2017-03-09T09:38:15")