trelloscrum 0.2.0 → 0.3.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ebcf1017670544951a750a392c016fe4f6f0183f
4
- data.tar.gz: fd5ee6f51bbc62d7e212bbd36f957685e9b2a4c8
3
+ metadata.gz: 3cbe70f6d030bb2ce6e272830a4c6cec23db6d58
4
+ data.tar.gz: d35e622d219b3a6af6b8ad663340fba302e0429a
5
5
  SHA512:
6
- metadata.gz: 540362e17cb52828a01951ab2646204debca8af3e916437b973ab44ab1168aa5e2c15635672db4dd0bcb93be11c9995669d5ca6f024d0d5b8bec1800d5900873
7
- data.tar.gz: 7cff2bbf9918d7691f95296d0f7c127ede4ea413faa5ee9ae759273d999045a7d039aa99f0436b713946fbe6ed94b985155d41c72b52727e09e88f82ac168727
6
+ metadata.gz: 0b82568a2d5aa71863a92cddb6ee13e5f47627e21956de5f5636353de0afdfea17dd28fe73df3849888380ec8f845d7cdaae1cb0955ebbc6d21694020756eb88
7
+ data.tar.gz: f3b8b1e92ac72f3c1a8a2710a0948b2f75ff30b69528c19884056378e794c14f2634defaded0d6bc38296e7e020b9e6c6fff265b9ab80da3de05b98e54c14f32
data/lib/cli.rb CHANGED
@@ -3,8 +3,11 @@ require 'thor'
3
3
  require 'json'
4
4
  require 'chronic'
5
5
  require 'trello'
6
+ require 'launchy'
6
7
 
8
+ require_relative 'trello_interface'
7
9
  require_relative 'pdf'
10
+ require_relative 'spreadsheet'
8
11
 
9
12
  module TrelloScrum
10
13
  class Cli < Thor
@@ -17,11 +20,36 @@ module TrelloScrum
17
20
  method_option :"list", :type => :string, :desc => "Listname to use"
18
21
  method_option :"board", :type => :string, :desc => "Board id to use"
19
22
  method_option :"filter-title", :type => :string, :desc => "Regexp to filter on titles, only show's cards matching title"
20
-
21
23
  def pdf(outfile)
22
- setup_trello
23
- cards = get_cards
24
- generate_pdf(cards, outfile)
24
+ trello = setup_trello
25
+
26
+ list_name = options.list || config["list_name"]
27
+
28
+ if !list_name || list_name.empty?
29
+ say "Please enter a listname (using --list) or configure one using setup"
30
+ exit(1)
31
+ end
32
+
33
+ lists_with_cards = trello.get_cards(list_name, options)
34
+
35
+ pdf = Pdf.new
36
+ pdf.render_cards(lists_with_cards)
37
+ pdf.save(outfile)
38
+ end
39
+
40
+ desc "excel OUTFILE", "generate Excel file for cards"
41
+ method_option :"only-estimated", :default => true, :type => :boolean, :desc => "Wether or not to output only estimates"
42
+ method_option :"list", :type => :string, :desc => "Listname to use (if not set it will take all lists)"
43
+ method_option :"include-archived-lists", :default => false, :type => :boolean, :desc => "Include archived lists"
44
+ method_option :"board", :type => :string, :desc => "Board id to use"
45
+ method_option :"filter-title", :type => :string, :desc => "Regexp to filter on titles, only show's cards matching title"
46
+ def excel(outfile)
47
+ trello = setup_trello
48
+ lists_with_cards = trello.get_cards(options.list || config["list_name"], options)
49
+
50
+ sheet = Spreadsheet.new
51
+ sheet.render_cards(lists_with_cards)
52
+ sheet.save(outfile)
25
53
  end
26
54
 
27
55
  desc "setup DEVELOPER_PUBLIC_KEY MEMBER_TOKEN [BOARD_ID] [LIST_NAME]", "config trello"
@@ -48,86 +76,79 @@ module TrelloScrum
48
76
  self.config["board_id"] = board_id if board_id
49
77
  self.config["list_name"] = list_name if list_name
50
78
 
51
- File.open(options.config, "w") do |f|
52
- f.write JSON.pretty_generate(self.config)
53
- end
54
-
55
- puts "New config written to #{options.config}"
79
+ write_config!
56
80
  end
57
81
 
58
- protected
82
+ desc "authorize", "Re-authorize trello"
83
+ long_desc <<-EOT
84
+ A simple way to launch the browser with the correct url. It will
85
+ also provide you with a way to paste your MEMBER_TOKEN.
86
+ EOT
87
+ def authorize
88
+ # Open the browser
89
+ url = "https://trello.com/1/connect"
90
+ url << "?key=#{self.config["developer_public_key"]}"
91
+ url << "&name=TrelloScrumCard&response_type=token"
92
+ Launchy.open(url)
93
+
94
+ member_token = ask("Paste member token here:")
95
+
96
+ if member_token =~ /.+/
97
+ self.config["member_token"] = member_token
98
+ write_config!
99
+ else
100
+ say "No member token entered. Not saving new member token"
101
+ end
102
+ end
59
103
 
60
- def log(msg)
61
- puts msg if options.verbose
104
+ no_commands do
105
+ def log(msg)
106
+ say msg if options.verbose
107
+ end
62
108
  end
109
+ protected
63
110
 
64
111
  def setup_trello
65
112
  if !config["developer_public_key"] || config["developer_public_key"].empty?
66
- puts "Please make sure you have configured a developer public key (run setup help for more info)"
113
+ say "Please make sure you have configured a developer public key (run setup help for more info)"
67
114
  exit(1)
68
115
  end
69
116
 
70
117
  if !config["member_token"] || config["member_token"].empty?
71
- puts "Please make sure you have configured a member token (run setup help for more info)"
72
- exit(1)
73
- end
74
-
75
- Trello.configure do |c|
76
- c.developer_public_key = config["developer_public_key"]
77
- c.member_token = config["member_token"]
78
- end
79
- end
80
-
81
- def config
82
- if File.exist?(options.config)
83
- @config ||= JSON.parse(File.read(options.config));
84
- else
85
- @config ||= {}
86
- end
87
- end
88
-
89
- def get_cards
90
- list_name = options.list || config["list_name"]
91
-
92
- if !list_name || list_name.empty?
93
- puts "Please enter a listname (using --list) or configure one using setup"
118
+ say "Please make sure you have configured a member token (run setup help for more info)"
94
119
  exit(1)
95
120
  end
96
121
 
97
122
  board_id = options.board || config["board_id"]
98
-
99
123
  if !board_id || board_id.empty?
100
- puts "Please enter a board_id (using --board) or configure one using setup "
124
+ say "Please enter a board_id (using --board) or configure one using setup "
101
125
  exit(1)
102
126
  end
103
127
 
104
- log "Getting cards from list #{list_name} of board #{board_id}"
105
-
106
- board = Trello::Board.find(board_id)
107
-
108
- list = board.lists.find{|l| l.name == list_name }
109
-
110
- log "Found list: #{list ? "yes" : "no"}"
111
-
112
- cards = list.cards.sort!{|a, b| a.pos <=> b.pos }
113
-
114
- log "List contains #{cards.size} cards"
128
+ TrelloInterface.new(
129
+ board_id,
130
+ config["developer_public_key"],
131
+ config["member_token"],
132
+ {
133
+ cli: self
134
+ }
135
+ )
136
+ end
115
137
 
116
- cards.find_all do |card|
117
- keep = true
118
- keep = false if options[:"only-estimated"] && !(card.name =~ /^\(\d+/)
119
- keep = false if options[:"filter-title"] && !(card.name =~ Regexp.new(options[:"filter-title"]))
120
- keep
138
+ def write_config!
139
+ File.open(options.config, "w") do |f|
140
+ f.write JSON.pretty_generate(self.config)
121
141
  end
142
+ say "Config written to #{options.config}"
122
143
  end
123
144
 
124
- def generate_pdf(cards, output_path)
125
- pdf = Pdf.new
126
- pdf.render_cards(cards)
127
- pdf.save(output_path)
145
+ def config
146
+ if File.exist?(options.config)
147
+ @config ||= JSON.parse(File.read(options.config));
148
+ else
149
+ @config ||= {}
150
+ end
128
151
  end
129
152
 
130
-
131
-
132
153
  end
133
154
  end
data/lib/pdf.rb CHANGED
@@ -31,6 +31,9 @@ module TrelloScrum
31
31
  end
32
32
 
33
33
  def render_cards(cards)
34
+ # Flatten the structure
35
+ cards = cards.map{|list| list[:cards]}.flatten
36
+
34
37
  cards.each_with_index do |card, i|
35
38
  render_card(card)
36
39
 
@@ -0,0 +1,56 @@
1
+ require 'axlsx'
2
+ require 'pry'
3
+
4
+ module TrelloScrum
5
+
6
+ class Spreadsheet
7
+
8
+ attr_reader :package, :workbook
9
+
10
+ def initialize
11
+ @package = Axlsx::Package.new
12
+ @workbook = @package.workbook
13
+ end
14
+
15
+ def render_cards(lists_with_cards)
16
+ list_name_style = workbook.styles.add_style :sz => 16, :b => true
17
+ header_style = workbook.styles.add_style :b => true
18
+
19
+ workbook.add_worksheet(:name => "Cards") do |sheet|
20
+ lists_with_cards.each do |list|
21
+ # The list title
22
+ sheet.add_row [
23
+ list[:list].name.to_s + (list[:list].closed ? " (archived)" : "")
24
+ ], style: list_name_style
25
+
26
+ # Header
27
+ sheet.add_row [
28
+ "Points",
29
+ "Title",
30
+ "Client",
31
+ "URL"
32
+ ], style: header_style
33
+
34
+ list[:cards].each do |card|
35
+ sheet.add_row [
36
+ card.scrum_points,
37
+ card.scrum_title,
38
+ card.scrum_client,
39
+ card.url
40
+ ]
41
+ end
42
+
43
+ # Add some empty rows
44
+ sheet.add_row
45
+ end
46
+
47
+ sheet.column_widths 10, nil, nil, nil
48
+ end
49
+ end
50
+
51
+ def save(filename)
52
+ package.serialize(filename)
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,88 @@
1
+ module TrelloScrum
2
+
3
+ class TrelloInterface
4
+
5
+ attr_accessor :board_id, :options
6
+
7
+ def initialize(board_id, developer_public_key, member_token, options = {})
8
+ Trello.configure do |c|
9
+ c.developer_public_key = developer_public_key
10
+ c.member_token = member_token
11
+ end
12
+
13
+ self.board_id = board_id
14
+
15
+ self.options = options
16
+ end
17
+
18
+
19
+ def get_cards(list_name = nil, options = {})
20
+ log "Getting cards from list #{list_name} of board #{board_id}"
21
+
22
+ lists = get_lists(list_name, options)
23
+
24
+ lists.map do |list|
25
+ cards = list.cards.sort!{|a, b| a.pos <=> b.pos }
26
+
27
+ log "List '#{list.name}' contains #{cards.size} cards"
28
+
29
+ filtered_cards = cards.find_all do |card|
30
+ keep = true
31
+ keep = false if options[:"only-estimated"] && !(card.name =~ /^\(\d+/)
32
+ keep = false if options[:"filter-title"] && !(card.name =~ Regexp.new(options[:"filter-title"]))
33
+ keep
34
+ end
35
+
36
+ filtered_cards.map! do |card|
37
+ class << card
38
+ attr_accessor :scrum_points, :scrum_client, :scrum_title
39
+ end
40
+ points,client,title = parse_card_title(card.name)
41
+ card.scrum_points = points
42
+ card.scrum_client = client
43
+ card.scrum_title = title
44
+ card
45
+ end
46
+
47
+ {
48
+ list: list,
49
+ cards: filtered_cards
50
+ }
51
+ end
52
+ end
53
+
54
+ def get_lists(list_name, options = {})
55
+ board = Trello::Board.find(board_id)
56
+
57
+ lists = board.lists filter: (options[:"include-archived-lists"] ? :all : :open)
58
+
59
+ if list_name && !list_name.empty?
60
+ lists = lists.find_all{|l| l.name == list_name }
61
+ end
62
+
63
+ lists.sort!{|a, b| a.pos <=> b.pos }
64
+
65
+ log "Found lists: #{lists.map(&:name).inspect}"
66
+
67
+ lists
68
+ end
69
+
70
+ protected
71
+
72
+ def parse_card_title(title)
73
+ match = title.match(/^\s*(\((\d+)\))?\s*(\[(.*?)\])?\s*(.*)/)
74
+ [match[2], match[4], match[5]]
75
+ end
76
+
77
+ def log(msg)
78
+ if options[:cli]
79
+ options[:cli].log msg
80
+ else
81
+ puts msg
82
+ end
83
+ end
84
+
85
+
86
+ end
87
+
88
+ end
@@ -1,3 +1,3 @@
1
1
  module TrelloScrum
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.3.0'.freeze
3
3
  end
@@ -26,6 +26,8 @@ Gem::Specification.new do |spec|
26
26
  spec.add_dependency "chronic", "~> 0.10.2"
27
27
  spec.add_dependency "ruby-trello", "~> 1.1.2"
28
28
  spec.add_dependency "thor", "~> 0.19.1"
29
+ spec.add_dependency "launchy", "~> 2.4.3"
30
+ spec.add_dependency "axlsx", "~> 2.0.1"
29
31
 
30
32
  spec.homepage = "https://github.com/flurin/trelloscrum"
31
33
  spec.description = <<END_DESC
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trelloscrum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Flurin Egger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-01 00:00:00.000000000 Z
11
+ date: 2015-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -94,6 +94,34 @@ dependencies:
94
94
  - - ~>
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.19.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: launchy
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 2.4.3
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 2.4.3
111
+ - !ruby/object:Gem::Dependency
112
+ name: axlsx
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 2.0.1
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: 2.0.1
97
125
  description: |2
98
126
  Generates PDF's with (+/-) one page per card with title, body and checklists. Print 4 of them on an A4 for the best action.
99
127
  email:
@@ -107,6 +135,8 @@ files:
107
135
  - bin/trelloscrum
108
136
  - lib/cli.rb
109
137
  - lib/pdf.rb
138
+ - lib/spreadsheet.rb
139
+ - lib/trello_interface.rb
110
140
  - lib/version.rb
111
141
  - readme.md
112
142
  - resources/Apache License.txt