Skip to content

Instantly share code, notes, and snippets.

@jcheng31
Last active February 23, 2017 07:11
Show Gist options
  • Save jcheng31/57ee2e4b4912e40913b3a7a93502c74f to your computer and use it in GitHub Desktop.
Save jcheng31/57ee2e4b4912e40913b3a7a93502c74f to your computer and use it in GitHub Desktop.
Given an Asana task CSV, output a week-by-week breakdown of completed tasks for a particular year.
require 'csv'
require 'date'
def print_usage_and_exit
puts 'Usage: ruby completed_tasks.rb PATH_TO_ASANA_CSV YEAR_TO_PROCESS'
exit
end
def parse_argruments
arguments = ARGV
print_usage_and_exit if arguments.length != 2
csv_file = arguments.first
unless File.exist?(csv_file)
puts "ERROR: #{csv_file} does not exist."
print_usage_and_exit
end
year = arguments.last
if year.to_i.zero?
puts "ERROR: #{year} is not a valid year."
print_usage_and_exit
end
{
csv_file: csv_file,
year: year.to_i
}
end
def empty_string_if_nil(input)
return '' if input.nil?
input
end
def parse_date_unless_nil(input)
return nil if input.nil?
Date.parse(input)
end
def split_possibly_nil_string(input)
return [] if input.nil?
input.split(',')
end
def parse_tasks(csv_file_path)
raw_rows = CSV.read(csv_file_path, headers: :first_row)
raw_rows.map do |row|
{
id: row['Task ID'],
created_at: parse_date_unless_nil(row['Created At']),
completed_at: parse_date_unless_nil(row['Completed At']),
name: row['Name'],
due_date: parse_date_unless_nil(row['Due Date']),
notes: row['Notes'],
projects: split_possibly_nil_string(row['Projects']),
parent_task: empty_string_if_nil(row['Parent Task']),
tags: split_possibly_nil_string(row['Tags'])
}
end
end
def process_completed_tasks_for_year(year, tasks)
relevant_tasks = tasks.select do |task|
task[:parent_task].empty? && !task[:completed_at].nil? && task[:completed_at].year == year
end
tasks_by_week = Hash.new { |hash, key| hash[key] = [] }
relevant_tasks.each do |task|
tasks_by_week[task[:completed_at].cweek] << task
end
tasks_by_week
end
def console_printer(tasks_by_week, year)
tasks_by_week.each do |week, tasks|
puts ''
puts ' ========================================================='
puts " | Completed Tasks for the Week of #{Date.commercial(year, week)} |"
puts ' ========================================================='
tasks.each do |task|
puts "#{task[:name]}"
end
end
end
def html_printer(tasks_by_week, year)
puts <<-HTML
<!DOCTYPE html>
<html>
<head>
<title>Completed Tasks for the Year of #{year}</title>
<style>
h1, h2, th, td {
font-family: 'Arial', sans-serif;
}
.center {
text-align: center;
}
table {
margin-left: auto;
margin-right: auto;
}
th {
padding: 0 12px 0 12px;
}
</style>
</head>
<body>
<h1 class='center'>Completed Tasks for #{year}</h1>
HTML
weeks = tasks_by_week.keys.sort.reverse
weeks.each do |week|
tasks = tasks_by_week[week].sort_by { |task| task[:completed_at] }.reverse
puts "<h2 class='center'>Completed Tasks for the Week of #{Date.commercial(year, week)}</h2>"
puts "<table><thead><th>Task</th><th>Created On</th><th>Completed On</th><th>Days Taken</th></thead><tbody>"
tasks.each do |task|
puts '<tr>'
puts "<td>#{task[:name]}</td>"
puts "<td class='center'>#{task[:created_at]}</td>"
puts "<td class='center'>#{task[:completed_at]}</td>"
puts "<td class='center'>#{(task[:completed_at] - task[:created_at]).to_i}</td>"
puts '</tr>'
end
puts "</tbody></table>"
end
puts <<-HTML
</body>
</html>
HTML
end
def main
arguments = parse_argruments
tasks = parse_tasks(arguments[:csv_file])
tasks_by_week = process_completed_tasks_for_year(arguments[:year], tasks)
html_printer(tasks_by_week, arguments[:year])
end
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment