taskmapper-mingle 0.2.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.
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.2@taskmapper-mingle --create
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "taskmapper", "~> 0.8"
4
+
5
+ group :development do
6
+ gem "rspec", "~> 2.8"
7
+ gem "jeweler", "~> 1.6"
8
+ gem "simplecov", "~> 0.5", :platforms => :ruby_19
9
+ gem "rcov", "~> 1.0", :platforms => :ruby_18
10
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,54 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.2.3)
5
+ activesupport (= 3.2.3)
6
+ builder (~> 3.0.0)
7
+ activeresource (3.2.3)
8
+ activemodel (= 3.2.3)
9
+ activesupport (= 3.2.3)
10
+ activesupport (3.2.3)
11
+ i18n (~> 0.6)
12
+ multi_json (~> 1.0)
13
+ builder (3.0.0)
14
+ diff-lcs (1.1.3)
15
+ git (1.2.5)
16
+ hashie (1.2.0)
17
+ i18n (0.6.0)
18
+ jeweler (1.8.3)
19
+ bundler (~> 1.0)
20
+ git (>= 1.2.5)
21
+ rake
22
+ rdoc
23
+ json (1.7.3)
24
+ multi_json (1.3.5)
25
+ rake (0.9.2.2)
26
+ rcov (1.0.0)
27
+ rdoc (3.12)
28
+ json (~> 1.4)
29
+ rspec (2.10.0)
30
+ rspec-core (~> 2.10.0)
31
+ rspec-expectations (~> 2.10.0)
32
+ rspec-mocks (~> 2.10.0)
33
+ rspec-core (2.10.0)
34
+ rspec-expectations (2.10.0)
35
+ diff-lcs (~> 1.1.3)
36
+ rspec-mocks (2.10.1)
37
+ simplecov (0.6.4)
38
+ multi_json (~> 1.0)
39
+ simplecov-html (~> 0.5.3)
40
+ simplecov-html (0.5.3)
41
+ taskmapper (0.8.0)
42
+ activeresource (~> 3.0)
43
+ activesupport (~> 3.0)
44
+ hashie (~> 1.2)
45
+
46
+ PLATFORMS
47
+ ruby
48
+
49
+ DEPENDENCIES
50
+ jeweler (~> 1.6)
51
+ rcov (~> 1.0)
52
+ rspec (~> 2.8)
53
+ simplecov (~> 0.5)
54
+ taskmapper (~> 0.8)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 anymoto
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # taskmapper-mingle
2
+
3
+ This is a provider for [taskmapper](http://ticketrb.com). It provides interoperability with [Mingle](http://www.thoughtworks-studios.com/mingle-agile-project-management/) and it's issue tracking system through the taskmapper gem.
4
+
5
+ # Usage and Examples
6
+
7
+ First we have to instantiate a new taskmapper instance, your Mingle installation should have api access enable:
8
+
9
+ mingle = TaskMapper.new(:mingle, {:server => 'myserver', :username=> 'foo', :password => 'bar'})
10
+
11
+ If you do not pass in the server name, username and password, you won't get any information.
12
+
13
+ Also you have to enable basic authentication, set the basic_authentication_enabled configuration option to true in the Mingle data directory/config/auth_config.yml file, where Mingle data directory is the path to the Mingle data directory:
14
+
15
+ basic_authentication_enabled: true
16
+
17
+ ## Finding Projects
18
+
19
+ You can find your own projects by doing:
20
+
21
+ projects = mingle.projects # Will return all your projects
22
+ projects = mingle.projects(["project1", "project2"]) # You must use your projects identifier
23
+ project = mingle.project("your_project") # Also use project identifier in here
24
+
25
+ ## Creating a project
26
+
27
+ project = mingle.project!(:name => "New Project", :identifier => "new_project", :description => "This is a new project")
28
+
29
+ ## Finding Tickets(Cards)
30
+
31
+ tickets = project.tickets # All tickets
32
+ ticket = project.ticket(<ticket_number>)
33
+
34
+ ## Open Tickets
35
+
36
+ ticket = project.ticket!({:name => "New ticket", :description=> "Body for the very new ticket"})
37
+
38
+
39
+ ## Finding comments
40
+
41
+ comments = project.ticket.comments
42
+
43
+ ## Creating a comment
44
+
45
+ comment = ticket.comment!(:content => 'New comment created.')
46
+
47
+ ## Requirements
48
+
49
+ * rubygems (obviously)
50
+ * taskmapper gem (latest version preferred)
51
+ * jeweler gem (only if you want to repackage and develop)
52
+ * Mingle
53
+
54
+ The taskmapper gem should automatically be installed during the installation of this gem if it is not already installed.
55
+
56
+ ## Other Notes
57
+
58
+ Since this and the taskmapper gem is still primarily a work-in-progress, minor changes may be incompatible with previous versions. Please be careful about using and updating this gem in production.
59
+
60
+ If you see or find any issues, feel free to open up an issue report.
61
+
62
+
63
+ ## Note on Patches/Pull Requests
64
+
65
+ * Fork the project.
66
+ * Make your feature addition or bug fix.
67
+ * Add tests for it. This is important so we don't break it in a
68
+ future version unintentionally.
69
+ * Commit, do not mess with rakefile, version, or history.
70
+ (if you want to have your own version, that is fine but bump version in a commit by itself so we can ignore when I pull)
71
+ * Send us a pull request. Bonus points for topic branches.
72
+
73
+ ## Copyright
74
+
75
+ Copyright (c) 2011 The Hybrid Group. See LICENSE for details.
76
+
77
+
data/Rakefile ADDED
@@ -0,0 +1,35 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'jeweler'
4
+ Jeweler::Tasks.new do |gem|
5
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
6
+ gem.name = "taskmapper-mingle"
7
+ gem.homepage = "http://ticketrb.com"
8
+ gem.summary = %Q{TaskMapper Provider for Mingle}
9
+ gem.description = %Q{Allows taskmapper to interact with Mingle}
10
+ gem.email = "ana@hybridgroup.com"
11
+ gem.authors = ["Hybridgroup"]
12
+ Jeweler::GemcutterTasks.new
13
+ end
14
+ require 'rspec/core'
15
+ require 'rspec/core/rake_task'
16
+ RSpec::Core::RakeTask.new(:spec) do |spec|
17
+ spec.pattern = FileList['spec/**/*_spec.rb']
18
+ end
19
+
20
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
21
+ spec.pattern = 'spec/**/*_spec.rb'
22
+ spec.rcov = true
23
+ end
24
+
25
+ task :default => :spec
26
+
27
+ require 'rake/rdoctask'
28
+ Rake::RDocTask.new do |rdoc|
29
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
30
+
31
+ rdoc.rdoc_dir = 'rdoc'
32
+ rdoc.title = "taskmapper-kanbanpad#{version}"
33
+ rdoc.rdoc_files.include('README*')
34
+ rdoc.rdoc_files.include('lib/**/*.rb')
35
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -0,0 +1,228 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'active_resource'
4
+
5
+ # Ruby lib for working with the Mingle API's XML interface.
6
+ # You should set the authentication using your login
7
+ # credentials with HTTP Basic Authentication.
8
+
9
+ # This library is a small wrapper around the REST interface
10
+
11
+ module MingleAPI
12
+ class Error < StandardError; end
13
+ class << self
14
+
15
+ #Sets up basic authentication credentials for all the resources.
16
+ def authenticate(server, login, password)
17
+ @server = server
18
+ @username = login
19
+ @password = password
20
+ self::Base.user = login
21
+ self::Base.password = password
22
+
23
+ resources.each do |klass|
24
+ klass.site = klass.site_format % "http://#{login}:#{password}@#{server}/api/v2"
25
+ end
26
+ end
27
+
28
+ def resources
29
+ @resources ||= []
30
+ end
31
+ end
32
+
33
+ class Base < ActiveResource::Base
34
+ def self.inherited(base)
35
+ MingleAPI.resources << base
36
+ class << base
37
+ attr_accessor :site_format
38
+ end
39
+ base.site_format = '%s'
40
+ super
41
+ end
42
+ end
43
+
44
+ # Find projects
45
+ #
46
+ # MingleAPI::Project.find(:all) # find all projects for the current account.
47
+ # MingleAPI::Project.find('my_project') # find individual project by ID
48
+ #
49
+ # Creating a Project
50
+ #
51
+ # project = MingleAPI::Project.new(:name => 'Ninja Whammy Jammy')
52
+ # project.save
53
+ # # => true
54
+ #
55
+ #
56
+ # Updating a Project
57
+ #
58
+ # project = MingleAPI::Project.find('my_project')
59
+ # project.name = "A new name"
60
+ # project.save
61
+ #
62
+ # Finding tickets
63
+ #
64
+ # project = MingleAPI::Project.find('my_project')
65
+ # project.tickets
66
+ #
67
+
68
+
69
+ class Project < Base
70
+
71
+ #begin monkey patches
72
+
73
+ def exists?(id, options = {})
74
+ begin
75
+ self.class.find(id)
76
+ true
77
+ rescue ActiveResource::ResourceNotFound, ActiveResource::ResourceGone
78
+ false
79
+ end
80
+ end
81
+
82
+ def new?
83
+ !self.exists?(id)
84
+ end
85
+
86
+ def element_path(options = nil)
87
+ self.class.element_path(self.id, options)
88
+ end
89
+
90
+ def encode(options={})
91
+ val = []
92
+ attributes.each_pair do |key, value|
93
+ val << "project[#{URI.escape key}]=#{URI.escape value}" rescue nil
94
+ end
95
+ val.join('&')
96
+ end
97
+
98
+ def create
99
+ connection.post(collection_path + '?' + encode, nil, self.class.headers).tap do |response|
100
+ self.id = id_from_response(response)
101
+ load_attributes_from_response(response)
102
+ end
103
+ end
104
+
105
+ #end monkey patches
106
+
107
+ def tickets(options = {})
108
+ Card.find(:all, :params => options.update(:identifier => id))
109
+ end
110
+
111
+ def id
112
+ @attributes['identifier']
113
+ end
114
+
115
+ end
116
+
117
+ # Find tickets
118
+ #
119
+ # MingleAPI::Ticket.find(:all, :params => { :identifier => 'my_project' })
120
+ #
121
+ # project = UnfuddleAPI::Project.find('my_project')
122
+ # project.tickets
123
+ # project.tickets(:name => 'a new name')
124
+ #
125
+
126
+
127
+ class Card < Base
128
+ self.site_format << '/projects/:identifier/'
129
+
130
+ #begin monkey patches
131
+
132
+ def element_path(options = nil)
133
+ self.class.element_path(self.number, options)
134
+ end
135
+
136
+ def encode(options={})
137
+ val = []
138
+ attributes.each_pair do |key, value|
139
+ unless value.nil?
140
+ case key
141
+ when 'card_type'
142
+ if value.is_a? Hash
143
+ name = value[:name]
144
+ else
145
+ name = value.name
146
+ end
147
+ val << "card[card_type_name]=#{URI.escape name}"
148
+ when 'properties'
149
+ value.each {|property|
150
+ val << "card[properties][][name]=#{URI.escape property[0]}
151
+ &card[properties][][value]=#{URI.escape property[1]}"} rescue NoMethodError
152
+ else
153
+ val << "card[#{URI.escape key.to_s}]=#{URI.escape value.to_s}" rescue nil
154
+ end
155
+ end
156
+ end
157
+ val.join('&')
158
+ end
159
+
160
+ def update
161
+ connection.put(element_path(prefix_options) + '?' + encode, nil, self.class.headers).tap do |response|
162
+ load_attributes_from_response(response)
163
+ end
164
+ end
165
+
166
+ def create
167
+ connection.post(collection_path + '?' + encode, nil, self.class.headers).tap do |response|
168
+ self.number = id_from_response(response)
169
+ load_attributes_from_response(response)
170
+ end
171
+ end
172
+
173
+ #end monkey patches
174
+
175
+ def number
176
+ @attributes['number']
177
+ end
178
+
179
+ def id
180
+ @attributes['id']
181
+ end
182
+
183
+ def name
184
+ @attributes['name']
185
+ end
186
+
187
+ def created_on
188
+ @attributes['created_on']
189
+ end
190
+
191
+ def modified_on
192
+ @attributes['modified_on']
193
+ end
194
+
195
+ def description
196
+ @attributes['description']
197
+ end
198
+
199
+ def card_type
200
+ @attributes['card_type']
201
+ end
202
+
203
+ def properties
204
+ @attributes['properties']
205
+ end
206
+
207
+ end
208
+
209
+ class Comment < Base
210
+ self.site_format << '/projects/:identifier/cards/:number'
211
+
212
+ def create
213
+ connection.post(collection_path + '?' + encode, nil, self.class.headers).tap do |response|
214
+ load_attributes_from_response(response)
215
+ end
216
+ end
217
+
218
+ def encode(options={})
219
+ val=[]
220
+ attributes.each_pair do |key, value|
221
+ val << "comment[#{URI.escape key}]=#{URI.escape value}" rescue nil
222
+ end
223
+ val.join('&')
224
+ end
225
+
226
+ end
227
+
228
+ end
@@ -0,0 +1,47 @@
1
+ module TaskMapper::Provider
2
+ module Mingle
3
+ # The comment class for taskmapper-mingle
4
+ #
5
+ # Do any mapping between TaskMapper and your system's comment model here
6
+ # versions of the ticket.
7
+ #
8
+ class Comment < TaskMapper::Provider::Base::Comment
9
+ API = MingleAPI::Comment # The class to access the api's comments
10
+ # declare needed overloaded methods here
11
+
12
+ def initialize(*object)
13
+ if object.first
14
+ object = object.first
15
+ @system_data = {:client => object}
16
+ unless object.is_a? Hash
17
+ hash = {:content => object.content,
18
+ :created_at => object.created_at,
19
+ :created_by => object.created_by,
20
+ :ticket_id => object.prefix_options[:number],
21
+ :project_id => object.prefix_options[:identifier]}
22
+ else
23
+ hash = object
24
+ end
25
+ super hash
26
+ end
27
+ end
28
+
29
+ def created_by
30
+ self[:created_by]
31
+ end
32
+
33
+ def created_at
34
+ self[:created_at]
35
+ end
36
+
37
+ def project_id
38
+ self[:identifier]
39
+ end
40
+
41
+ def ticket_id
42
+ self[:number]
43
+ end
44
+
45
+ end
46
+ end
47
+ end