def reflect(request): """ Respond to the "/reflect" URL. This is the main view for the "reflect" mode. """ # Calculate a summary of the tasks worked on over the past 7 days. started_at = utils.start_of_day() - datetime.timedelta(days=7) ended_at = utils.current_datetime() weekly_summary = activities.calc_task_summary(started_at, ended_at) # Now calculate a summary for each day of the week, grouping the results by # day and storing the results in a format which makes it easy for us to # generate the final table. day_start = started_at day_end = started_at + datetime.timedelta(days=1) \ - datetime.timedelta(seconds=1) daily_task_times = [] # List of times spent on the various tasks each day. # For each day, the list item will be a dictionary # with the following entries: # # 'day_label' # # The label to use to identify this day. # # 'task_times' # # A dictionary mapping each Task record ID to # the time spent on that task, as an integer # number of seconds. start_of_today = utils.start_of_day() while day_start <= start_of_today: weekday = day_start.date().weekday() day_label = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"][weekday] daily_summary = activities.calc_task_summary(day_start, day_end) def _add_task_times(daily_summary, task_times): """ Recursively add 'daily_summary' to the 'task_times' dictionary. """ for node in daily_summary: task_times[node['task'].id] = node['time_spent'] _add_task_times(node['children'], task_times) task_times = {} _add_task_times(daily_summary['summary'], task_times) daily_task_times.append({'day_label' : day_label, 'task_times' : task_times}) day_start = day_start + datetime.timedelta(days=1) day_end = day_end + datetime.timedelta(days=1) daily_task_times.reverse() # Show newest day first. # Process the weekly task summary, building a master list of all tasks # worked on during the week. tasks = [] # List of tasks worked on during the week. Each list item is a # dictionary with the following entries: # # 'task' # # The Task object to work on. # # 'label' # # The (possibly indented) label to use for this task. # # 'time_spent' # # The total amount of time spent on this task over the # last week, as an integer number of seconds. def _add_tree(tree, task, indent=0): """ Recursively add a summary tree to the list of tasks. """ for node in tree: label = " " * indent * 8 + node['task'].label tasks.append({'task' : node['task'], 'label' : label, 'time_spent' : node['time_spent']}) _add_tree(node['children'], tasks, indent=indent+1) _add_tree(weekly_summary['summary'], tasks) # Calculate the totals to display at the bottom of the table. weekly_total = 0 # Total time spent for the week, in seconds. for task in tasks: weekly_total = weekly_total + task['time_spent'] daily_totals = [] # Total time spent per day, in seconds. for day in daily_task_times: daily_total = 0 for task_time in day['task_times'].values(): daily_total = daily_total + task_time daily_totals.append(daily_total) # Using the calculated information, build a single large table representing # the entire summary. summary_table = [] # List of [col][row] entries. Each list item is a # dictionary with the following entries: # # 'text' # # The text to be displayed. # # 'style' # # The CSS style to apply to this table item. # Add the heading row to the top of the table. row = [] row.append({'text' : " ", 'style' : "heading"}) row.append({'text' : "Last 7 Days", 'style' : "heading border-b"}) row.append({'text' : " ", 'style' : "heading"}) for day in daily_task_times: row.append({'text' : day['day_label'], 'style' : "heading border-b"}) summary_table.append(row) # Add each task in turn. for task in tasks: row = [] row.append({'text' : task['label'] + " ", 'style' : "heading left"}) row.append({'text' : utils.seconds_to_hms(task['time_spent']), 'style' : "body border-lrb"}) row.append({'text' : " ", 'style' : "body"}) task_id = task['task'].id for day in daily_task_times: if task_id in day['task_times']: task_time = utils.seconds_to_hms(day['task_times'][task_id]) else: task_time = " " row.append({'text' : task_time, 'style' : "body border-lrb"}) summary_table.append(row) # Add the total times to the bottom of the table. row = [] row.append({'text' : " ", 'style' : "heading right"}) row.append({'text' : utils.seconds_to_hms(weekly_total), 'style' : "body border-t"}) row.append({'text' : " ", 'style' : "body"}) for daily_total in daily_totals: row.append({'text' : utils.seconds_to_hms(daily_total), 'style' : "body border-t"}) summary_table.append(row) # Finally, display the table to the user. return render(request, "reflect.html", {'table' : summary_table})
def suggest(request): """ Select a task and suggest that the user works on it. This is the main view for the "do" mode. """ # Get the details of the most recently worked-on task, if any. activity = activities.latest_activity() if activity['task'] == None: recent_task = None else: age = utils.current_datetime() - activity['ended_at'] if age > datetime.timedelta(hours=1): recent_task = None else: time_spent = \ utils.format_seconds_for_display(activity['time_spent']) did_minimum = (activity['time_spent'] > activity['task'].min_time) recent_task = {'label' : activity['task'].label, 'time_spent' : time_spent, 'did_minimum' : did_minimum} # Calculate the summary of the tasks worked on so far today. started_at = utils.start_of_day() #.replace(day=17) ended_at = utils.current_datetime() summary = activities.calc_task_summary(started_at, ended_at) # Convert the task tree into a "table" of nested activities. task_table = [] def _add_tree(tree, task_table, indent=0): """ Recursively add the tree to the task table. """ for node in tree: time_spent = utils.format_seconds_for_display(node['time_spent']) indent_str = " " * 8 task_table.append({'task' : node['task'], 'time_spent' : time_spent, 'prefix' : indent_str * indent}) _add_tree(node['children'], task_table, indent=indent+1) _add_tree(summary['summary'], task_table) # Choose the suggested task to work on next. suggested_task = chooser.choose_next_task() if suggested_task != None: start_url = "/do/" + str(suggested_task.id) else: start_url = None # Finally, display the suggested task to the user. total_time = utils.format_seconds_for_display(summary['tot_time']) finished_url = "/" return render(request, "suggest.html", {'recent_task' : recent_task, 'task_table' : task_table, 'total_time' : total_time, 'suggested_task' : suggested_task, 'start_url' : start_url, 'finished_url' : finished_url})