Commands - timesheet

- Migrated handleReportTimesheet to CmdTimesheet.
This commit is contained in:
Paul Beckingham 2011-05-30 13:46:08 -04:00
parent 2fb743992f
commit 75a24f5113
9 changed files with 230 additions and 146 deletions

View file

@ -131,7 +131,6 @@ void Cmd::load ()
{ {
commands.push_back ("delete"); commands.push_back ("delete");
commands.push_back ("done"); commands.push_back ("done");
commands.push_back ("timesheet");
commands.push_back ("merge"); commands.push_back ("merge");
commands.push_back ("push"); commands.push_back ("push");
commands.push_back ("pull"); commands.push_back ("pull");
@ -192,7 +191,6 @@ void Cmd::allCommands (std::vector <std::string>& all) const
bool Cmd::isReadOnlyCommand () bool Cmd::isReadOnlyCommand ()
{ {
if (command == "push" || if (command == "push" ||
command == "timesheet" ||
validCustom (command)) validCustom (command))
return true; return true;

View file

@ -249,8 +249,7 @@ int Context::dispatch (std::string &out)
Timer t ("Context::dispatch"); Timer t ("Context::dispatch");
// TODO Chain-of-command pattern dispatch. // TODO Chain-of-command pattern dispatch.
if (cmd.command == "timesheet") { rc = handleReportTimesheet (out); } if (cmd.command == "done") { rc = handleDone (out); }
else if (cmd.command == "done") { rc = handleDone (out); }
else if (cmd.command == "delete") { rc = handleDelete (out); } else if (cmd.command == "delete") { rc = handleDelete (out); }
else if (cmd.command == "merge") { tdb.gc (); else if (cmd.command == "merge") { tdb.gc ();
handleMerge (out); } handleMerge (out); }

View file

@ -40,6 +40,7 @@ set (commands_SRCS Command.cpp Command.h
CmdStop.cpp CmdStop.h CmdStop.cpp CmdStop.h
CmdSummary.cpp CmdSummary.h CmdSummary.cpp CmdSummary.h
CmdTags.cpp CmdTags.h CmdTags.cpp CmdTags.h
CmdTimesheet.cpp CmdTimesheet.h
CmdTip.cpp CmdTip.h CmdTip.cpp CmdTip.h
CmdUndo.cpp CmdUndo.h CmdUndo.cpp CmdUndo.h
CmdUrgency.cpp CmdUrgency.h CmdUrgency.cpp CmdUrgency.h

View file

@ -111,10 +111,6 @@ int CmdHelp::execute (const std::string&, std::string& output)
view.set (row, 1, "task done ID [tags] [attrs] [desc...]"); view.set (row, 1, "task done ID [tags] [attrs] [desc...]");
view.set (row, 2, "Marks the specified task as completed."); view.set (row, 2, "Marks the specified task as completed.");
row = view.addRow ();
view.set (row, 1, "task timesheet [weeks]");
view.set (row, 2, "Shows a weekly report of tasks completed and started.");
row = view.addRow (); row = view.addRow ();
view.set (row, 1, "task merge URL"); view.set (row, 1, "task merge URL");
view.set (row, 2, "Merges the specified undo.data file with the local data files."); view.set (row, 2, "Merges the specified undo.data file with the local data files.");

View file

@ -0,0 +1,184 @@
////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#include <sstream>
#include <Context.h>
#include <ViewText.h>
#include <Date.h>
#include <main.h>
#include <CmdTimesheet.h>
extern Context context;
////////////////////////////////////////////////////////////////////////////////
CmdTimesheet::CmdTimesheet ()
{
_keyword = "timesheet";
_usage = "task timesheet [weeks]";
_description = "Shows a weekly report of tasks completed and started.";
_read_only = true;
_displays_id = false;
}
////////////////////////////////////////////////////////////////////////////////
int CmdTimesheet::execute (const std::string&, std::string& output)
{
int rc = 0;
// Scan the pending tasks.
std::vector <Task> tasks;
context.tdb.lock (context.config.getBoolean ("locking"));
handleRecurrence ();
context.tdb.load (tasks, context.filter);
context.tdb.commit ();
context.tdb.unlock ();
// Just do this once.
int width = context.getWidth ();
// What day of the week does the user consider the first?
int weekStart = Date::dayOfWeek (context.config.get ("weekstart"));
if (weekStart != 0 && weekStart != 1)
throw std::string ("The 'weekstart' configuration variable may "
"only contain 'Sunday' or 'Monday'.");
// Determine the date of the first day of the most recent report.
Date today;
Date start;
start -= (((today.dayOfWeek () - weekStart) + 7) % 7) * 86400;
// Roll back to midnight.
start = Date (start.month (), start.day (), start.year ());
Date end = start + (7 * 86400);
// Determine how many reports to run.
int quantity = 1;
if (context.sequence.size () == 1)
quantity = context.sequence[0];
std::stringstream out;
for (int week = 0; week < quantity; ++week)
{
Date endString (end);
endString -= 86400;
std::string title = start.toString (context.config.get ("dateformat"))
+ " - "
+ endString.toString (context.config.get ("dateformat"));
Color bold (Color::nocolor, Color::nocolor, false, true, false);
out << "\n"
<< (context.color () ? bold.colorize (title) : title)
<< "\n";
// Render the completed table.
ViewText completed;
completed.width (width);
completed.add (Column::factory ("string", " "));
completed.add (Column::factory ("string", "Project"));
completed.add (Column::factory ("string.right", "Due"));
completed.add (Column::factory ("string", "Description"));
std::vector <Task>::iterator task;
for (task = tasks.begin (); task != tasks.end (); ++task)
{
// If task completed within range.
if (task->getStatus () == Task::completed)
{
Date compDate (atoi (task->get ("end").c_str ()));
if (compDate >= start && compDate < end)
{
Color c (task->get ("fg") + " " + task->get ("bg"));
if (context.color ())
autoColorize (*task, c);
int row = completed.addRow ();
std::string format = context.config.get ("dateformat.report");
if (format == "")
format = context.config.get ("dateformat");
completed.set (row, 1, task->get ("project"), c);
completed.set (row, 2, getDueDate (*task, format), c);
completed.set (row, 3, getFullDescription (*task, "timesheet"), c);
}
}
}
out << " Completed (" << completed.rows () << " tasks)\n";
if (completed.rows ())
out << completed.render ()
<< "\n";
// Now render the started table.
ViewText started;
started.width (width);
started.add (Column::factory ("string", " "));
started.add (Column::factory ("string", "Project"));
started.add (Column::factory ("string.right", "Due"));
started.add (Column::factory ("string", "Description"));
for (task = tasks.begin (); task != tasks.end (); ++task)
{
// If task started within range, but not completed withing range.
if (task->getStatus () == Task::pending &&
task->has ("start"))
{
Date startDate (atoi (task->get ("start").c_str ()));
if (startDate >= start && startDate < end)
{
Color c (task->get ("fg") + " " + task->get ("bg"));
if (context.color ())
autoColorize (*task, c);
int row = started.addRow ();
std::string format = context.config.get ("dateformat.report");
if (format == "")
format = context.config.get ("dateformat");
started.set (row, 1, task->get ("project"), c);
started.set (row, 2, getDueDate (*task, format), c);
started.set (row, 3, getFullDescription (*task, "timesheet"), c);
}
}
}
out << " Started (" << started.rows () << " tasks)\n";
if (started.rows ())
out << started.render ()
<< "\n\n";
// Prior week.
start -= 7 * 86400;
end -= 7 * 86400;
}
output = out.str ();
return rc;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -0,0 +1,42 @@
////////////////////////////////////////////////////////////////////////////////
// taskwarrior - a command line task list manager.
//
// Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez.
// All rights reserved.
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
// details.
//
// You should have received a copy of the GNU General Public License along with
// this program; if not, write to the
//
// Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor,
// Boston, MA
// 02110-1301
// USA
//
////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_CMDTIMESHEET
#define INCLUDED_CMDTIMESHEET
#define L10N // Localization complete.
#include <string>
#include <Command.h>
class CmdTimesheet : public Command
{
public:
CmdTimesheet ();
int execute (const std::string&, std::string&);
};
#endif
////////////////////////////////////////////////////////////////////////////////

View file

@ -62,6 +62,7 @@
#include <CmdStop.h> #include <CmdStop.h>
#include <CmdSummary.h> #include <CmdSummary.h>
#include <CmdTags.h> #include <CmdTags.h>
#include <CmdTimesheet.h>
#include <CmdTip.h> #include <CmdTip.h>
#include <CmdUndo.h> #include <CmdUndo.h>
#include <CmdUrgency.h> #include <CmdUrgency.h>
@ -118,6 +119,7 @@ void Command::factory (std::map <std::string, Command*>& all)
c = new CmdStop (); all[c->keyword ()] = c; c = new CmdStop (); all[c->keyword ()] = c;
c = new CmdSummary (); all[c->keyword ()] = c; c = new CmdSummary (); all[c->keyword ()] = c;
c = new CmdTags (); all[c->keyword ()] = c; c = new CmdTags (); all[c->keyword ()] = c;
c = new CmdTimesheet (); all[c->keyword ()] = c;
c = new CmdTip (); all[c->keyword ()] = c; c = new CmdTip (); all[c->keyword ()] = c;
c = new CmdUndo (); all[c->keyword ()] = c; c = new CmdUndo (); all[c->keyword ()] = c;
c = new CmdUrgency (); all[c->keyword ()] = c; c = new CmdUrgency (); all[c->keyword ()] = c;

View file

@ -64,7 +64,6 @@ int deltaAttributes (Task&);
int deltaSubstitutions (Task&); int deltaSubstitutions (Task&);
// report.cpp // report.cpp
int handleReportTimesheet (std::string&);
std::string getFullDescription (Task&, const std::string&); std::string getFullDescription (Task&, const std::string&);
std::string getDueDate (Task&, const std::string&); std::string getDueDate (Task&, const std::string&);
std::string onProjectChange (Task&, bool scope = true); std::string onProjectChange (Task&, bool scope = true);

View file

@ -51,143 +51,6 @@ static void countTasks (const std::vector <Task>&, const std::string&, const std
extern Context context; extern Context context;
////////////////////////////////////////////////////////////////////////////////
int handleReportTimesheet (std::string& outs)
{
int rc = 0;
// Scan the pending tasks.
std::vector <Task> tasks;
context.tdb.lock (context.config.getBoolean ("locking"));
handleRecurrence ();
context.tdb.load (tasks, context.filter);
context.tdb.commit ();
context.tdb.unlock ();
// Just do this once.
int width = context.getWidth ();
// What day of the week does the user consider the first?
int weekStart = Date::dayOfWeek (context.config.get ("weekstart"));
if (weekStart != 0 && weekStart != 1)
throw std::string ("The 'weekstart' configuration variable may "
"only contain 'Sunday' or 'Monday'.");
// Determine the date of the first day of the most recent report.
Date today;
Date start;
start -= (((today.dayOfWeek () - weekStart) + 7) % 7) * 86400;
// Roll back to midnight.
start = Date (start.month (), start.day (), start.year ());
Date end = start + (7 * 86400);
// Determine how many reports to run.
int quantity = 1;
if (context.sequence.size () == 1)
quantity = context.sequence[0];
std::stringstream out;
for (int week = 0; week < quantity; ++week)
{
Date endString (end);
endString -= 86400;
std::string title = start.toString (context.config.get ("dateformat"))
+ " - "
+ endString.toString (context.config.get ("dateformat"));
Color bold (Color::nocolor, Color::nocolor, false, true, false);
out << "\n"
<< (context.color () ? bold.colorize (title) : title)
<< "\n";
// Render the completed table.
ViewText completed;
completed.width (width);
completed.add (Column::factory ("string", " "));
completed.add (Column::factory ("string", "Project"));
completed.add (Column::factory ("string.right", "Due"));
completed.add (Column::factory ("string", "Description"));
std::vector <Task>::iterator task;
for (task = tasks.begin (); task != tasks.end (); ++task)
{
// If task completed within range.
if (task->getStatus () == Task::completed)
{
Date compDate (atoi (task->get ("end").c_str ()));
if (compDate >= start && compDate < end)
{
Color c (task->get ("fg") + " " + task->get ("bg"));
if (context.color ())
autoColorize (*task, c);
int row = completed.addRow ();
std::string format = context.config.get ("dateformat.report");
if (format == "")
format = context.config.get ("dateformat");
completed.set (row, 1, task->get ("project"), c);
completed.set (row, 2, getDueDate (*task, format), c);
completed.set (row, 3, getFullDescription (*task, "timesheet"), c);
}
}
}
out << " Completed (" << completed.rows () << " tasks)\n";
if (completed.rows ())
out << completed.render ()
<< "\n";
// Now render the started table.
ViewText started;
started.width (width);
started.add (Column::factory ("string", " "));
started.add (Column::factory ("string", "Project"));
started.add (Column::factory ("string.right", "Due"));
started.add (Column::factory ("string", "Description"));
for (task = tasks.begin (); task != tasks.end (); ++task)
{
// If task started within range, but not completed withing range.
if (task->getStatus () == Task::pending &&
task->has ("start"))
{
Date startDate (atoi (task->get ("start").c_str ()));
if (startDate >= start && startDate < end)
{
Color c (task->get ("fg") + " " + task->get ("bg"));
if (context.color ())
autoColorize (*task, c);
int row = started.addRow ();
std::string format = context.config.get ("dateformat.report");
if (format == "")
format = context.config.get ("dateformat");
started.set (row, 1, task->get ("project"), c);
started.set (row, 2, getDueDate (*task, format), c);
started.set (row, 3, getFullDescription (*task, "timesheet"), c);
}
}
}
out << " Started (" << started.rows () << " tasks)\n";
if (started.rows ())
out << started.render ()
<< "\n\n";
// Prior week.
start -= 7 * 86400;
end -= 7 * 86400;
}
outs = out.str ();
return rc;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
std::string getFullDescription (Task& task, const std::string& report) std::string getFullDescription (Task& task, const std::string& report)
{ {