tps_reporter 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/HISTORY.md +4 -0
 - data/README.md +86 -0
 - data/Rakefile +14 -0
 - data/bin/tps +145 -0
 - data/data/index.haml +182 -0
 - data/data/sample.yml +18 -0
 - data/lib/tps/cli_reporter.rb +76 -0
 - data/lib/tps/task.rb +166 -0
 - data/lib/tps/task_list.rb +17 -0
 - data/lib/tps/version.rb +5 -0
 - data/lib/tps.rb +34 -0
 - data/test/hello.yml +42 -0
 - data/test/test_helper.rb +13 -0
 - data/test/tps_test.rb +71 -0
 - data/tps_reporter.gemspec +16 -0
 - metadata +83 -0
 
    
        data/HISTORY.md
    ADDED
    
    
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,86 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Task progress sheet reporter
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            We often need to make regular reports of things done for our projects at work. I
         
     | 
| 
      
 6 
     | 
    
         
            +
            hate doing these by hand. This tool lets us build these reports from YAML files.
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            Get started
         
     | 
| 
      
 9 
     | 
    
         
            +
            -----------
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            Install TPS (Ruby):
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                $ gem install tps_reporter
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            ...then generate a sample file. (or create `tasks.yml` based on [this][s]
         
     | 
| 
      
 16 
     | 
    
         
            +
            sample.)
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                $ tps sample
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            Edit it, then generate the report:
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                $ tps open
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            [s]: https://github.com/rstacruz/tps_reporter/blob/master/data/sample.yml
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            Format
         
     | 
| 
      
 27 
     | 
    
         
            +
            ------
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            The tasks file, usually `tasks.yml`, is in YAML format.
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            Tasks are always keys (ie, they all end in `:`). They can be nested as far
         
     | 
| 
      
 32 
     | 
    
         
            +
            as you like.
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            ``` yaml
         
     | 
| 
      
 35 
     | 
    
         
            +
            Edit users:
         
     | 
| 
      
 36 
     | 
    
         
            +
              Register and signup:
         
     | 
| 
      
 37 
     | 
    
         
            +
              Login and logout:
         
     | 
| 
      
 38 
     | 
    
         
            +
            ```
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            To define task metadata for *leaf* tasks, add it as an array inside the task:
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            ``` yaml
         
     | 
| 
      
 43 
     | 
    
         
            +
            Manage employees: [done]
         
     | 
| 
      
 44 
     | 
    
         
            +
            ```
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            Or for *branch* tasks, add it under the `_` task:
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            ``` yaml
         
     | 
| 
      
 49 
     | 
    
         
            +
            Manage employees:
         
     | 
| 
      
 50 
     | 
    
         
            +
              _: [done]
         
     | 
| 
      
 51 
     | 
    
         
            +
              Creating employees:
         
     | 
| 
      
 52 
     | 
    
         
            +
              Editing employees:
         
     | 
| 
      
 53 
     | 
    
         
            +
            ```
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            The metadata is just a simple YAML array that you can conveniently define using
         
     | 
| 
      
 56 
     | 
    
         
            +
            `[tag1, tag2, etc]`.  Allowed metadata are:
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
             - `done`
         
     | 
| 
      
 59 
     | 
    
         
            +
             - `in progress`
         
     | 
| 
      
 60 
     | 
    
         
            +
             - `pt/2839478` *(Pivotal tracker ID. Links to a Pivotal tracker story.)*
         
     | 
| 
      
 61 
     | 
    
         
            +
             - `0pt` *(points; influences percentage. needs to end in __pt__ or __pts__.)*
         
     | 
| 
      
 62 
     | 
    
         
            +
             - `10%` *(task progress. implies __in progress__.)*
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            Example:
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            ``` yaml
         
     | 
| 
      
 67 
     | 
    
         
            +
              Creating employees: [40%]
         
     | 
| 
      
 68 
     | 
    
         
            +
              Editing employees: [done, 2pts]
         
     | 
| 
      
 69 
     | 
    
         
            +
            ```
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
            Exporting to PDF or image
         
     | 
| 
      
 72 
     | 
    
         
            +
            -------------------------
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
            If you're on a Mac, install [Paparazzi](http://derailer.org/paparazzi)
         
     | 
| 
      
 75 
     | 
    
         
            +
            and use the `tps paparazzi` command. This will open the report in Paparazzi
         
     | 
| 
      
 76 
     | 
    
         
            +
            where you can save or copy it as an image, or PDF.
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            Command line
         
     | 
| 
      
 79 
     | 
    
         
            +
            ------------
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
            There's also a command line reporter that you can access via `tps print`. It
         
     | 
| 
      
 82 
     | 
    
         
            +
            looks like this:
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
            ![Comamnd line reporter][cli]
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
            [cli]: https://img.skitch.com/20120204-ccb2guerhrjmj3rht3e4ies4ur.png
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            desc "Invokes the test suite in multiple RVM environments"
         
     | 
| 
      
 2 
     | 
    
         
            +
            task :'test!' do
         
     | 
| 
      
 3 
     | 
    
         
            +
              # Override this by adding RVM_TEST_ENVS=".." in .rvmrc
         
     | 
| 
      
 4 
     | 
    
         
            +
              envs = ENV['RVM_TEST_ENVS'] || '1.9.2@sinatra,1.8.7@sinatra'
         
     | 
| 
      
 5 
     | 
    
         
            +
              puts "* Testing in the following RVM environments: #{envs.gsub(',', ', ')}"
         
     | 
| 
      
 6 
     | 
    
         
            +
              system "rvm #{envs} rake test" or abort
         
     | 
| 
      
 7 
     | 
    
         
            +
            end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            desc "Runs tests"
         
     | 
| 
      
 10 
     | 
    
         
            +
            task :test do
         
     | 
| 
      
 11 
     | 
    
         
            +
              Dir['test/*_test.rb'].each { |f| load f }
         
     | 
| 
      
 12 
     | 
    
         
            +
            end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            task :default => :test
         
     | 
    
        data/bin/tps
    ADDED
    
    | 
         @@ -0,0 +1,145 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            $:.unshift File.expand_path('../../lib', __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'tps'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Params
         
     | 
| 
      
 6 
     | 
    
         
            +
              def extract(what)   i = index(what) and slice!(i, 2)[1] end;
         
     | 
| 
      
 7 
     | 
    
         
            +
              def first_is(what)  shift  if first == what; end
         
     | 
| 
      
 8 
     | 
    
         
            +
            end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            ARGV.extend Params
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            module TPS::Command
         
     | 
| 
      
 13 
     | 
    
         
            +
              extend self
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              def help
         
     | 
| 
      
 16 
     | 
    
         
            +
                puts "Usage: tps <command> [-f filename] [-o output]"
         
     | 
| 
      
 17 
     | 
    
         
            +
                puts ""
         
     | 
| 
      
 18 
     | 
    
         
            +
                puts "Commands:"
         
     | 
| 
      
 19 
     | 
    
         
            +
                puts "   html                 Builds HTML"
         
     | 
| 
      
 20 
     | 
    
         
            +
                puts "   open                 Builds HTML and opens it in the browser"
         
     | 
| 
      
 21 
     | 
    
         
            +
                puts "   paparazzi            Builds HTML and opens it in Paparazzi (Mac)"
         
     | 
| 
      
 22 
     | 
    
         
            +
                puts "   print                Prints the report to the console."
         
     | 
| 
      
 23 
     | 
    
         
            +
                puts ""
         
     | 
| 
      
 24 
     | 
    
         
            +
                puts "Options (optional):"
         
     | 
| 
      
 25 
     | 
    
         
            +
                puts "  -f FILE               Specifies the input file. Defaults to tasks.yml."
         
     | 
| 
      
 26 
     | 
    
         
            +
                puts "  -o/--output OUTPUT    Specifies the output HTML file."
         
     | 
| 
      
 27 
     | 
    
         
            +
                puts ""
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              def html
         
     | 
| 
      
 31 
     | 
    
         
            +
                t = get_tasks
         
     | 
| 
      
 32 
     | 
    
         
            +
                path = output { |file| file.write t.to_html }
         
     | 
| 
      
 33 
     | 
    
         
            +
                info "Wrote to '#{path}'."
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                path
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              def sample
         
     | 
| 
      
 39 
     | 
    
         
            +
                require 'fileutils'
         
     | 
| 
      
 40 
     | 
    
         
            +
                fn = tasks_filename
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                if File.exists?(fn)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  err "Error: #{fn} already exists."
         
     | 
| 
      
 44 
     | 
    
         
            +
                  exit 130
         
     | 
| 
      
 45 
     | 
    
         
            +
                end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                FileUtils.cp TPS.root('data', 'sample.yml'), fn
         
     | 
| 
      
 48 
     | 
    
         
            +
                info "Created '#{fn}'."
         
     | 
| 
      
 49 
     | 
    
         
            +
                info "Edit it, then use `tps html` to generate HTML from it."
         
     | 
| 
      
 50 
     | 
    
         
            +
              end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              def open
         
     | 
| 
      
 53 
     | 
    
         
            +
                fn = html
         
     | 
| 
      
 54 
     | 
    
         
            +
                open_file fn
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
              def paparazzi
         
     | 
| 
      
 58 
     | 
    
         
            +
                fn = html
         
     | 
| 
      
 59 
     | 
    
         
            +
                open_file "paparazzi:(minwidth=1,minheight=1)#{fn}"
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              def print
         
     | 
| 
      
 63 
     | 
    
         
            +
                t = get_tasks
         
     | 
| 
      
 64 
     | 
    
         
            +
                reporter = TPS::CliReporter.new(t)
         
     | 
| 
      
 65 
     | 
    
         
            +
                reporter.print
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            private
         
     | 
| 
      
 69 
     | 
    
         
            +
              def err(str)
         
     | 
| 
      
 70 
     | 
    
         
            +
                $stdout << "#{str}\n"
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
              def info(str)
         
     | 
| 
      
 74 
     | 
    
         
            +
                puts str
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
              def tasks_filename
         
     | 
| 
      
 78 
     | 
    
         
            +
                ARGV.extract('-f') ||
         
     | 
| 
      
 79 
     | 
    
         
            +
                ENV['TPS_FILE'] ||
         
     | 
| 
      
 80 
     | 
    
         
            +
                Dir['./{Tasksfile,tasks.yml}'].first ||
         
     | 
| 
      
 81 
     | 
    
         
            +
                "tasks.yml"
         
     | 
| 
      
 82 
     | 
    
         
            +
              end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
              def output(&blk)
         
     | 
| 
      
 85 
     | 
    
         
            +
                fn = ARGV.extract('--output') || ARGV.extract('-o') || get_temp_filename
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                File.open(fn, 'w', &blk)
         
     | 
| 
      
 88 
     | 
    
         
            +
                fn
         
     | 
| 
      
 89 
     | 
    
         
            +
              end
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
              def get_tasks
         
     | 
| 
      
 92 
     | 
    
         
            +
                fn = tasks_filename
         
     | 
| 
      
 93 
     | 
    
         
            +
                if !File.exists?(fn)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  err "No tasks file found."
         
     | 
| 
      
 95 
     | 
    
         
            +
                  err "Create a sample using `tsp sample`."
         
     | 
| 
      
 96 
     | 
    
         
            +
                  exit 256
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                begin
         
     | 
| 
      
 100 
     | 
    
         
            +
                  TPS::TaskList.new yaml: fn
         
     | 
| 
      
 101 
     | 
    
         
            +
                rescue => e
         
     | 
| 
      
 102 
     | 
    
         
            +
                  err "Parse error: #{e.message}"
         
     | 
| 
      
 103 
     | 
    
         
            +
                  exit 256
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
              end
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
              def opener
         
     | 
| 
      
 108 
     | 
    
         
            +
                program = %w[open xdg-open start].detect { |cmd| `which #{cmd}` }
         
     | 
| 
      
 109 
     | 
    
         
            +
                unless program
         
     | 
| 
      
 110 
     | 
    
         
            +
                  err "No opener found."
         
     | 
| 
      
 111 
     | 
    
         
            +
                  exit 256
         
     | 
| 
      
 112 
     | 
    
         
            +
                end
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                program
         
     | 
| 
      
 115 
     | 
    
         
            +
              end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
              def open_file(file)
         
     | 
| 
      
 118 
     | 
    
         
            +
                require 'shellwords'
         
     | 
| 
      
 119 
     | 
    
         
            +
                system "#{opener} #{file.shellescape}"
         
     | 
| 
      
 120 
     | 
    
         
            +
              end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
              def get_temp_filename
         
     | 
| 
      
 123 
     | 
    
         
            +
                require 'tmpdir'
         
     | 
| 
      
 124 
     | 
    
         
            +
                File.join Dir.tmpdir, "tasks-#{'%x' % [rand * 2**48]}.html"
         
     | 
| 
      
 125 
     | 
    
         
            +
              end
         
     | 
| 
      
 126 
     | 
    
         
            +
            end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
            if ARGV.first_is('html')
         
     | 
| 
      
 129 
     | 
    
         
            +
              TPS::Command.html
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
            elsif ARGV.first_is('open')
         
     | 
| 
      
 132 
     | 
    
         
            +
              TPS::Command.open
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
            elsif ARGV.first_is('sample')
         
     | 
| 
      
 135 
     | 
    
         
            +
              TPS::Command.sample
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
            elsif ARGV.first_is('print')
         
     | 
| 
      
 138 
     | 
    
         
            +
              TPS::Command.print
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
            elsif ARGV.first_is('paparazzi')
         
     | 
| 
      
 141 
     | 
    
         
            +
              TPS::Command.paparazzi
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
            else
         
     | 
| 
      
 144 
     | 
    
         
            +
              TPS::Command.help
         
     | 
| 
      
 145 
     | 
    
         
            +
            end
         
     | 
    
        data/data/index.haml
    ADDED
    
    | 
         @@ -0,0 +1,182 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            !!! 5
         
     | 
| 
      
 2 
     | 
    
         
            +
            %html
         
     | 
| 
      
 3 
     | 
    
         
            +
              %head
         
     | 
| 
      
 4 
     | 
    
         
            +
                %script{src: "http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js"}
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                :javascript
         
     | 
| 
      
 7 
     | 
    
         
            +
                  $("td").live('click', function() {
         
     | 
| 
      
 8 
     | 
    
         
            +
                    $(this).closest('tr').toggleClass('highlight');
         
     | 
| 
      
 9 
     | 
    
         
            +
                  });
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                %style
         
     | 
| 
      
 12 
     | 
    
         
            +
                  :plain
         
     | 
| 
      
 13 
     | 
    
         
            +
                    body {
         
     | 
| 
      
 14 
     | 
    
         
            +
                      padding: 0;
         
     | 
| 
      
 15 
     | 
    
         
            +
                      margin: 0; }
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                    body, td {
         
     | 
| 
      
 18 
     | 
    
         
            +
                      font-family: pt sans, sans-serif;
         
     | 
| 
      
 19 
     | 
    
         
            +
                      color: #333;
         
     | 
| 
      
 20 
     | 
    
         
            +
                      line-height: 13.5pt;
         
     | 
| 
      
 21 
     | 
    
         
            +
                      font-size: 9pt; }
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                    table {
         
     | 
| 
      
 24 
     | 
    
         
            +
                      border: solid 2px #aaa;
         
     | 
| 
      
 25 
     | 
    
         
            +
                      padding: 2px;
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                      background: #fafafa;
         
     | 
| 
      
 28 
     | 
    
         
            +
                      margin: 0;
         
     | 
| 
      
 29 
     | 
    
         
            +
                      width: 600px;
         
     | 
| 
      
 30 
     | 
    
         
            +
                      border-collapse: collapse; }
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    table td, table th {
         
     | 
| 
      
 33 
     | 
    
         
            +
                      padding: 5px 10px;
         
     | 
| 
      
 34 
     | 
    
         
            +
                      border-top: solid 1px #eee; }
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    /* Columns */
         
     | 
| 
      
 37 
     | 
    
         
            +
                    tr>.task { width: 50%; text-align: left; }
         
     | 
| 
      
 38 
     | 
    
         
            +
                    tr>.points { width: 9%; }
         
     | 
| 
      
 39 
     | 
    
         
            +
                    tr>.progress { width: 18%; }
         
     | 
| 
      
 40 
     | 
    
         
            +
                    tr>.owner { display: none; }
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                    /* Indentation */
         
     | 
| 
      
 43 
     | 
    
         
            +
                    .level-1 .task { padding-left: 25px; }
         
     | 
| 
      
 44 
     | 
    
         
            +
                    .level-2 .task { padding-left: 50px; }
         
     | 
| 
      
 45 
     | 
    
         
            +
                    .level-3 .task { padding-left: 75px; }
         
     | 
| 
      
 46 
     | 
    
         
            +
                    .level-4 .task { padding-left: 100px; }
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                    /* Overrides for parents */
         
     | 
| 
      
 49 
     | 
    
         
            +
                    .milestone td.task,
         
     | 
| 
      
 50 
     | 
    
         
            +
                    .feature td.task {
         
     | 
| 
      
 51 
     | 
    
         
            +
                      font-weight: bold;
         
     | 
| 
      
 52 
     | 
    
         
            +
                      font-size: 1.1em; }
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                    tr.milestone td,
         
     | 
| 
      
 55 
     | 
    
         
            +
                    tr.feature td {
         
     | 
| 
      
 56 
     | 
    
         
            +
                      border-top: solid 1px #888; }
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                    tr .progress .bar {
         
     | 
| 
      
 59 
     | 
    
         
            +
                      display: none; }
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                    tr.milestone .progress .bar,
         
     | 
| 
      
 62 
     | 
    
         
            +
                    tr.feature .progress .bar {
         
     | 
| 
      
 63 
     | 
    
         
            +
                      display: block; }
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                    tr td.points>* {
         
     | 
| 
      
 66 
     | 
    
         
            +
                      display: none; }
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                    tr.milestone td.points>*,
         
     | 
| 
      
 69 
     | 
    
         
            +
                    tr.feature td.points>* {
         
     | 
| 
      
 70 
     | 
    
         
            +
                      display: inline; }
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                    /* Header */
         
     | 
| 
      
 73 
     | 
    
         
            +
                    thead {
         
     | 
| 
      
 74 
     | 
    
         
            +
                      display: none; }
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                    th {
         
     | 
| 
      
 77 
     | 
    
         
            +
                      color: #888; }
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                    /* Zebra */
         
     | 
| 
      
 80 
     | 
    
         
            +
                    tr td,
         
     | 
| 
      
 81 
     | 
    
         
            +
                    tr {
         
     | 
| 
      
 82 
     | 
    
         
            +
                      background: #ffffff; }
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                    tr:nth-child(odd) td,
         
     | 
| 
      
 85 
     | 
    
         
            +
                    tr:nth-child(odd) {
         
     | 
| 
      
 86 
     | 
    
         
            +
                      background: #fafafa; }
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                    tr.highlight,
         
     | 
| 
      
 89 
     | 
    
         
            +
                    tr.highlight td {
         
     | 
| 
      
 90 
     | 
    
         
            +
                      background: #fafae0; }
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                    /* Status box */
         
     | 
| 
      
 93 
     | 
    
         
            +
                    span.status {
         
     | 
| 
      
 94 
     | 
    
         
            +
                      display: inline-block;
         
     | 
| 
      
 95 
     | 
    
         
            +
                      width: 12px;
         
     | 
| 
      
 96 
     | 
    
         
            +
                      height: 12px;
         
     | 
| 
      
 97 
     | 
    
         
            +
                      margin: 0 5px 0 0;
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                      border-radius: 2px;
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                      position: relative;
         
     | 
| 
      
 102 
     | 
    
         
            +
                      top: 2px;
         
     | 
| 
      
 103 
     | 
    
         
            +
                      background: #ddd; }
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    span.status.in_progress {
         
     | 
| 
      
 106 
     | 
    
         
            +
                      background: #ea3; }
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                    span.status.done {
         
     | 
| 
      
 109 
     | 
    
         
            +
                      background: #393; }
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                    /* Progress */
         
     | 
| 
      
 112 
     | 
    
         
            +
                    .progress .number {
         
     | 
| 
      
 113 
     | 
    
         
            +
                      display: none; }
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                    .progress .bar {
         
     | 
| 
      
 116 
     | 
    
         
            +
                      height: 10px;
         
     | 
| 
      
 117 
     | 
    
         
            +
                      border-radius: 5px;
         
     | 
| 
      
 118 
     | 
    
         
            +
                      background: #ddd; }
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                    .progress .bar span {
         
     | 
| 
      
 121 
     | 
    
         
            +
                      display: block;
         
     | 
| 
      
 122 
     | 
    
         
            +
                      height: 10px;
         
     | 
| 
      
 123 
     | 
    
         
            +
                      border-radius: 5px;
         
     | 
| 
      
 124 
     | 
    
         
            +
                      background: #888; }
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                    a.meta {
         
     | 
| 
      
 127 
     | 
    
         
            +
                      font-size: 0.9em;
         
     | 
| 
      
 128 
     | 
    
         
            +
                      text-decoration: none;
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                      background: #ddd;
         
     | 
| 
      
 131 
     | 
    
         
            +
                      padding: 1px 3px;
         
     | 
| 
      
 132 
     | 
    
         
            +
                      border-radius: 2px;
         
     | 
| 
      
 133 
     | 
    
         
            +
                      border-bottom: solid 1px #ccc;
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                      margin: 0 5px;
         
     | 
| 
      
 136 
     | 
    
         
            +
                      color: #777; }
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                    /* Progress */
         
     | 
| 
      
 139 
     | 
    
         
            +
                    td.points {
         
     | 
| 
      
 140 
     | 
    
         
            +
                      text-align: left;
         
     | 
| 
      
 141 
     | 
    
         
            +
                      font-size: 0.9em; }
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                    td.points .points.done {
         
     | 
| 
      
 144 
     | 
    
         
            +
                      font-weight: bold; }
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                    td.points .of,
         
     | 
| 
      
 147 
     | 
    
         
            +
                    td.points .points.total {
         
     | 
| 
      
 148 
     | 
    
         
            +
                      color: #888; }
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
              %body
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                %table
         
     | 
| 
      
 153 
     | 
    
         
            +
                  %thead
         
     | 
| 
      
 154 
     | 
    
         
            +
                    %tr
         
     | 
| 
      
 155 
     | 
    
         
            +
                      %th.task Task
         
     | 
| 
      
 156 
     | 
    
         
            +
                      %th.owner Owner
         
     | 
| 
      
 157 
     | 
    
         
            +
                      %th.progress Progress
         
     | 
| 
      
 158 
     | 
    
         
            +
                      %th.points Points
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
                  - list.walk do |task, recurse|
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
                    %tr{class: "level-#{task.level} #{task.tasks? ? 'parent' : 'leaf'} #{'root' if task.root?} #{'feature' if task.feature?} #{'milestone' if task.milestone?}"}
         
     | 
| 
      
 163 
     | 
    
         
            +
                      %td.task
         
     | 
| 
      
 164 
     | 
    
         
            +
                        %span.status{class: "#{task.status}"}
         
     | 
| 
      
 165 
     | 
    
         
            +
                        = task
         
     | 
| 
      
 166 
     | 
    
         
            +
                        - if task.pivotal_id
         
     | 
| 
      
 167 
     | 
    
         
            +
                          %a.meta{href: task.pivotal_url}= "Pivotal: #{task.pivotal_id}"
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                      %td.owner
         
     | 
| 
      
 170 
     | 
    
         
            +
                        = task.owner
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                      %td.progress
         
     | 
| 
      
 173 
     | 
    
         
            +
                        .bar
         
     | 
| 
      
 174 
     | 
    
         
            +
                          %span{style: "width: #{(task.percent*95+5).to_i}%"}
         
     | 
| 
      
 175 
     | 
    
         
            +
                        %span.number= "#{(task.percent*100).to_i}%"
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                      %td.points
         
     | 
| 
      
 178 
     | 
    
         
            +
                        %span.points.done= task.points_done.round(1).to_s.gsub(/\.0+$/,'')
         
     | 
| 
      
 179 
     | 
    
         
            +
                        %span.of of
         
     | 
| 
      
 180 
     | 
    
         
            +
                        %span.points.total= task.points.round(1).to_s.gsub(/\.0+$/,'')
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                    - recurse.call  if recurse
         
     | 
    
        data/data/sample.yml
    ADDED
    
    | 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Version 1:
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              User signup:
         
     | 
| 
      
 4 
     | 
    
         
            +
                Register for an account:
         
     | 
| 
      
 5 
     | 
    
         
            +
                Log in: [done]
         
     | 
| 
      
 6 
     | 
    
         
            +
                Forget password:
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              Manage users:
         
     | 
| 
      
 9 
     | 
    
         
            +
                _: [in progress]
         
     | 
| 
      
 10 
     | 
    
         
            +
                Create users: [in progress]
         
     | 
| 
      
 11 
     | 
    
         
            +
                Delete users:
         
     | 
| 
      
 12 
     | 
    
         
            +
                User profile page:
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              Blog:
         
     | 
| 
      
 15 
     | 
    
         
            +
                Creating new posts: [done]
         
     | 
| 
      
 16 
     | 
    
         
            +
                Comments: [done]
         
     | 
| 
      
 17 
     | 
    
         
            +
                Moderating comments: [done]
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,76 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module TPS
         
     | 
| 
      
 2 
     | 
    
         
            +
              class CliReporter
         
     | 
| 
      
 3 
     | 
    
         
            +
                attr_reader :task
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(task)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @task = task
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                def print
         
     | 
| 
      
 10 
     | 
    
         
            +
                  puts report
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                def report
         
     | 
| 
      
 14 
     | 
    
         
            +
                  re = ""
         
     | 
| 
      
 15 
     | 
    
         
            +
                  task.walk do |t, recurse|
         
     | 
| 
      
 16 
     | 
    
         
            +
                    re += CliReporter.new(t).report_task
         
     | 
| 
      
 17 
     | 
    
         
            +
                    recurse.call  if recurse
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  re
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                def report_task
         
     | 
| 
      
 23 
     | 
    
         
            +
                  indent = ' ' * (4 * task.level)
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  # Columns
         
     | 
| 
      
 26 
     | 
    
         
            +
                  c1 = "%s %s %s" % [ indent, status, task.name ]
         
     | 
| 
      
 27 
     | 
    
         
            +
                  c2 = if task.feature? || task.milestone?
         
     | 
| 
      
 28 
     | 
    
         
            +
                         progress
         
     | 
| 
      
 29 
     | 
    
         
            +
                      else
         
     | 
| 
      
 30 
     | 
    
         
            +
                        ' '*12
         
     | 
| 
      
 31 
     | 
    
         
            +
                      end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  pref = c("-"*80, 30)+"\n"  if task.feature?
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  # Put together
         
     | 
| 
      
 36 
     | 
    
         
            +
                  "#{pref}" + "%-95s%s\n" % [ c1, c2 ]
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                def color
         
     | 
| 
      
 40 
     | 
    
         
            +
                  if task.done?
         
     | 
| 
      
 41 
     | 
    
         
            +
                    32
         
     | 
| 
      
 42 
     | 
    
         
            +
                  elsif task.in_progress?
         
     | 
| 
      
 43 
     | 
    
         
            +
                    34
         
     | 
| 
      
 44 
     | 
    
         
            +
                  else
         
     | 
| 
      
 45 
     | 
    
         
            +
                    30
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                def status
         
     | 
| 
      
 50 
     | 
    
         
            +
                  l = c("(", 30)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  r = c(")", 30)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  if task.done?
         
     | 
| 
      
 53 
     | 
    
         
            +
                     l + c('##', color) + r
         
     | 
| 
      
 54 
     | 
    
         
            +
                  elsif task.in_progress?
         
     | 
| 
      
 55 
     | 
    
         
            +
                    l + c('--', color) + r
         
     | 
| 
      
 56 
     | 
    
         
            +
                  else
         
     | 
| 
      
 57 
     | 
    
         
            +
                    l + c('  ', color) + r
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def progress
         
     | 
| 
      
 62 
     | 
    
         
            +
                  max = 12
         
     | 
| 
      
 63 
     | 
    
         
            +
                  len = (task.percent * max).to_i
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                  prog = ("%-#{max}s" % ["="*len])
         
     | 
| 
      
 66 
     | 
    
         
            +
                  prog = c("|"*len, color) + c("."*(max-len), 30)
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                  prog
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
              private
         
     | 
| 
      
 72 
     | 
    
         
            +
                def c(str, c=nil)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  c ? "\033[#{c}m#{str}\033[0m" : str
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/tps/task.rb
    ADDED
    
    | 
         @@ -0,0 +1,166 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'yaml'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'tilt'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module TPS
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Task
         
     | 
| 
      
 6 
     | 
    
         
            +
                attr_reader :name     # "Create metrics"
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :tasks    # Array of Tasks
         
     | 
| 
      
 8 
     | 
    
         
            +
                attr_reader :owner
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_reader :pivotal_id
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_reader :parent
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def initialize(parent, name, data=nil)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @name   = name
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @tasks  = Array.new
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @parent = parent
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  if data.is_a?(Array)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    tags = data
         
     | 
| 
      
 19 
     | 
    
         
            +
                    tasks = nil
         
     | 
| 
      
 20 
     | 
    
         
            +
                  elsif data.is_a?(Hash) && data['_']
         
     | 
| 
      
 21 
     | 
    
         
            +
                    tags = data.delete('_')
         
     | 
| 
      
 22 
     | 
    
         
            +
                    tasks = data
         
     | 
| 
      
 23 
     | 
    
         
            +
                  else
         
     | 
| 
      
 24 
     | 
    
         
            +
                    tags = Array.new
         
     | 
| 
      
 25 
     | 
    
         
            +
                    tasks = data
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  # Parse tags.
         
     | 
| 
      
 29 
     | 
    
         
            +
                  tags.each do |t|
         
     | 
| 
      
 30 
     | 
    
         
            +
                    # [done]
         
     | 
| 
      
 31 
     | 
    
         
            +
                    if ['done', 'ok'].include?(t)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      @status = :done
         
     | 
| 
      
 33 
     | 
    
         
            +
                    elsif ['in progress', '...'].include?(t)
         
     | 
| 
      
 34 
     | 
    
         
            +
                      @status = :in_progress
         
     | 
| 
      
 35 
     | 
    
         
            +
                    # [@rstacruz]
         
     | 
| 
      
 36 
     | 
    
         
            +
                    elsif t =~ /^@/
         
     | 
| 
      
 37 
     | 
    
         
            +
                      @owner = t[1..-1]
         
     | 
| 
      
 38 
     | 
    
         
            +
                    # [pt/28394] -- Pivotal tracker
         
     | 
| 
      
 39 
     | 
    
         
            +
                    elsif t =~ /^pt\/(.*)$/i
         
     | 
| 
      
 40 
     | 
    
         
            +
                      @pivotal_id = $1.strip
         
     | 
| 
      
 41 
     | 
    
         
            +
                    # [50%] -- percentage
         
     | 
| 
      
 42 
     | 
    
         
            +
                    elsif t =~ /^([\d\.]+)%$/
         
     | 
| 
      
 43 
     | 
    
         
            +
                      @status = :in_progress
         
     | 
| 
      
 44 
     | 
    
         
            +
                      @percent = $1.strip.to_f / 100
         
     | 
| 
      
 45 
     | 
    
         
            +
                    # [0pt] -- points
         
     | 
| 
      
 46 
     | 
    
         
            +
                    elsif t =~ /^([\d\.]+)pts?/i
         
     | 
| 
      
 47 
     | 
    
         
            +
                      @points = $1.strip.to_f
         
     | 
| 
      
 48 
     | 
    
         
            +
                    end
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  @tasks = tasks.map { |task, data| Task.new self, task, data }  if tasks
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  n = @name.to_s.downcase
         
     | 
| 
      
 54 
     | 
    
         
            +
                  @milestone = root? && (n.include?('milestone') || n.include?('version'))
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                def status
         
     | 
| 
      
 58 
     | 
    
         
            +
                  # If no status is given, infer the status based on tasks.
         
     | 
| 
      
 59 
     | 
    
         
            +
                  if !@status && tasks?
         
     | 
| 
      
 60 
     | 
    
         
            +
                    if all_tasks_done?
         
     | 
| 
      
 61 
     | 
    
         
            +
                      return :done
         
     | 
| 
      
 62 
     | 
    
         
            +
                    elsif has_started_tasks?
         
     | 
| 
      
 63 
     | 
    
         
            +
                      return :in_progress
         
     | 
| 
      
 64 
     | 
    
         
            +
                    end
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  @status or :unstarted
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                def points
         
     | 
| 
      
 71 
     | 
    
         
            +
                  if @points
         
     | 
| 
      
 72 
     | 
    
         
            +
                    @points
         
     | 
| 
      
 73 
     | 
    
         
            +
                  elsif tasks?
         
     | 
| 
      
 74 
     | 
    
         
            +
                    tasks.inject(0.0) { |pts, task| pts + task.points }
         
     | 
| 
      
 75 
     | 
    
         
            +
                  else
         
     | 
| 
      
 76 
     | 
    
         
            +
                    1.0
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                def points_done
         
     | 
| 
      
 81 
     | 
    
         
            +
                  points * percent
         
     | 
| 
      
 82 
     | 
    
         
            +
                end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                def all_tasks_done?
         
     | 
| 
      
 85 
     | 
    
         
            +
                  tasks? and !tasks.any? { |t| ! t.done? }
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                def has_started_tasks?
         
     | 
| 
      
 89 
     | 
    
         
            +
                  tasks? and tasks.any? { |t| t.in_progress? or t.done? }
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 93 
     | 
    
         
            +
                  name
         
     | 
| 
      
 94 
     | 
    
         
            +
                end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                def done?
         
     | 
| 
      
 97 
     | 
    
         
            +
                  status == :done
         
     | 
| 
      
 98 
     | 
    
         
            +
                end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                def in_progress?
         
     | 
| 
      
 101 
     | 
    
         
            +
                  status == :in_progress
         
     | 
| 
      
 102 
     | 
    
         
            +
                end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                def unstarted?
         
     | 
| 
      
 105 
     | 
    
         
            +
                  status == :unstarted
         
     | 
| 
      
 106 
     | 
    
         
            +
                end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                def tasks?
         
     | 
| 
      
 109 
     | 
    
         
            +
                  tasks.any?
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                def pivotal_url
         
     | 
| 
      
 113 
     | 
    
         
            +
                  "https://www.pivotaltracker.com/story/show/#{pivotal_id}"  if pivotal_id
         
     | 
| 
      
 114 
     | 
    
         
            +
                end
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                def percent
         
     | 
| 
      
 117 
     | 
    
         
            +
                  if done?
         
     | 
| 
      
 118 
     | 
    
         
            +
                    1.0
         
     | 
| 
      
 119 
     | 
    
         
            +
                  elsif @percent
         
     | 
| 
      
 120 
     | 
    
         
            +
                    @percent
         
     | 
| 
      
 121 
     | 
    
         
            +
                  elsif tasks?
         
     | 
| 
      
 122 
     | 
    
         
            +
                    total = tasks.inject(0.0) { |pts, task| pts + task.points }
         
     | 
| 
      
 123 
     | 
    
         
            +
                    tasks.inject(0) { |i, task| i + task.points_done } / total
         
     | 
| 
      
 124 
     | 
    
         
            +
                  else
         
     | 
| 
      
 125 
     | 
    
         
            +
                    in_progress? ? 0.5 : 0
         
     | 
| 
      
 126 
     | 
    
         
            +
                  end
         
     | 
| 
      
 127 
     | 
    
         
            +
                end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                def level
         
     | 
| 
      
 130 
     | 
    
         
            +
                  parent ? parent.level + 1 : 0
         
     | 
| 
      
 131 
     | 
    
         
            +
                end
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                def root?
         
     | 
| 
      
 134 
     | 
    
         
            +
                  ! parent
         
     | 
| 
      
 135 
     | 
    
         
            +
                end
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                def feature?
         
     | 
| 
      
 138 
     | 
    
         
            +
                  root? or parent.milestone?
         
     | 
| 
      
 139 
     | 
    
         
            +
                end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                def milestone?
         
     | 
| 
      
 142 
     | 
    
         
            +
                  !! @milestone
         
     | 
| 
      
 143 
     | 
    
         
            +
                end
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
                # - list.walk do |task, recurse|
         
     | 
| 
      
 146 
     | 
    
         
            +
                #   %ul
         
     | 
| 
      
 147 
     | 
    
         
            +
                #     %li
         
     | 
| 
      
 148 
     | 
    
         
            +
                #       = task
         
     | 
| 
      
 149 
     | 
    
         
            +
                #       - recurse.call  if recurse
         
     | 
| 
      
 150 
     | 
    
         
            +
                def walk(&blk)
         
     | 
| 
      
 151 
     | 
    
         
            +
                  tasks.each do |task|
         
     | 
| 
      
 152 
     | 
    
         
            +
                    yield task, lambda {
         
     | 
| 
      
 153 
     | 
    
         
            +
                      task.walk { |t, recurse| blk.call t, recurse }
         
     | 
| 
      
 154 
     | 
    
         
            +
                    }
         
     | 
| 
      
 155 
     | 
    
         
            +
                  end
         
     | 
| 
      
 156 
     | 
    
         
            +
                end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                def to_html(template=nil)
         
     | 
| 
      
 159 
     | 
    
         
            +
                  require 'tilt'
         
     | 
| 
      
 160 
     | 
    
         
            +
                  template ||= TPS.root('data', 'index.haml')
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
                  tpl = Tilt.new(template)
         
     | 
| 
      
 163 
     | 
    
         
            +
                  tpl.evaluate({}, list: self)
         
     | 
| 
      
 164 
     | 
    
         
            +
                end
         
     | 
| 
      
 165 
     | 
    
         
            +
              end
         
     | 
| 
      
 166 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module TPS
         
     | 
| 
      
 2 
     | 
    
         
            +
              class TaskList < Task
         
     | 
| 
      
 3 
     | 
    
         
            +
                def initialize(options)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  super nil, nil
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  data = if options[:yaml]
         
     | 
| 
      
 7 
     | 
    
         
            +
                           YAML::load_file options[:yaml]
         
     | 
| 
      
 8 
     | 
    
         
            +
                         elsif options[:data]
         
     | 
| 
      
 9 
     | 
    
         
            +
                           options[:data]
         
     | 
| 
      
 10 
     | 
    
         
            +
                         else
         
     | 
| 
      
 11 
     | 
    
         
            +
                          options
         
     | 
| 
      
 12 
     | 
    
         
            +
                         end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  @tasks = data.map { |task, data| Task.new nil, task, data }
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/tps/version.rb
    ADDED
    
    
    
        data/lib/tps.rb
    ADDED
    
    | 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'yaml'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'tilt'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            # Common usage:
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            #     list = TPS::TaskList.new data: yaml_data
         
     | 
| 
      
 7 
     | 
    
         
            +
            #     list = TPS::TaskList.new yaml: filename
         
     | 
| 
      
 8 
     | 
    
         
            +
            #
         
     | 
| 
      
 9 
     | 
    
         
            +
            #     # Returns an array of tasks.
         
     | 
| 
      
 10 
     | 
    
         
            +
            #     task.tasks
         
     | 
| 
      
 11 
     | 
    
         
            +
            #
         
     | 
| 
      
 12 
     | 
    
         
            +
            #     # Metadata:
         
     | 
| 
      
 13 
     | 
    
         
            +
            #     task.name
         
     | 
| 
      
 14 
     | 
    
         
            +
            #     task.owner
         
     | 
| 
      
 15 
     | 
    
         
            +
            #     task.status
         
     | 
| 
      
 16 
     | 
    
         
            +
            #
         
     | 
| 
      
 17 
     | 
    
         
            +
            #     task.done?
         
     | 
| 
      
 18 
     | 
    
         
            +
            #     task.in_progress?
         
     | 
| 
      
 19 
     | 
    
         
            +
            #
         
     | 
| 
      
 20 
     | 
    
         
            +
            #     list.to_html
         
     | 
| 
      
 21 
     | 
    
         
            +
            #
         
     | 
| 
      
 22 
     | 
    
         
            +
            module TPS
         
     | 
| 
      
 23 
     | 
    
         
            +
              ROOT = File.expand_path('../../', __FILE__)
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              autoload :Task,        'tps/task'
         
     | 
| 
      
 26 
     | 
    
         
            +
              autoload :TaskList,    'tps/task_list'
         
     | 
| 
      
 27 
     | 
    
         
            +
              autoload :CliReporter, 'tps/cli_reporter'
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              require 'tps/version'
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              def self.root(*a)
         
     | 
| 
      
 32 
     | 
    
         
            +
                File.join ROOT, *a
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
    
        data/test/hello.yml
    ADDED
    
    | 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Milestone 1:
         
     | 
| 
      
 2 
     | 
    
         
            +
              First task: [25%] #0
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              User login: #1
         
     | 
| 
      
 5 
     | 
    
         
            +
                Login:
         
     | 
| 
      
 6 
     | 
    
         
            +
                Signup:
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              Overridden percent: #2
         
     | 
| 
      
 9 
     | 
    
         
            +
                _: [50%]
         
     | 
| 
      
 10 
     | 
    
         
            +
                one: [done]
         
     | 
| 
      
 11 
     | 
    
         
            +
                two: [done]
         
     | 
| 
      
 12 
     | 
    
         
            +
                three: [done]
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              Explicit points: #3
         
     | 
| 
      
 15 
     | 
    
         
            +
                _: [15pt]
         
     | 
| 
      
 16 
     | 
    
         
            +
                one: [done]
         
     | 
| 
      
 17 
     | 
    
         
            +
                two: [done]
         
     | 
| 
      
 18 
     | 
    
         
            +
                three: [done]
         
     | 
| 
      
 19 
     | 
    
         
            +
                four:
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              Compound points: #4
         
     | 
| 
      
 22 
     | 
    
         
            +
                one:
         
     | 
| 
      
 23 
     | 
    
         
            +
                two:
         
     | 
| 
      
 24 
     | 
    
         
            +
                three:
         
     | 
| 
      
 25 
     | 
    
         
            +
                  sub1: [3pts, done]
         
     | 
| 
      
 26 
     | 
    
         
            +
                  sub2:
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              Point rescaling: #5
         
     | 
| 
      
 29 
     | 
    
         
            +
                # Has 6 sub points, but will be rescaled to 8.
         
     | 
| 
      
 30 
     | 
    
         
            +
                # That is, the done "3" point task is actually worth 4 points.
         
     | 
| 
      
 31 
     | 
    
         
            +
                one:
         
     | 
| 
      
 32 
     | 
    
         
            +
                  _: [8pts]
         
     | 
| 
      
 33 
     | 
    
         
            +
                  sub1: [3pts, done]
         
     | 
| 
      
 34 
     | 
    
         
            +
                  sub2: [1pt]
         
     | 
| 
      
 35 
     | 
    
         
            +
                  sub3: [1pt]
         
     | 
| 
      
 36 
     | 
    
         
            +
                  sub4: [1pt]
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              In progress: #6
         
     | 
| 
      
 39 
     | 
    
         
            +
                one:
         
     | 
| 
      
 40 
     | 
    
         
            +
                two: [in progress]
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            Milestone 2:
         
     | 
    
        data/test/test_helper.rb
    ADDED
    
    
    
        data/test/tps_test.rb
    ADDED
    
    | 
         @@ -0,0 +1,71 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path('../test_helper', __FILE__)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class MyTest < UnitTest
         
     | 
| 
      
 4 
     | 
    
         
            +
              setup do
         
     | 
| 
      
 5 
     | 
    
         
            +
                @list = TPS::TaskList.new yaml: f('hello.yml')
         
     | 
| 
      
 6 
     | 
    
         
            +
                @milestone = @list.tasks.first
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              test "Has tasks" do
         
     | 
| 
      
 10 
     | 
    
         
            +
                assert @list.tasks?
         
     | 
| 
      
 11 
     | 
    
         
            +
                assert @list.tasks.size == 2
         
     | 
| 
      
 12 
     | 
    
         
            +
                assert @list.tasks.first.tasks.size >= 2
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              test "Explicit percent" do
         
     | 
| 
      
 16 
     | 
    
         
            +
                task = @milestone.tasks[0]
         
     | 
| 
      
 17 
     | 
    
         
            +
                assert task.in_progress?
         
     | 
| 
      
 18 
     | 
    
         
            +
                assert task.status == :in_progress
         
     | 
| 
      
 19 
     | 
    
         
            +
                assert task.percent == 0.25
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              test "Overriding percent" do
         
     | 
| 
      
 23 
     | 
    
         
            +
                task = @milestone.tasks[2]
         
     | 
| 
      
 24 
     | 
    
         
            +
                assert task.name == "Overridden percent"
         
     | 
| 
      
 25 
     | 
    
         
            +
                assert task.in_progress?
         
     | 
| 
      
 26 
     | 
    
         
            +
                assert task.status == :in_progress
         
     | 
| 
      
 27 
     | 
    
         
            +
                assert task.percent == 0.5
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              test "Points" do
         
     | 
| 
      
 31 
     | 
    
         
            +
                task = @milestone.tasks[1]
         
     | 
| 
      
 32 
     | 
    
         
            +
                assert task.points == 2.0
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              test "Explicit points" do
         
     | 
| 
      
 36 
     | 
    
         
            +
                task = @milestone.tasks[3]
         
     | 
| 
      
 37 
     | 
    
         
            +
                assert task.points == 15
         
     | 
| 
      
 38 
     | 
    
         
            +
                assert task.percent == 0.75
         
     | 
| 
      
 39 
     | 
    
         
            +
                assert task.points_done == 11.25
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              test "Compound points" do
         
     | 
| 
      
 43 
     | 
    
         
            +
                task = @milestone.tasks[4]
         
     | 
| 
      
 44 
     | 
    
         
            +
                assert task.points == 6
         
     | 
| 
      
 45 
     | 
    
         
            +
                assert task.percent == 0.50
         
     | 
| 
      
 46 
     | 
    
         
            +
              end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              test "Point rescaling" do
         
     | 
| 
      
 49 
     | 
    
         
            +
                task = @milestone.tasks[5]
         
     | 
| 
      
 50 
     | 
    
         
            +
                assert task.points == 8
         
     | 
| 
      
 51 
     | 
    
         
            +
                assert task.points_done == 4.0
         
     | 
| 
      
 52 
     | 
    
         
            +
                assert task.percent == 0.5
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              test "In progress" do
         
     | 
| 
      
 56 
     | 
    
         
            +
                task = @milestone.tasks[6]
         
     | 
| 
      
 57 
     | 
    
         
            +
                assert_equal 2, task.tasks.size
         
     | 
| 
      
 58 
     | 
    
         
            +
                assert task.tasks[1].in_progress?
         
     | 
| 
      
 59 
     | 
    
         
            +
                assert_equal 0.5, task.tasks[1].percent
         
     | 
| 
      
 60 
     | 
    
         
            +
                assert_equal 0.5, task.tasks[1].points_done
         
     | 
| 
      
 61 
     | 
    
         
            +
                assert_equal 0.25, task.percent
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              test "Milestone" do
         
     | 
| 
      
 65 
     | 
    
         
            +
                assert @milestone.milestone?
         
     | 
| 
      
 66 
     | 
    
         
            +
              end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
              test "HTML works" do
         
     | 
| 
      
 69 
     | 
    
         
            +
                assert @list.to_html
         
     | 
| 
      
 70 
     | 
    
         
            +
              end
         
     | 
| 
      
 71 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,16 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require './lib/tps/version'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Gem::Specification.new do |s|
         
     | 
| 
      
 4 
     | 
    
         
            +
              s.name = "tps_reporter"
         
     | 
| 
      
 5 
     | 
    
         
            +
              s.version = TPS.version
         
     | 
| 
      
 6 
     | 
    
         
            +
              s.summary = %{Task progress sheet reporter.}
         
     | 
| 
      
 7 
     | 
    
         
            +
              s.description = %Q{A YAML-powered, simple command-line task report builder.}
         
     | 
| 
      
 8 
     | 
    
         
            +
              s.authors = ["Rico Sta. Cruz"]
         
     | 
| 
      
 9 
     | 
    
         
            +
              s.email = ["rico@sinefunc.com"]
         
     | 
| 
      
 10 
     | 
    
         
            +
              s.homepage = "http://github.com/rstacruz/tps_reporter"
         
     | 
| 
      
 11 
     | 
    
         
            +
              s.files = `git ls-files`.strip.split("\n")
         
     | 
| 
      
 12 
     | 
    
         
            +
              s.executables = Dir["bin/*"].map { |f| File.basename(f) }
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              s.add_dependency "tilt"
         
     | 
| 
      
 15 
     | 
    
         
            +
              s.add_development_dependency "contest"
         
     | 
| 
      
 16 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,83 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: tps_reporter
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.2
         
     | 
| 
      
 5 
     | 
    
         
            +
              prerelease: 
         
     | 
| 
      
 6 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 7 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 8 
     | 
    
         
            +
            - Rico Sta. Cruz
         
     | 
| 
      
 9 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 10 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 11 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2012-02-04 00:00:00.000000000Z
         
     | 
| 
      
 13 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 14 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 15 
     | 
    
         
            +
              name: tilt
         
     | 
| 
      
 16 
     | 
    
         
            +
              requirement: &2152658640 !ruby/object:Gem::Requirement
         
     | 
| 
      
 17 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 18 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 19 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 20 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 21 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 22 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 23 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 24 
     | 
    
         
            +
              version_requirements: *2152658640
         
     | 
| 
      
 25 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 26 
     | 
    
         
            +
              name: contest
         
     | 
| 
      
 27 
     | 
    
         
            +
              requirement: &2152658200 !ruby/object:Gem::Requirement
         
     | 
| 
      
 28 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 29 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 30 
     | 
    
         
            +
                - - ! '>='
         
     | 
| 
      
 31 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 32 
     | 
    
         
            +
                    version: '0'
         
     | 
| 
      
 33 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 34 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 35 
     | 
    
         
            +
              version_requirements: *2152658200
         
     | 
| 
      
 36 
     | 
    
         
            +
            description: A YAML-powered, simple command-line task report builder.
         
     | 
| 
      
 37 
     | 
    
         
            +
            email:
         
     | 
| 
      
 38 
     | 
    
         
            +
            - rico@sinefunc.com
         
     | 
| 
      
 39 
     | 
    
         
            +
            executables:
         
     | 
| 
      
 40 
     | 
    
         
            +
            - tps
         
     | 
| 
      
 41 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 42 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 43 
     | 
    
         
            +
            files:
         
     | 
| 
      
 44 
     | 
    
         
            +
            - HISTORY.md
         
     | 
| 
      
 45 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 46 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 47 
     | 
    
         
            +
            - bin/tps
         
     | 
| 
      
 48 
     | 
    
         
            +
            - data/index.haml
         
     | 
| 
      
 49 
     | 
    
         
            +
            - data/sample.yml
         
     | 
| 
      
 50 
     | 
    
         
            +
            - lib/tps.rb
         
     | 
| 
      
 51 
     | 
    
         
            +
            - lib/tps/cli_reporter.rb
         
     | 
| 
      
 52 
     | 
    
         
            +
            - lib/tps/task.rb
         
     | 
| 
      
 53 
     | 
    
         
            +
            - lib/tps/task_list.rb
         
     | 
| 
      
 54 
     | 
    
         
            +
            - lib/tps/version.rb
         
     | 
| 
      
 55 
     | 
    
         
            +
            - test/hello.yml
         
     | 
| 
      
 56 
     | 
    
         
            +
            - test/test_helper.rb
         
     | 
| 
      
 57 
     | 
    
         
            +
            - test/tps_test.rb
         
     | 
| 
      
 58 
     | 
    
         
            +
            - tps_reporter.gemspec
         
     | 
| 
      
 59 
     | 
    
         
            +
            homepage: http://github.com/rstacruz/tps_reporter
         
     | 
| 
      
 60 
     | 
    
         
            +
            licenses: []
         
     | 
| 
      
 61 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 62 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 63 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 64 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 65 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 66 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 67 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 68 
     | 
    
         
            +
              - - ! '>='
         
     | 
| 
      
 69 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 70 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 71 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 72 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 73 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 74 
     | 
    
         
            +
              - - ! '>='
         
     | 
| 
      
 75 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 76 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 77 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 78 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 79 
     | 
    
         
            +
            rubygems_version: 1.8.10
         
     | 
| 
      
 80 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 81 
     | 
    
         
            +
            specification_version: 3
         
     | 
| 
      
 82 
     | 
    
         
            +
            summary: Task progress sheet reporter.
         
     | 
| 
      
 83 
     | 
    
         
            +
            test_files: []
         
     |