pivotalprinter 0.1.7

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/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ *.swp
2
+ pkg
3
+ Gemfile.lock
data/COPYING ADDED
@@ -0,0 +1,23 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2010 pkw.de full name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # vim: set ft=ruby:
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gemspec
data/History.txt ADDED
@@ -0,0 +1,18 @@
1
+ === 0.1.7 2011-07-19
2
+
3
+ * use a newver prawn version
4
+
5
+ === 0.1.4 2011-01-20
6
+
7
+ * print multiple stories by id
8
+ * story id is now included at the sheet
9
+
10
+ === 0.1.2 2010-12-22
11
+
12
+ * removed dependencies:
13
+ * pivotal-tracker no longer needed
14
+
15
+ === 0.0.1 2010-12-07
16
+
17
+ * 1 major enhancement:
18
+ * Initial release
data/Manifest.txt ADDED
@@ -0,0 +1,20 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ bin/pivotalprinter
7
+ images/bug.png
8
+ images/chore.png
9
+ images/feature.png
10
+ images/release.png
11
+ lib/pivotalprinter.rb
12
+ lib/pivotalprinter/client.rb
13
+ lib/pivotalprinter/story.rb
14
+ lib/pivotalprinter/iteration.rb
15
+ pivotalprinter.gemspec
16
+ script/console
17
+ script/destroy
18
+ script/generate
19
+ test/test_helper.rb
20
+ test/test_pivotalprinter.rb
data/PostInstall.txt ADDED
@@ -0,0 +1 @@
1
+ For more information on pivotalprinter, see http://github.com/pkwde/pivotalprinter
data/README.rdoc ADDED
@@ -0,0 +1,22 @@
1
+ = pivotalprinter
2
+
3
+ * https://github.com/caroo/pivotalprinter
4
+
5
+ == DESCRIPTION:
6
+
7
+ Script to print use stories in pivotal printer
8
+
9
+ == INSTALL:
10
+
11
+ Just type
12
+
13
+ $ gem install privotalprinter
14
+
15
+
16
+ == AUTHORS
17
+
18
+ pkw.de Development Team
19
+
20
+ == LICENSE:
21
+
22
+ The MIT License, see the COPYING file
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env ruby
2
+ # inspired by from http://ephemera.karmi.cz/post/622136360/create-printable-pdf-cards-for-your-pivotal-tracker-stor
3
+
4
+ require 'pivotalprinter'
5
+
6
+ class String; include Term::ANSIColor; end
7
+
8
+ module Pivotalprinter
9
+ class ConfigNeeded < StandardError; end
10
+ class TokenMissing < StandardError; end
11
+ class ProjectMissing < StandardError; end
12
+ end
13
+
14
+ module Pivotalprinter
15
+ class Printer
16
+ def run
17
+ opts = parse_options
18
+ yaml = load_yaml_config
19
+ project,token = extract_config(opts, yaml)
20
+ Pivotalprinter::Client.project = project
21
+ Pivotalprinter::Client.token = token
22
+ @stories = case ARGV.last
23
+ when "done" : Pivotalprinter::Iteration.open('done').stories
24
+ when "backlog": Pivotalprinter::Iteration.open('backlog').stories
25
+ when /^\d+$/ : Pivotalprinter::Story.open(ARGV.map(&:to_i))
26
+ else Pivotalprinter::Iteration.open('current').stories
27
+ end
28
+ generate_output
29
+ rescue ConfigNeeded
30
+ print_config
31
+ rescue TokenMissing
32
+ Trollop::die :token, "token must be specified through config file or explicitly"
33
+ rescue ProjectMissing
34
+ Trollop::die :project, "project must be a valid number or one of the configured projects (#{(yaml.keys - ["default"]).join(", ")}) if no default is configured in $HOME/.pivotalprinterrc"
35
+ rescue SystemExit
36
+ rescue Exception
37
+ puts "[!] There was an error while generating the PDF file... What happened was:".white.on_red
38
+ raise
39
+ end
40
+
41
+ def print_config
42
+ puts %{---\ndefault: &default\n token: "YOUR TOKEN HERE"\n project: 123\n\nsome_project:\n <<: *default # so you don't need to rewrite the token\n project: 789}
43
+ end
44
+
45
+ def parse_options
46
+ opts = Trollop::options do
47
+ version "pivotalprinter #{Pivotalprinter::VERSION} (c) 2010#{(year = Time.now.year) > 2010 ? "-#{year}" : ''} pkw.de"
48
+ banner <<-EOS
49
+ Pivotalprinter is an awesome program to print stories from the PivotalTracker.
50
+
51
+ Useage:
52
+ pivotalprinter [-p PROJECT] [-t TOKEN] [current|backlog|done|STORY]
53
+ pivotalprinter --config > ~/.pivotalprinterrc
54
+
55
+ Options:
56
+ EOS
57
+ opt :project, "Project Name defined in $HOME/.pivotalprinterrc or project number", :short => "-p", :type => :string
58
+ opt :token, "Pivotaltracker Token", :short => "-t", :type => :string
59
+ opt :config, "show example configuration", :short => "-c"
60
+ end
61
+
62
+ raise ConfigNeeded if opts[:config]
63
+ opts
64
+ end
65
+
66
+ def load_yaml_config
67
+ File.exist?("#{ENV["HOME"]}/.pivotalprinterrc") ? YAML::load_file("#{ENV["HOME"]}/.pivotalprinterrc") : {}
68
+ end
69
+
70
+ def extract_config(opts, yaml)
71
+ if opts[:project].nil? && yaml.key?("default")
72
+ return yaml["default"]["project"], yaml["default"]["token"]
73
+ elsif opts[:project] =~ /[0-9]+/
74
+ return opts[:project], (opts[:token] || yaml["default"]["project"])
75
+ elsif yaml.key?(opts[:project])
76
+ return yaml[opts[:project]]["project"], yaml[opts[:project]]["token"]
77
+ else
78
+ raise ProjectMissing
79
+ end
80
+ end
81
+
82
+ def generate_output
83
+ Prawn::Document.generate("/tmp/stories.pdf", :page_layout => :landscape, :margin => [25, 25, 50, 25], :page_size => 'A4') do |pdf|
84
+ @num_cards_on_page = 0
85
+ pdf.font "#{Prawn::BASEDIR}/data/fonts/DejaVuSans.ttf"
86
+ @stories.each_with_index do |story, i|
87
+ # --- Split pages
88
+ if i > 0 and i % 4 == 0
89
+ # puts "New page..."
90
+ pdf.start_new_page
91
+ @num_cards_on_page = 1
92
+ else
93
+ @num_cards_on_page += 1
94
+ end
95
+
96
+ # --- Define 2x2 grid
97
+ pdf.define_grid(:columns => 2, :rows => 2, :gutter => 42)
98
+ # pdf.grid.show_all
99
+
100
+ row = (@num_cards_on_page+1) / 4
101
+ column = i % 2
102
+ padding = 12
103
+ cell = pdf.grid( row, column )
104
+ cell.bounding_box do
105
+
106
+ pdf.stroke_color = "666666"
107
+ pdf.stroke_bounds
108
+
109
+ pdf.text_box story.name, :size => 14, :height => 50, :overflow => :truncate, :width => cell.width-(padding*2)-50, :at => [pdf.bounds.left+padding+50, pdf.bounds.top-padding]
110
+ pdf.text_box story.description, :size => 8, :overflow => :truncate, :width => cell.width-(padding*2), :height => cell.height-(padding*7), :at => [pdf.bounds.left+padding, pdf.bounds.top-padding-55]
111
+ pdf.text_box "ID #{story.id}", :size => 8, :at => [pdf.bounds.left, pdf.bounds.bottom+padding], :align => :right
112
+ pdf.text_box story.created_at.strftime('%F'), :size => 8, :at => [pdf.bounds.left, pdf.bounds.bottom+padding], :align => :left
113
+
114
+ x, y = 32, 205
115
+ if story.story_type=="feature"
116
+ pdf.fill_color story.points_background
117
+ pdf.fill_circle [x,y], 25
118
+ pdf.font_size = 36
119
+ pdf.font "Helvetica", :style => :bold
120
+ pdf.fill_color 'ffffff'
121
+ pdf.draw_text "#{story.points}", :at => [x-10, y-12]
122
+ pdf.fill_color '000000'
123
+ pdf.font_size = 14
124
+ pdf.font "#{Prawn::BASEDIR}/data/fonts/DejaVuSans.ttf", :style => :normal
125
+ else
126
+ pdf.image open("#{File.dirname(__FILE__)}/../images/#{story.story_type}.png"), :position => 5, :vposition => 5
127
+ end
128
+ end
129
+ end
130
+ end
131
+ puts ">>> Generated PDF file in 'stories.pdf' with #{@stories.size} stories".black.on_green
132
+ system "open /tmp/stories.pdf"
133
+ end
134
+ end
135
+ end
136
+
137
+ Pivotalprinter::Printer.new.run
data/images/bug.png ADDED
Binary file
data/images/chore.png ADDED
Binary file
Binary file
Binary file
@@ -0,0 +1,13 @@
1
+ module Pivotalprinter
2
+ class Client
3
+ class << self
4
+ attr_accessor :token, :project
5
+
6
+ def get(path, options={})
7
+ raise TokenMissing if @token.nil?
8
+ raise ProjectMissing if @project.nil?
9
+ open("http://www.pivotaltracker.com/services/v3#{path}", 'X-TrackerToken' => @token, 'Content-Type' => 'application/xml').read
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ module Pivotalprinter
2
+ class Iteration
3
+
4
+ attr_accessor :stories
5
+
6
+ def self.open(name)
7
+ self.new(name)
8
+ end
9
+
10
+ def initialize(name)
11
+ @stories = []
12
+ extract_stories(Client.get "/projects/#{Client.project}/iterations/#{name}")
13
+ end
14
+
15
+ private
16
+
17
+ def extract_stories(response)
18
+ response = Nokogiri::XML.parse(response)
19
+ response.css("story").each do |story|
20
+ @stories << Story.new(story)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,43 @@
1
+ require 'time'
2
+
3
+ module Pivotalprinter
4
+ class Story
5
+ FIELDS = [ :name, :id, :story_type, :estimate, :current_state, :description, :requested_by, :labels, :created_at, :updated_at ]
6
+ attr_accessor *FIELDS
7
+
8
+ def initialize(xml)
9
+ FIELDS.each do |field|
10
+ value = xml.css("#{field}")
11
+ send "#{field}=", value.first.full? { |v| v.send(:text) } || value.send(:text)
12
+ end
13
+ created_at and self.created_at = Time.parse(created_at)
14
+ updated_at and self.updated_at = Time.parse(updated_at)
15
+ end
16
+
17
+ def self.open(ids)
18
+ stories = ids.map do |id|
19
+ response = Client.get "/projects/#{Client.project}/stories/#{id}"
20
+ response = Nokogiri::XML.parse(response)
21
+ self.new(response.css('story'))
22
+ end
23
+ end
24
+
25
+ def points
26
+ estimate.to_i >= 0 ? estimate.to_i : '?'
27
+ end
28
+
29
+ def points_background
30
+ case points
31
+ when '?': 'cccccc'
32
+ when 0: 'ccff66'
33
+ when 1: '408000'
34
+ when 2: '808000'
35
+ when 3: 'ffcc66'
36
+ when 5: 'ff8000'
37
+ when 8: 'ff0000'
38
+ else 'aa0000'
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,3 @@
1
+ module Pivotalprinter
2
+ VERSION = '0.1.7'
3
+ end
@@ -0,0 +1,19 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module Pivotalprinter
5
+ require 'rubygems'
6
+ require 'pivotalprinter/version'
7
+ require 'term/ansicolor'
8
+ require 'prawn'
9
+ require 'prawn/layout/grid'
10
+ require 'spruz/xt/full'
11
+ require 'trollop'
12
+ require 'yaml'
13
+ require "rubygems"
14
+ require "open-uri"
15
+ require "nokogiri"
16
+ require "pivotalprinter/client"
17
+ require "pivotalprinter/iteration"
18
+ require "pivotalprinter/story"
19
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.unshift 'lib'
3
+ require "pivotalprinter/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "pivotalprinter"
7
+ s.version = Pivotalprinter::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["pkw.de"]
10
+ s.email = ["dev@pkw.de"]
11
+ s.homepage = "http://pkw.de"
12
+ s.summary = %q{Story printer for pivotaltracker}
13
+ s.description = %q{Generate nice story cards from pivotaltracker.}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_dependency('term-ansicolor','>= 0.4.4')
21
+ s.add_dependency('prawn','~>0.11.1')
22
+ s.add_dependency('spruz','>= 0.2.0')
23
+ s.add_dependency('trollop','>= 1.16.2')
24
+ s.add_dependency('nokogiri','>= 1.4.4')
25
+ end
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/pivotalprinter.rb'}"
9
+ puts "Loading pivotalprinter gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,3 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/../lib/pivotalprinter'
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestPivotalprinter < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def test_truth
9
+ assert true
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,169 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pivotalprinter
3
+ version: !ruby/object:Gem::Version
4
+ hash: 21
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 7
10
+ version: 0.1.7
11
+ platform: ruby
12
+ authors:
13
+ - pkw.de
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-07-19 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: term-ansicolor
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 7
29
+ segments:
30
+ - 0
31
+ - 4
32
+ - 4
33
+ version: 0.4.4
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: prawn
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 49
45
+ segments:
46
+ - 0
47
+ - 11
48
+ - 1
49
+ version: 0.11.1
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: spruz
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 23
61
+ segments:
62
+ - 0
63
+ - 2
64
+ - 0
65
+ version: 0.2.0
66
+ type: :runtime
67
+ version_requirements: *id003
68
+ - !ruby/object:Gem::Dependency
69
+ name: trollop
70
+ prerelease: false
71
+ requirement: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ hash: 83
77
+ segments:
78
+ - 1
79
+ - 16
80
+ - 2
81
+ version: 1.16.2
82
+ type: :runtime
83
+ version_requirements: *id004
84
+ - !ruby/object:Gem::Dependency
85
+ name: nokogiri
86
+ prerelease: false
87
+ requirement: &id005 !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 15
93
+ segments:
94
+ - 1
95
+ - 4
96
+ - 4
97
+ version: 1.4.4
98
+ type: :runtime
99
+ version_requirements: *id005
100
+ description: Generate nice story cards from pivotaltracker.
101
+ email:
102
+ - dev@pkw.de
103
+ executables:
104
+ - pivotalprinter
105
+ extensions: []
106
+
107
+ extra_rdoc_files: []
108
+
109
+ files:
110
+ - .gitignore
111
+ - COPYING
112
+ - Gemfile
113
+ - History.txt
114
+ - Manifest.txt
115
+ - PostInstall.txt
116
+ - README.rdoc
117
+ - Rakefile
118
+ - bin/pivotalprinter
119
+ - images/bug.png
120
+ - images/chore.png
121
+ - images/feature.png
122
+ - images/release.png
123
+ - lib/pivotalprinter.rb
124
+ - lib/pivotalprinter/client.rb
125
+ - lib/pivotalprinter/iteration.rb
126
+ - lib/pivotalprinter/story.rb
127
+ - lib/pivotalprinter/version.rb
128
+ - pivotalprinter.gemspec
129
+ - script/console
130
+ - script/destroy
131
+ - script/generate
132
+ - test/test_helper.rb
133
+ - test/test_pivotalprinter.rb
134
+ homepage: http://pkw.de
135
+ licenses: []
136
+
137
+ post_install_message:
138
+ rdoc_options: []
139
+
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ none: false
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ hash: 3
148
+ segments:
149
+ - 0
150
+ version: "0"
151
+ required_rubygems_version: !ruby/object:Gem::Requirement
152
+ none: false
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ hash: 3
157
+ segments:
158
+ - 0
159
+ version: "0"
160
+ requirements: []
161
+
162
+ rubyforge_project:
163
+ rubygems_version: 1.7.2
164
+ signing_key:
165
+ specification_version: 3
166
+ summary: Story printer for pivotaltracker
167
+ test_files:
168
+ - test/test_helper.rb
169
+ - test/test_pivotalprinter.rb