taskmapper-mingle 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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