Add id filtering to reports

Signed-off-by: Thomas Lauf <thomas.lauf@tngtech.com>
This commit is contained in:
Thomas Lauf 2023-12-30 15:13:36 +01:00 committed by Thomas Lauf
parent 9cc2844595
commit 6c74f7aa3c
2 changed files with 53 additions and 7 deletions

View file

@ -6,6 +6,7 @@ timew-report - run an extension report
== SYNOPSIS
[verse]
*timew* [*report*] _<report>_ [_<range>_] [_<tag>_**...**]
*timew* [*report*] _<report>_ _<id>_**...**
== DESCRIPTION
Runs an extension report, and supports filtering data.
@ -19,6 +20,8 @@ This does however assume there is a 'foo' extension installed.
The return code is the return code of the extension.
If the extension produces no output and a non-zero rc, then 255 is returned.
Filtering is either possible by range and/or tags, or by ids.
== CONFIGURATION
**reports.range**::
@ -30,3 +33,4 @@ Defaults to `all`
Set the date range for report _name_, used if no _range_ is given on the command line.
Here, _name_ is the name of the report executable without its extension (i.e. a report executable 'foo.py' is referred to by 'foo').
The value has to correspond to a range hint, see **timew-hints**(7).
Defaults to the value of **reports.range**.

View file

@ -26,6 +26,7 @@
#include <FS.h>
#include <IntervalFilterAllInRange.h>
#include <IntervalFilterAllWithIds.h>
#include <IntervalFilterAllWithTags.h>
#include <IntervalFilterAndGroup.h>
#include <cmake.h>
@ -133,16 +134,57 @@ int CmdReport (
Range default_range = {};
expandIntervalHint (":" + report_hint, default_range);
// Create a filter, and if empty, choose the current week.
auto ids = cli.getIds ();
auto tags = cli.getTags ();
auto range = cli.getRange (default_range);
IntervalFilterAndGroup filtering ({
std::make_shared <IntervalFilterAllInRange> (range),
std::make_shared <IntervalFilterAllWithTags> (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 <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)
});
tracked = getTracked (database, rules, filtering);
}
// Compose Header info.
rules.set ("temp.report.start", range.is_started () ? range.start.toISO () : "");