Refactor task diffs to handle new attributes
This refactors task(Info)Differences to be methods of Task and to correctly handle the `annotation_`, `tags_`, and `dep_` attributes.
This commit is contained in:
committed by
Tomas Babej
parent
7aee9567a3
commit
309e99d49e
207
src/feedback.cpp
207
src/feedback.cpp
@@ -42,213 +42,6 @@
|
||||
|
||||
static void countTasks (const std::vector <Task>&, const std::string&, int&, int&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Converts a vector of tasks to a human-readable string that represents the tasks.
|
||||
std::string taskIdentifiers (const std::vector <Task>& tasks)
|
||||
{
|
||||
std::vector <std::string> identifiers;
|
||||
identifiers.reserve(tasks.size());
|
||||
for (const auto& task: tasks)
|
||||
identifiers.push_back (task.identifier (true));
|
||||
|
||||
return join (", ", identifiers);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string taskDifferences (const Task& before, const Task& after)
|
||||
{
|
||||
// Attributes are all there is, so figure the different attribute names
|
||||
// between before and after.
|
||||
std::vector <std::string> beforeAtts;
|
||||
for (auto& att : before.data)
|
||||
beforeAtts.push_back (att.first);
|
||||
|
||||
std::vector <std::string> afterAtts;
|
||||
for (auto& att : after.data)
|
||||
afterAtts.push_back (att.first);
|
||||
|
||||
std::vector <std::string> beforeOnly;
|
||||
std::vector <std::string> afterOnly;
|
||||
listDiff (beforeAtts, afterAtts, beforeOnly, afterOnly);
|
||||
|
||||
// Now start generating a description of the differences.
|
||||
std::stringstream out;
|
||||
for (auto& name : beforeOnly)
|
||||
out << " - "
|
||||
<< format ("{1} will be deleted.", Lexer::ucFirst (name))
|
||||
<< "\n";
|
||||
|
||||
// TODO: #2572 - rewrite to look at dep_ and tag_
|
||||
for (auto& name : afterOnly)
|
||||
{
|
||||
if (name == "depends")
|
||||
{
|
||||
auto deps_after = after.getDependencyTasks ();
|
||||
|
||||
out << " - "
|
||||
<< format ("Dependencies will be set to '{1}'.", taskIdentifiers (deps_after))
|
||||
<< "\n";
|
||||
}
|
||||
else
|
||||
out << " - "
|
||||
<< format ("{1} will be set to '{2}'.",
|
||||
Lexer::ucFirst (name),
|
||||
renderAttribute (name, after.get (name)))
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
for (auto& name : beforeAtts)
|
||||
{
|
||||
// Ignore UUID differences, and find values that changed, but are not also
|
||||
// in the beforeOnly and afterOnly lists, which have been handled above..
|
||||
if (name != "uuid" &&
|
||||
before.get (name) != after.get (name) &&
|
||||
std::find (beforeOnly.begin (), beforeOnly.end (), name) == beforeOnly.end () &&
|
||||
std::find (afterOnly.begin (), afterOnly.end (), name) == afterOnly.end ())
|
||||
{
|
||||
if (name == "depends")
|
||||
{
|
||||
auto deps_before = before.getDependencyTasks ();
|
||||
std::string from = taskIdentifiers (deps_before);
|
||||
|
||||
auto deps_after = after.getDependencyTasks ();
|
||||
std::string to = taskIdentifiers (deps_after);
|
||||
|
||||
out << " - "
|
||||
<< format ("Dependencies will be changed from '{1}' to '{2}'.", from, to)
|
||||
<< "\n";
|
||||
}
|
||||
else
|
||||
out << " - "
|
||||
<< format ("{1} will be changed from '{2}' to '{3}'.",
|
||||
Lexer::ucFirst (name),
|
||||
renderAttribute (name, before.get (name)),
|
||||
renderAttribute (name, after.get (name)))
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Shouldn't just say nothing.
|
||||
if (out.str ().length () == 0)
|
||||
out << " - No changes will be made.\n";
|
||||
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string taskInfoDifferences (
|
||||
const Task& before,
|
||||
const Task& after,
|
||||
const std::string& dateformat,
|
||||
long& last_timestamp,
|
||||
const long current_timestamp)
|
||||
{
|
||||
// Attributes are all there is, so figure the different attribute names
|
||||
// between before and after.
|
||||
std::vector <std::string> beforeAtts;
|
||||
for (auto& att : before.data)
|
||||
beforeAtts.push_back (att.first);
|
||||
|
||||
std::vector <std::string> afterAtts;
|
||||
for (auto& att : after.data)
|
||||
afterAtts.push_back (att.first);
|
||||
|
||||
std::vector <std::string> beforeOnly;
|
||||
std::vector <std::string> afterOnly;
|
||||
listDiff (beforeAtts, afterAtts, beforeOnly, afterOnly);
|
||||
|
||||
// Now start generating a description of the differences.
|
||||
std::stringstream out;
|
||||
for (auto& name : beforeOnly)
|
||||
{
|
||||
if (name == "depends")
|
||||
{
|
||||
out << format ("Dependencies '{1}' deleted.", taskIdentifiers (before.getDependencyTasks ()))
|
||||
<< "\n";
|
||||
}
|
||||
else if (name.substr (0, 11) == "annotation_")
|
||||
{
|
||||
out << format ("Annotation '{1}' deleted.\n", before.get (name));
|
||||
}
|
||||
else if (name == "start")
|
||||
{
|
||||
Datetime started (before.get ("start"));
|
||||
Datetime stopped;
|
||||
|
||||
if (after.has ("end"))
|
||||
// Task was marked as finished, use end time
|
||||
stopped = Datetime (after.get ("end"));
|
||||
else
|
||||
// Start attribute was removed, use modification time
|
||||
stopped = Datetime (current_timestamp);
|
||||
|
||||
out << format ("{1} deleted (duration: {2}).",
|
||||
Lexer::ucFirst (name),
|
||||
Duration (stopped - started).format ())
|
||||
<< "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
out << format ("{1} deleted.\n", Lexer::ucFirst (name));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& name : afterOnly)
|
||||
{
|
||||
if (name == "depends")
|
||||
{
|
||||
out << format ("Dependencies set to '{1}'.", taskIdentifiers (after.getDependencyTasks ()))
|
||||
<< "\n";
|
||||
}
|
||||
else if (name.substr (0, 11) == "annotation_")
|
||||
{
|
||||
out << format ("Annotation of '{1}' added.\n", after.get (name));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (name == "start")
|
||||
last_timestamp = current_timestamp;
|
||||
|
||||
out << format ("{1} set to '{2}'.",
|
||||
Lexer::ucFirst (name),
|
||||
renderAttribute (name, after.get (name), dateformat))
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& name : beforeAtts)
|
||||
if (name != "uuid" &&
|
||||
name != "modified" &&
|
||||
before.get (name) != after.get (name) &&
|
||||
before.get (name) != "" &&
|
||||
after.get (name) != "")
|
||||
{
|
||||
if (name == "depends")
|
||||
{
|
||||
auto from = taskIdentifiers (before.getDependencyTasks ());
|
||||
auto to = taskIdentifiers (after.getDependencyTasks ());
|
||||
|
||||
out << format ("Dependencies changed from '{1}' to '{2}'.\n", from, to);
|
||||
}
|
||||
else if (name.substr (0, 11) == "annotation_")
|
||||
{
|
||||
out << format ("Annotation changed to '{1}'.\n", after.get (name));
|
||||
}
|
||||
else
|
||||
out << format ("{1} changed from '{2}' to '{3}'.",
|
||||
Lexer::ucFirst (name),
|
||||
renderAttribute (name, before.get (name), dateformat),
|
||||
renderAttribute (name, after.get (name), dateformat))
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
// Shouldn't just say nothing.
|
||||
if (out.str ().length () == 0)
|
||||
out << "No changes made.\n";
|
||||
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string renderAttribute (const std::string& name, const std::string& value, const std::string& format /* = "" */)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user