confuddle 0.0.1
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 +18 -0
- data/.passwd_to_unfuddle.example.yml +7 -0
- data/README.md +40 -0
- data/bin/un +833 -0
- data/bin/un.cmd +1 -0
- data/confuddle.gemspec +22 -0
- data/lib/graft/README.rdoc +138 -0
- data/lib/graft/Rakefile +43 -0
- data/lib/graft/lib/graft/core_ext/hash.rb +9 -0
- data/lib/graft/lib/graft/json.rb +14 -0
- data/lib/graft/lib/graft/json/attribute.rb +18 -0
- data/lib/graft/lib/graft/json/model.rb +28 -0
- data/lib/graft/lib/graft/model.rb +43 -0
- data/lib/graft/lib/graft/version.rb +13 -0
- data/lib/graft/lib/graft/xml.rb +19 -0
- data/lib/graft/lib/graft/xml/attribute.rb +55 -0
- data/lib/graft/lib/graft/xml/model.rb +49 -0
- data/lib/graft/lib/graft/xml/type.rb +91 -0
- data/lib/graft/test/test_helper.rb +38 -0
- data/lib/graft/test/unit/core_ext/hash_test.rb +29 -0
- data/lib/graft/test/unit/json/attribute_test.rb +51 -0
- data/lib/graft/test/unit/json/model_test.rb +86 -0
- data/lib/graft/test/unit/xml/attribute_test.rb +161 -0
- data/lib/graft/test/unit/xml/model_test.rb +173 -0
- data/lib/graft/test/unit/xml/type_test.rb +65 -0
- data/lib/unfuzzle/.gitignore +4 -0
- data/lib/unfuzzle/README.rdoc +129 -0
- data/lib/unfuzzle/Rakefile +39 -0
- data/lib/unfuzzle/lib/unfuzzle.rb +87 -0
- data/lib/unfuzzle/lib/unfuzzle/comment.rb +37 -0
- data/lib/unfuzzle/lib/unfuzzle/component.rb +31 -0
- data/lib/unfuzzle/lib/unfuzzle/milestone.rb +54 -0
- data/lib/unfuzzle/lib/unfuzzle/person.rb +20 -0
- data/lib/unfuzzle/lib/unfuzzle/priority.rb +30 -0
- data/lib/unfuzzle/lib/unfuzzle/project.rb +62 -0
- data/lib/unfuzzle/lib/unfuzzle/request.rb +75 -0
- data/lib/unfuzzle/lib/unfuzzle/response.rb +25 -0
- data/lib/unfuzzle/lib/unfuzzle/severity.rb +31 -0
- data/lib/unfuzzle/lib/unfuzzle/ticket.rb +156 -0
- data/lib/unfuzzle/lib/unfuzzle/ticket_report.rb +29 -0
- data/lib/unfuzzle/lib/unfuzzle/time_entry.rb +75 -0
- data/lib/unfuzzle/lib/unfuzzle/version.rb +13 -0
- data/lib/unfuzzle/test/fixtures/component.xml +8 -0
- data/lib/unfuzzle/test/fixtures/components.xml +17 -0
- data/lib/unfuzzle/test/fixtures/milestone.xml +12 -0
- data/lib/unfuzzle/test/fixtures/milestones.xml +25 -0
- data/lib/unfuzzle/test/fixtures/project.xml +17 -0
- data/lib/unfuzzle/test/fixtures/projects.xml +35 -0
- data/lib/unfuzzle/test/fixtures/severities.xml +24 -0
- data/lib/unfuzzle/test/fixtures/severity.xml +8 -0
- data/lib/unfuzzle/test/fixtures/ticket.xml +25 -0
- data/lib/unfuzzle/test/fixtures/tickets.xml +51 -0
- data/lib/unfuzzle/test/test_helper.rb +60 -0
- data/lib/unfuzzle/test/unit/unfuzzle/component_test.rb +36 -0
- data/lib/unfuzzle/test/unit/unfuzzle/milestone_test.rb +100 -0
- data/lib/unfuzzle/test/unit/unfuzzle/priority_test.rb +25 -0
- data/lib/unfuzzle/test/unit/unfuzzle/project_test.rb +87 -0
- data/lib/unfuzzle/test/unit/unfuzzle/request_test.rb +104 -0
- data/lib/unfuzzle/test/unit/unfuzzle/response_test.rb +37 -0
- data/lib/unfuzzle/test/unit/unfuzzle/severity_test.rb +36 -0
- data/lib/unfuzzle/test/unit/unfuzzle/ticket_test.rb +181 -0
- data/lib/unfuzzle/test/unit/unfuzzle_test.rb +39 -0
- data/lib/unfuzzle/unfuzzle.gemspec +31 -0
- data/lib/version.rb +3 -0
- metadata +176 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
module Unfuzzle
|
2
|
+
|
3
|
+
#
|
4
|
+
class Comment
|
5
|
+
|
6
|
+
include Graft
|
7
|
+
|
8
|
+
attribute :id
|
9
|
+
attribute :created_at
|
10
|
+
attribute :body
|
11
|
+
attribute :author_id, :from => "author-id", :type => :integer
|
12
|
+
|
13
|
+
# Hash representation of this ticket's data (for updating)
|
14
|
+
def to_hash
|
15
|
+
{
|
16
|
+
'id' => id,
|
17
|
+
'body' => body,
|
18
|
+
'author-id' => author_id
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
# Return a list of all tickets for an individual project
|
23
|
+
def self.all_by_project_and_ticket(project_id, ticket_id)
|
24
|
+
response = Request.get("/projects/{id}/tickets/{id}/comments")
|
25
|
+
collection_from(response.body, 'comments/comment')
|
26
|
+
end
|
27
|
+
|
28
|
+
# Create a comment
|
29
|
+
def create(project_id, ticket_id)
|
30
|
+
resource_path = "/projects/#{project_id}/tickets/#{ticket_id}/comments"
|
31
|
+
Request.post(resource_path, self.to_xml('comment'))
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Unfuzzle
|
2
|
+
|
3
|
+
# = Component
|
4
|
+
#
|
5
|
+
# Represents a Component in an Unfuddle project. These are user-configurable
|
6
|
+
# and are custom for each project you have. Examples include 'Administration',
|
7
|
+
# 'User Registration', etc.. A component has the following attributes:
|
8
|
+
#
|
9
|
+
# [id] The unique id for this component
|
10
|
+
# [name] The name of this component (e.g User Registration)
|
11
|
+
# [created_at] The date/time that this component was created
|
12
|
+
# [updated_at] The date/time that this component was last updated
|
13
|
+
#
|
14
|
+
class Component
|
15
|
+
|
16
|
+
include Graft
|
17
|
+
|
18
|
+
attribute :id, :type => :integer
|
19
|
+
attribute :name
|
20
|
+
attribute :project_id, :from => 'project-id', :type => :integer
|
21
|
+
attribute :created_at, :from => 'created-at', :type => :time
|
22
|
+
attribute :updated_at, :from => 'updated-at', :type => :time
|
23
|
+
|
24
|
+
# Find a component by ID for a given project
|
25
|
+
def self.find_by_project_id_and_component_id(project_id, component_id)
|
26
|
+
response = Request.get("/projects/#{project_id}/components/#{component_id}")
|
27
|
+
new response.body
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Unfuzzle
|
2
|
+
|
3
|
+
# = Milestone
|
4
|
+
#
|
5
|
+
# A representation of an Unfuddle Milestone. Has the following attributes:
|
6
|
+
#
|
7
|
+
# [id] Unique identifier for this milestone
|
8
|
+
# [name] Name of the milestone
|
9
|
+
# [archived] The archived status of this milestone (see Milestone#archived?)
|
10
|
+
# [due_on] The due date for this milestone
|
11
|
+
# [created_at] The date/time that this milestone was created
|
12
|
+
# [updated_at] The date/time that this milestone was last updated
|
13
|
+
#
|
14
|
+
class Milestone
|
15
|
+
|
16
|
+
include Graft
|
17
|
+
|
18
|
+
attribute :id, :type => :integer
|
19
|
+
attribute :project_id, :from => 'project-id', :type => :integer
|
20
|
+
attribute :archived, :type => :boolean
|
21
|
+
attribute :name, :from => 'title'
|
22
|
+
attribute :created_at, :from => 'created-at', :type => :time
|
23
|
+
attribute :updated_at, :from => 'updated-at', :type => :time
|
24
|
+
attribute :due_on, :from => 'due-on', :type => :date
|
25
|
+
|
26
|
+
# Return a list of all milestones for a given project
|
27
|
+
def self.find_all_by_project_id(project_id)
|
28
|
+
response = Request.get("/projects/#{project_id}/milestones")
|
29
|
+
collection_from(response.body, 'milestones/milestone')
|
30
|
+
end
|
31
|
+
|
32
|
+
# Find a milestone by ID for a given project
|
33
|
+
def self.find_by_project_id_and_milestone_id(project_id, milestone_id)
|
34
|
+
response = Request.get("/projects/#{project_id}/milestones/#{milestone_id}")
|
35
|
+
new response.body
|
36
|
+
end
|
37
|
+
|
38
|
+
# Has this milestone been archived?
|
39
|
+
def archived?
|
40
|
+
archived == true
|
41
|
+
end
|
42
|
+
|
43
|
+
# Does this milestone occur in the past?
|
44
|
+
def past?
|
45
|
+
due_on < Date.today
|
46
|
+
end
|
47
|
+
|
48
|
+
# The collection of Tickets associated to this milestone
|
49
|
+
def tickets
|
50
|
+
Ticket.find_all_by_project_id_and_milestone_id(project_id, id)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Unfuzzle
|
2
|
+
class Person
|
3
|
+
include Graft
|
4
|
+
attribute :id, :type => :integer
|
5
|
+
attribute :first_name, :from => 'first-name'
|
6
|
+
attribute :last_name, :from => 'last-name'
|
7
|
+
attribute :username, :from => 'username'
|
8
|
+
|
9
|
+
def self.all
|
10
|
+
response = Request.get("/people")
|
11
|
+
collection_from(response.body, 'people/person')
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.all_for_project(project_id)
|
15
|
+
response = Request.get("/projects/#{project_id}/people")
|
16
|
+
collection_from(response.body, 'people/person')
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Unfuzzle
|
2
|
+
|
3
|
+
# = Priority
|
4
|
+
#
|
5
|
+
# Represents a priority for a ticket.
|
6
|
+
#
|
7
|
+
class Priority
|
8
|
+
|
9
|
+
def initialize(id)
|
10
|
+
@id = id
|
11
|
+
end
|
12
|
+
|
13
|
+
# The name of the priority based on the supplied ID
|
14
|
+
def name
|
15
|
+
mapping[@id]
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
def mapping
|
20
|
+
{
|
21
|
+
5 => 'Highest',
|
22
|
+
4 => 'High',
|
23
|
+
3 => 'Normal',
|
24
|
+
2 => 'Low',
|
25
|
+
1 => 'Lowest'
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Unfuzzle
|
2
|
+
|
3
|
+
# = Project
|
4
|
+
#
|
5
|
+
# Represents an Unfuddle project. Has the following attributes:
|
6
|
+
#
|
7
|
+
# [id] The unique identifier for this project
|
8
|
+
# [slug] The "short name" for this project
|
9
|
+
# [name] The name of this project
|
10
|
+
# [description] The description for the project
|
11
|
+
# [archived] The archived status of this project (see Project#archived?)
|
12
|
+
# [created_at] The date/time that this project was created
|
13
|
+
# [updated_at] The date/time that this project was last updated
|
14
|
+
#
|
15
|
+
class Project
|
16
|
+
|
17
|
+
include Graft
|
18
|
+
|
19
|
+
attribute :id, :type => :integer
|
20
|
+
attribute :slug, :from => 'short-name'
|
21
|
+
attribute :archived, :type => :boolean
|
22
|
+
attribute :name, :from => 'title'
|
23
|
+
attribute :description
|
24
|
+
attribute :created_at, :from => 'created-at', :type => :time
|
25
|
+
attribute :updated_at, :from => 'updated-at', :type => :time
|
26
|
+
attribute :disk_usage, :from => 'disk-usage'
|
27
|
+
|
28
|
+
# Return a list of all projects to which the current user has access
|
29
|
+
def self.all
|
30
|
+
response = Request.get('/projects')
|
31
|
+
collection_from(response.body, 'projects/project')
|
32
|
+
end
|
33
|
+
|
34
|
+
# Find a single project by its slug (short name)
|
35
|
+
def self.find_by_slug(slug)
|
36
|
+
response = Request.get("/projects/by_short_name/#{slug}")
|
37
|
+
new(response.body)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Find a single project by its ID
|
41
|
+
def self.find_by_id(id)
|
42
|
+
response = Request.get("/projects/#{id}")
|
43
|
+
new(response.body)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Has this project been archived?
|
47
|
+
def archived?
|
48
|
+
archived == true
|
49
|
+
end
|
50
|
+
|
51
|
+
# The collection of Milestones associated to this project
|
52
|
+
def milestones
|
53
|
+
Milestone.find_all_by_project_id(id)
|
54
|
+
end
|
55
|
+
|
56
|
+
# The collection of Tickets associated to this project
|
57
|
+
def tickets
|
58
|
+
Ticket.find_all_by_project_id(id)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Unfuzzle
|
2
|
+
|
3
|
+
# = Request
|
4
|
+
#
|
5
|
+
# A basic wrapper for GET requests to the Unfuddle API
|
6
|
+
#
|
7
|
+
class Request
|
8
|
+
|
9
|
+
# Retrieve a response from the given resource path
|
10
|
+
def self.get(resource_path, query = nil)
|
11
|
+
request = new(resource_path, nil, query)
|
12
|
+
request.get
|
13
|
+
end
|
14
|
+
|
15
|
+
# Send a POST request with data and retrieve a Response
|
16
|
+
def self.post(resource_path, payload)
|
17
|
+
request = new(resource_path, payload)
|
18
|
+
request.post
|
19
|
+
end
|
20
|
+
|
21
|
+
# Send a PUT request with data and retrieve a Response
|
22
|
+
def self.put(resource_path, payload)
|
23
|
+
request = new(resource_path, payload)
|
24
|
+
request.put
|
25
|
+
end
|
26
|
+
|
27
|
+
# Create a new request for the given resource path
|
28
|
+
def initialize(resource_path, payload = nil, query = nil)
|
29
|
+
@resource_path = resource_path
|
30
|
+
@payload = payload
|
31
|
+
@query = query
|
32
|
+
end
|
33
|
+
|
34
|
+
def endpoint_uri # :nodoc:
|
35
|
+
url = "https://#{Unfuzzle.subdomain}.unfuddle.com/api/v1#{@resource_path}.xml"
|
36
|
+
url += @query if @query
|
37
|
+
URI.parse(url)
|
38
|
+
end
|
39
|
+
|
40
|
+
def client # :nodoc:
|
41
|
+
http = Net::HTTP.new(endpoint_uri.host, endpoint_uri.port)
|
42
|
+
if Unfuzzle.use_ssl
|
43
|
+
http.use_ssl = true
|
44
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
45
|
+
end
|
46
|
+
http
|
47
|
+
end
|
48
|
+
|
49
|
+
# Retrieve a response from the current resource path
|
50
|
+
def get
|
51
|
+
request = Net::HTTP::Get.new(endpoint_uri.request_uri)
|
52
|
+
request.basic_auth Unfuzzle.username, Unfuzzle.password
|
53
|
+
Response.new(client.request(request))
|
54
|
+
end
|
55
|
+
|
56
|
+
# Send a POST request to the configured endpoint
|
57
|
+
def post
|
58
|
+
request = Net::HTTP::Post.new(endpoint_uri.request_uri)
|
59
|
+
request.basic_auth Unfuzzle.username, Unfuzzle.password
|
60
|
+
request.content_type = 'application/xml'
|
61
|
+
|
62
|
+
Response.new(client.request(request, @payload))
|
63
|
+
end
|
64
|
+
|
65
|
+
# Send a PUT request to the configured endpoint
|
66
|
+
def put
|
67
|
+
request = Net::HTTP::Put.new(endpoint_uri.request_uri)
|
68
|
+
request.basic_auth Unfuzzle.username, Unfuzzle.password
|
69
|
+
request.content_type = 'application/xml'
|
70
|
+
|
71
|
+
Response.new(client.request(request, @payload))
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Unfuzzle
|
2
|
+
|
3
|
+
# = Response
|
4
|
+
#
|
5
|
+
# A simple wrapper around an HTTP response from the Unfuddle API
|
6
|
+
#
|
7
|
+
class Response
|
8
|
+
|
9
|
+
# Create a new response from an HTTP response object
|
10
|
+
def initialize(http_response)
|
11
|
+
@http_response = http_response
|
12
|
+
end
|
13
|
+
|
14
|
+
# Was there an error produced as part of the request?
|
15
|
+
def error?
|
16
|
+
!@http_response.is_a?(Net::HTTPSuccess)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Raw body of the HTTP response
|
20
|
+
def body
|
21
|
+
@http_response.body
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Unfuzzle
|
2
|
+
|
3
|
+
# = Severity
|
4
|
+
#
|
5
|
+
# Represents a Severity in an Unfuddle project. These are user-configurable
|
6
|
+
# and are custom for each project you have. Examples include 'Story',
|
7
|
+
# 'Defect', etc.. A severity has the following attributes:
|
8
|
+
#
|
9
|
+
# [id] The unique identifier for this severity
|
10
|
+
# [name] The name of this severity
|
11
|
+
# [created_at] The date/time that this severity was created
|
12
|
+
# [updated_at] The date/time that this severity was last updated
|
13
|
+
#
|
14
|
+
class Severity
|
15
|
+
|
16
|
+
include Graft
|
17
|
+
|
18
|
+
attribute :id, :type => :integer
|
19
|
+
attribute :name
|
20
|
+
attribute :project_id, :from => 'project-id', :type => :integer
|
21
|
+
attribute :created_at, :from => 'created-at', :type => :time
|
22
|
+
attribute :updated_at, :from => 'updated-at', :type => :time
|
23
|
+
|
24
|
+
# Find the severity by ID for a given project
|
25
|
+
def self.find_by_project_id_and_severity_id(project_id, severity_id)
|
26
|
+
response = Request.get("/projects/#{project_id}/severities/#{severity_id}")
|
27
|
+
new response.body
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
module Unfuzzle
|
2
|
+
|
3
|
+
# = Ticket
|
4
|
+
#
|
5
|
+
# Represents a single Unfuddle Ticket - is associated to a project
|
6
|
+
# and optionally a project's milestone. Has the following attributes:
|
7
|
+
#
|
8
|
+
# [id] The unique identifier for this ticket
|
9
|
+
# [number] The ticket's number - this is displayed in the web interface
|
10
|
+
# [title] The title of the ticket (short)
|
11
|
+
# [description] The full description of the ticket
|
12
|
+
# [status] The ticket's status (new / accepted / resolved / closed)
|
13
|
+
# [due_on] The due date for this ticket
|
14
|
+
# [created_at] The date/time that this ticket was created
|
15
|
+
# [updated_at] The date/time that this ticket was last updated
|
16
|
+
#
|
17
|
+
class Ticket
|
18
|
+
|
19
|
+
include Graft
|
20
|
+
|
21
|
+
attribute :id, :type => :integer
|
22
|
+
attribute :project_id, :from => 'project-id', :type => :integer
|
23
|
+
attribute :milestone_id, :from => 'milestone-id', :type => :integer
|
24
|
+
attribute :component_id, :from => 'component-id', :type => :integer
|
25
|
+
attribute :priority, :type => :integer
|
26
|
+
attribute :number, :type => :integer
|
27
|
+
attribute :title, :from => 'summary'
|
28
|
+
attribute :description
|
29
|
+
attribute :due_on, :from => 'due-on', :type => :date
|
30
|
+
attribute :created_at, :from => 'created-at', :type => :time
|
31
|
+
attribute :updated_at, :from => 'updated-at', :type => :time
|
32
|
+
attribute :severity_id, :from => 'severity-id', :type => :integer
|
33
|
+
attribute :assignee_id, :from => 'assignee-id', :type => :integer
|
34
|
+
attribute :reporter_id, :from => 'reporter-id', :type => :integer
|
35
|
+
attribute :status
|
36
|
+
attribute :hours, :from => 'hours-estimate-current'
|
37
|
+
|
38
|
+
|
39
|
+
def initialize(*args)
|
40
|
+
self.priority = 3
|
41
|
+
self.status = "new"
|
42
|
+
super(*args)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Return a list of all tickets for an individual project
|
46
|
+
def self.find_all_by_project_id(project_id)
|
47
|
+
response = Request.get("/projects/#{project_id}/tickets")
|
48
|
+
collection_from(response.body, 'tickets/ticket')
|
49
|
+
end
|
50
|
+
|
51
|
+
# Return a list of all tickets for a given milestone as part of a project
|
52
|
+
def self.find_all_by_project_id_and_milestone_id(project_id, milestone_id)
|
53
|
+
response = Request.get("/projects/#{project_id}/milestones/#{milestone_id}/tickets")
|
54
|
+
collection_from(response.body, 'tickets/ticket')
|
55
|
+
end
|
56
|
+
|
57
|
+
# Return a list of all tickets for a given milestone as part of a project
|
58
|
+
def self.find_first_by_project_id_and_number(project_id, number)
|
59
|
+
response = Request.get("/projects/#{project_id}/tickets/by_number/#{number}")
|
60
|
+
new(response.body)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Return a list of all tickets for a given milestone as part of a project
|
64
|
+
def self.find_first_by_project_id_and_number_with_comments(project_id, number)
|
65
|
+
response = Request.get("/projects/#{project_id}/tickets/by_number/#{number}", "?comments=true")
|
66
|
+
[new(response.body), Comment.collection_from(response.body, 'comments/comment')]
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def self.find_all_by_project_and_report(project_id, report_id)
|
71
|
+
response = Request.get("/projects/#{project_id}/ticket_reports/#{report_id}/generate")
|
72
|
+
collection_from(response.body, 'tickets/ticket')
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
def self.all_by_dinamic_report(with_project_ids = nil, only_my_tickets = false)
|
77
|
+
query = "?title=Dynamic&conditions_string=status-neq-closed"
|
78
|
+
query += ",assignee-eq-current" if only_my_tickets
|
79
|
+
query += "&fields_string=id,number,title,hours,assignee,status,reporter"
|
80
|
+
|
81
|
+
res = []
|
82
|
+
|
83
|
+
if with_project_ids.blank?
|
84
|
+
response = Request.get("/ticket_reports/dynamic", query)
|
85
|
+
res = collection_from(response.body, 'tickets/ticket')
|
86
|
+
else
|
87
|
+
with_project_ids.each do |id|
|
88
|
+
response = Request.get("/projects/#{id}/ticket_reports/dynamic", query)
|
89
|
+
res << collection_from(response.body, 'tickets/ticket')
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
res.flatten
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
# The Milestone associated with this ticket
|
98
|
+
def milestone
|
99
|
+
Milestone.find_by_project_id_and_milestone_id(project_id, milestone_id)
|
100
|
+
end
|
101
|
+
|
102
|
+
# The Severity associated with this ticket
|
103
|
+
def severity
|
104
|
+
Severity.find_by_project_id_and_severity_id(project_id, severity_id) unless severity_id.nil?
|
105
|
+
end
|
106
|
+
|
107
|
+
def severity_name
|
108
|
+
severity.name unless severity.nil?
|
109
|
+
end
|
110
|
+
|
111
|
+
def priority_name
|
112
|
+
# priority.name
|
113
|
+
Priority.new(priority).name
|
114
|
+
end
|
115
|
+
|
116
|
+
# The Component associated with this ticket
|
117
|
+
def component
|
118
|
+
Component.find_by_project_id_and_component_id(project_id, component_id) unless component_id.nil?
|
119
|
+
end
|
120
|
+
|
121
|
+
def component_name
|
122
|
+
component.name unless component.nil?
|
123
|
+
end
|
124
|
+
|
125
|
+
# Hash representation of this ticket's data (for updating)
|
126
|
+
def to_hash
|
127
|
+
{
|
128
|
+
'id' => id,
|
129
|
+
'project-id' => project_id,
|
130
|
+
'milestone-id' => milestone_id,
|
131
|
+
'priority' => priority,
|
132
|
+
'severity-id' => severity_id,
|
133
|
+
'number' => number,
|
134
|
+
'summary' => title,
|
135
|
+
'description' => description,
|
136
|
+
'status' => status,
|
137
|
+
'assignee-id' => assignee_id,
|
138
|
+
'reporter-id' => reporter_id#,
|
139
|
+
#'hours' => hours
|
140
|
+
}
|
141
|
+
end
|
142
|
+
|
143
|
+
# Update the ticket's data in unfuddle
|
144
|
+
def update
|
145
|
+
resource_path = "/projects/#{project_id}/tickets/#{id}"
|
146
|
+
Request.put(resource_path, self.to_xml('ticket'))
|
147
|
+
end
|
148
|
+
|
149
|
+
# Create a ticket in unfuddle
|
150
|
+
def create
|
151
|
+
resource_path = "/projects/#{project_id}/tickets"
|
152
|
+
Request.post(resource_path, self.to_xml('ticket'))
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
end
|