Filter summary based on ids

Closes  #573

Signed-off-by: Thomas Lauf <thomas.lauf@tngtech.com>
This commit is contained in:
Thomas Lauf 2023-12-19 22:31:10 +01:00
parent 82ca6d4027
commit bf683eedbf
5 changed files with 75 additions and 8 deletions

View file

@ -122,3 +122,4 @@ Thanks to the following, who submitted detailed bug reports and excellent sugges
Beshoy Girgis
Sergey Zhuravlevich
catexis
Aniket Meshram

View file

@ -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

View file

@ -6,10 +6,14 @@ timew-summary - display a time-tracking summary
== SYNOPSIS
[verse]
*timew summary* [_<range>_] [_<tag>_**...**]
*timew summary* [_<id>_**...**]
== 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:

View file

@ -25,6 +25,7 @@
////////////////////////////////////////////////////////////////////////////////
#include <IntervalFilterAllInRange.h>
#include <IntervalFilterAllWithIds.h>
#include <IntervalFilterAllWithTags.h>
#include <IntervalFilterAndGroup.h>
#include <SummaryTable.h>
@ -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.
if (! ids.empty () && ! tags.empty ())
{
throw std::string ("You cannot filter intervals by both, ids and tags.");
}
Range range;
std::vector <Interval> 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 <IntervalFilterAllInRange> (range),
std::make_shared <IntervalFilterAllWithTags> (tags)
});
auto tracked = getTracked (database, rules, filtering);
tracked = getTracked (database, rules, filtering);
}
if (tracked.empty ())
{

View file

@ -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")