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 +4 -4
- data/lib/cli.rb +81 -60
- data/lib/pdf.rb +3 -0
- data/lib/spreadsheet.rb +56 -0
- data/lib/trello_interface.rb +88 -0
- data/lib/version.rb +1 -1
- data/trelloscrum.gemspec +2 -0
- metadata +32 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3cbe70f6d030bb2ce6e272830a4c6cec23db6d58
|
4
|
+
data.tar.gz: d35e622d219b3a6af6b8ad663340fba302e0429a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
24
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
61
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
124
|
+
say "Please enter a board_id (using --board) or configure one using setup "
|
101
125
|
exit(1)
|
102
126
|
end
|
103
127
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
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
|
-
|
117
|
-
|
118
|
-
|
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
|
125
|
-
|
126
|
-
|
127
|
-
|
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
data/lib/spreadsheet.rb
ADDED
@@ -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
|
data/lib/version.rb
CHANGED
data/trelloscrum.gemspec
CHANGED
@@ -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.
|
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-
|
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
|