taskmapper-basecamp 0.5.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/.document +5 -0
- data/.travis.yml +4 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +52 -0
- data/LICENSE +20 -0
- data/README.md +63 -0
- data/Rakefile +41 -0
- data/VERSION +1 -0
- data/lib/basecamp/basecamp.rb +655 -0
- data/lib/provider/basecamp.rb +39 -0
- data/lib/provider/comment.rb +63 -0
- data/lib/provider/project.rb +94 -0
- data/lib/provider/ticket.rb +162 -0
- data/lib/taskmapper-basecamp.rb +5 -0
- data/spec/comments_spec.rb +103 -0
- data/spec/fixtures/comments/74197051.json +1 -0
- data/spec/fixtures/comments/74197051.xml +14 -0
- data/spec/fixtures/comments/74197096.json +1 -0
- data/spec/fixtures/comments/74197096.xml +14 -0
- data/spec/fixtures/comments.json +1 -0
- data/spec/fixtures/comments.xml +47 -0
- data/spec/fixtures/project_count.json +1 -0
- data/spec/fixtures/project_count.xml +5 -0
- data/spec/fixtures/projects/5220065.json +1 -0
- data/spec/fixtures/projects/5220065.xml +16 -0
- data/spec/fixtures/projects/create.json +1 -0
- data/spec/fixtures/projects/create.xml +2 -0
- data/spec/fixtures/projects.json +1 -0
- data/spec/fixtures/projects.xml +19 -0
- data/spec/fixtures/todo_items/62509330_todo_item.xml +15 -0
- data/spec/fixtures/todo_list_9972756.xml +14 -0
- data/spec/fixtures/todo_list_with_items.json +1 -0
- data/spec/fixtures/todo_list_with_items.xml +3477 -0
- data/spec/fixtures/todo_lists/9972756_items.json +1 -0
- data/spec/fixtures/todo_lists/9972756_items.xml +93 -0
- data/spec/fixtures/todo_lists/9973518_items.json +1 -0
- data/spec/fixtures/todo_lists/9973518_items.xml +98 -0
- data/spec/fixtures/todo_lists/create.json +1 -0
- data/spec/fixtures/todo_lists/create.xml +14 -0
- data/spec/fixtures/todo_lists.json +1 -0
- data/spec/fixtures/todo_lists.xml +29 -0
- data/spec/projects_spec.rb +83 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/taskmapper-basecamp_spec.rb +20 -0
- data/spec/tickets_spec.rb +87 -0
- data/taskmapper-basecamp.gemspec +100 -0
- metadata +201 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
module TaskMapper::Provider
|
2
|
+
module Basecamp
|
3
|
+
# The comment class for taskmapper-basecamp
|
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
|
+
# declare needed overloaded methods here
|
10
|
+
API = BasecampAPI::Comment
|
11
|
+
|
12
|
+
def initialize(*object)
|
13
|
+
if object.first
|
14
|
+
object = object.first
|
15
|
+
unless object.is_a? Hash
|
16
|
+
hash = {:id => object.id,
|
17
|
+
:body => object.body,
|
18
|
+
:author => object.author_name,
|
19
|
+
:created_at => object.created_at,
|
20
|
+
:project_id => object.project_id,
|
21
|
+
:ticket_id => object.ticket_id}
|
22
|
+
else
|
23
|
+
hash = object
|
24
|
+
end
|
25
|
+
super hash
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.find_by_id(project_id, ticket_id, id)
|
30
|
+
basecamp_comment = self::API.find(id, :params => {:todo_item_id => ticket_id})
|
31
|
+
self.new basecamp_comment.attributes.merge!(:project_id => project_id, :ticket_id => ticket_id)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.find_by_attributes(project_id, ticket_id, attributes = {})
|
35
|
+
self.search(project_id, ticket_id, attributes)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.search(project_id, ticket_id, options = {}, limit = 1000)
|
39
|
+
comments = API.find(:all, :params => {:todo_item_id => ticket_id}).collect {|c| self.new(c.attributes.merge!(:project_id => project_id, :ticket_id => ticket_id)) }
|
40
|
+
search_by_attribute(comments, options, limit)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.create(ticket_id, attributes)
|
44
|
+
new_comment = API.new attributes.merge(:todo_item_id => ticket_id)
|
45
|
+
new_comment.save
|
46
|
+
|
47
|
+
reloaded_comment = find_bc_comment(ticket_id, new_comment.id)
|
48
|
+
self.new reloaded_comment.attributes.merge!(:ticket_id => ticket_id)
|
49
|
+
end
|
50
|
+
|
51
|
+
def save
|
52
|
+
bc_comment = self.class.find_bc_comment ticket_id, id
|
53
|
+
bc_comment.body = self.body
|
54
|
+
bc_comment.save
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
def self.find_bc_comment(ticket_id, id)
|
59
|
+
API.find id, :params => { :todo_item_id => ticket_id }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module TaskMapper::Provider
|
2
|
+
module Basecamp
|
3
|
+
# Project class for taskampper-basecamp
|
4
|
+
#
|
5
|
+
# Remaps
|
6
|
+
#
|
7
|
+
# description => announcement
|
8
|
+
# created_at => created_on
|
9
|
+
# updated_at => last_changed_on
|
10
|
+
class Project < TaskMapper::Provider::Base::Project
|
11
|
+
API = BasecampAPI::Project
|
12
|
+
|
13
|
+
def initialize(*object)
|
14
|
+
if object.first
|
15
|
+
object = object.first
|
16
|
+
unless object.is_a? Hash
|
17
|
+
hash = {:id => object.id,
|
18
|
+
:created_at => created_on,
|
19
|
+
:updated_at => updated_on,
|
20
|
+
:description => object.announcement,
|
21
|
+
:name => object.name}
|
22
|
+
|
23
|
+
else
|
24
|
+
hash = object
|
25
|
+
end
|
26
|
+
super hash
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def description
|
31
|
+
announcement
|
32
|
+
end
|
33
|
+
|
34
|
+
def description=(desc)
|
35
|
+
announcement = desc
|
36
|
+
end
|
37
|
+
|
38
|
+
def created_at
|
39
|
+
begin
|
40
|
+
created_on.to_time
|
41
|
+
rescue
|
42
|
+
created_on
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def created_at=(created)
|
47
|
+
created_on = created
|
48
|
+
end
|
49
|
+
|
50
|
+
def updated_at
|
51
|
+
begin
|
52
|
+
last_changed_on.to_time
|
53
|
+
rescue
|
54
|
+
last_changed_on
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def updated_at=(updated)
|
59
|
+
last_changed_on = updated
|
60
|
+
end
|
61
|
+
|
62
|
+
def ticket!(attributes_hash)
|
63
|
+
provider_parent(self.class)::Ticket.create attributes_hash.merge :project_id => id
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.find_by_id(id)
|
67
|
+
self.new API.find(id)
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.find_by_attributes(attributes = {})
|
71
|
+
self.search(attributes)
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.search(options = {}, limit = 1000)
|
75
|
+
projects = API.find(:all).collect { |project| self.new project }
|
76
|
+
search_by_attribute(projects, options, limit)
|
77
|
+
end
|
78
|
+
|
79
|
+
# copy from this.copy(that) copies that into this
|
80
|
+
def copy(project)
|
81
|
+
project.tickets.each do |ticket|
|
82
|
+
copy_ticket = self.ticket!(:title => ticket.title, :description => ticket.description)
|
83
|
+
ticket.comments.each do |comment|
|
84
|
+
copy_ticket.comment!(:body => comment.body)
|
85
|
+
sleep 1
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
@@ -0,0 +1,162 @@
|
|
1
|
+
module TaskMapper::Provider
|
2
|
+
module Basecamp
|
3
|
+
# Ticket class for taskmapper-basecamp
|
4
|
+
#
|
5
|
+
#
|
6
|
+
# * status => completed (either completed or incomplete)
|
7
|
+
# * priority => position
|
8
|
+
# * title => TodoList#name - TodoItem#content (up to 100 characters)
|
9
|
+
# * resolution => completed (either completed or '')
|
10
|
+
# * updated_at => completed_on
|
11
|
+
# * description => content
|
12
|
+
# * assignee => responsible_party_name (read-only)
|
13
|
+
# * requestor => creator_name (read-only)
|
14
|
+
# * project_id
|
15
|
+
class Ticket < TaskMapper::Provider::Base::Ticket
|
16
|
+
def initialize(*options)
|
17
|
+
@system_data ||= {}
|
18
|
+
@cache ||= {}
|
19
|
+
first = options.first
|
20
|
+
case first
|
21
|
+
when Hash
|
22
|
+
super(first.to_hash)
|
23
|
+
else
|
24
|
+
@system_data[:client] = first
|
25
|
+
super(first.attributes)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
|
31
|
+
def find_by_id(project_id, id)
|
32
|
+
find_by_attributes(project_id, {:id => id}).first
|
33
|
+
end
|
34
|
+
|
35
|
+
def find_by_attributes(project_id, attributes = {})
|
36
|
+
search(project_id, attributes)
|
37
|
+
end
|
38
|
+
|
39
|
+
def search(project_id, options = {}, limit = 1000)
|
40
|
+
tickets = todo_items(project_id).map {|ti| self.new ti.attributes.merge :project_id => project_id }
|
41
|
+
search_by_attribute(tickets, options, limit)
|
42
|
+
end
|
43
|
+
|
44
|
+
# It expects a single hash
|
45
|
+
def create(attributes_hash)
|
46
|
+
todo_item_hash = create_todo_item_hash attributes_hash
|
47
|
+
todo_item = create_todo_item todo_item_hash
|
48
|
+
|
49
|
+
return nil unless todo_item.save
|
50
|
+
|
51
|
+
todo_item.project_id = attributes_hash[:project_id]
|
52
|
+
todo_item.todo_list_id = todo_item_hash[:todo_list_id]
|
53
|
+
self.new(todo_item)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def all_todo_lists
|
58
|
+
BasecampAPI::TodoListWithItems.find(:all, :params => {:responsible_party => ''})
|
59
|
+
end
|
60
|
+
|
61
|
+
def project_todo_lists(project_id)
|
62
|
+
all_todo_lists.select {|l| l.project_id == project_id }
|
63
|
+
end
|
64
|
+
|
65
|
+
def todo_items(project_id)
|
66
|
+
project_todo_lists(project_id).map { |l| l.todo_items }.flatten
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def create_todo_item_hash(ticket_hash)
|
71
|
+
a = ticket_hash
|
72
|
+
validate_ticket_hash a
|
73
|
+
todo_item_hash = {
|
74
|
+
:content => a[:title],
|
75
|
+
:position => a[:priority] || 1,
|
76
|
+
:todo_list_id => a[:todo_list_id] || create_todo_list({
|
77
|
+
:project_id => a[:project_id],
|
78
|
+
:name => "#{a[:title]} list"}).id
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
def create_todo_item(attributes_hash)
|
83
|
+
BasecampAPI::TodoItem.new(attributes_hash)
|
84
|
+
end
|
85
|
+
|
86
|
+
def validate_ticket_hash(attributes_hash)
|
87
|
+
title = attributes_hash[:title]
|
88
|
+
raise ArgumentError.new "Title is required" if title.nil? or title.empty?
|
89
|
+
end
|
90
|
+
|
91
|
+
def create_todo_list(attributes)
|
92
|
+
BasecampAPI::TodoList.create(attributes)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def copy_to(todo_item)
|
97
|
+
todo_item.completed = status
|
98
|
+
todo_item.position = priority
|
99
|
+
todo_item.name = title
|
100
|
+
todo_item.content = title
|
101
|
+
todo_item.completed = resolution
|
102
|
+
todo_item.responsible_party_name = assignee
|
103
|
+
todo_item.creator_name = requestor
|
104
|
+
todo_item
|
105
|
+
end
|
106
|
+
|
107
|
+
def save
|
108
|
+
todo_item = BasecampAPI::TodoItem.find id, :params => { :todo_list_id => todo_list_id }
|
109
|
+
copy_to(todo_item).save
|
110
|
+
end
|
111
|
+
|
112
|
+
def todo_list_id
|
113
|
+
self['todo_list_id'].to_i
|
114
|
+
end
|
115
|
+
|
116
|
+
def status
|
117
|
+
self.completed ? 'completed' : 'incomplete'
|
118
|
+
end
|
119
|
+
|
120
|
+
def priority
|
121
|
+
self.position
|
122
|
+
end
|
123
|
+
|
124
|
+
def priority=(pri)
|
125
|
+
self.position = pri
|
126
|
+
end
|
127
|
+
|
128
|
+
def title
|
129
|
+
self.content
|
130
|
+
end
|
131
|
+
|
132
|
+
def title=(titl)
|
133
|
+
self.content = titl
|
134
|
+
end
|
135
|
+
|
136
|
+
def updated_at=(comp)
|
137
|
+
self.completed_on = comp
|
138
|
+
end
|
139
|
+
|
140
|
+
def description
|
141
|
+
self.content
|
142
|
+
end
|
143
|
+
|
144
|
+
def description=(desc)
|
145
|
+
self.content = desc
|
146
|
+
end
|
147
|
+
|
148
|
+
def assignee
|
149
|
+
self.responsible_party_name
|
150
|
+
end
|
151
|
+
|
152
|
+
def requestor
|
153
|
+
self.creator_name
|
154
|
+
end
|
155
|
+
|
156
|
+
def comment!(attributes)
|
157
|
+
Comment.create id, attributes
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe TaskMapper::Provider::Basecamp::Comment do
|
4
|
+
let(:project_id) { 5220065 }
|
5
|
+
let(:ticket_id) {133184178 }
|
6
|
+
let(:tm) { TaskMapper.new(:basecamp, :domain => 'ticketmaster.basecamphq.com', :token => '000000') }
|
7
|
+
let(:comment_class) { TaskMapper::Provider::Basecamp::Comment }
|
8
|
+
let(:comment_id) { 74197051 }
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
@headers = {'Authorization' => 'Basic MDAwMDAwOkJhc2VjYW1w'}
|
12
|
+
gheaders = @headers.merge 'Accept' => 'application/xml'
|
13
|
+
|
14
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
15
|
+
mock.get '/projects/5220065.xml', @headers, fixture_for('projects/5220065'), 200
|
16
|
+
mock.get '/todo_lists.xml?responsible_party=', @headers, fixture_for('todo_list_with_items'), 200
|
17
|
+
end
|
18
|
+
@project = tm.project(project_id)
|
19
|
+
@ticket = @project.ticket(ticket_id)
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "Retrieving comments" do
|
23
|
+
before(:each) do
|
24
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
25
|
+
mock.get '/todo_items/133184178/comments.xml', @headers, fixture_for('comments'), 200
|
26
|
+
mock.get '/todo_items/133184178/comments/74197051.xml', @headers, fixture_for('comments/74197051'), 200
|
27
|
+
mock.get '/todo_items/133184178/comments/74197096.xml', @headers, fixture_for('comments/74197096'), 200
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "when #comments is call to a ticket instance" do
|
32
|
+
subject { @ticket.comments }
|
33
|
+
it { should be_an_instance_of(Array) }
|
34
|
+
it { subject.first.should be_an_instance_of(comment_class) }
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when #comments is call to a ticket instance with an array of id's as parameters" do
|
38
|
+
subject { @ticket.comments([74197051, 74197096]) }
|
39
|
+
it { should be_an_instance_of(Array) }
|
40
|
+
it { subject.first.should be_an_instance_of(comment_class) }
|
41
|
+
it { subject.first.id.should be_eql(74197051) }
|
42
|
+
it { subject.last.id.should be_eql(74197096) }
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when #comments is call to a ticket instance with comments attributes as parameters" do
|
46
|
+
subject { @ticket.comments(:id => comment_id) }
|
47
|
+
it { should be_an_instance_of(Array) }
|
48
|
+
it { subject.first.should be_an_instance_of(comment_class) }
|
49
|
+
it { subject.first.id.should be_eql(comment_id) }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "Retrieve a single comment from a ticket" do
|
54
|
+
before(:each) do
|
55
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
56
|
+
mock.get '/todo_items/133184178/comments.xml', @headers, fixture_for('comments'), 200
|
57
|
+
mock.get '/todo_items/133184178/comments/74197051.xml', @headers, fixture_for('comments/74197051'), 200
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when #comment is call with a comment id" do
|
62
|
+
subject { @ticket.comment(comment_id) }
|
63
|
+
it { should be_an_instance_of(comment_class) }
|
64
|
+
it { subject.id.should be_eql(comment_id) }
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when #comment is call with an attribute" do
|
68
|
+
subject { @ticket.comment(:id => comment_id) }
|
69
|
+
it { should be_an_instance_of(comment_class) }
|
70
|
+
it { subject.id.should be_eql(comment_id) }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "Create and update a comment for a ticket" do
|
75
|
+
before(:each) do
|
76
|
+
pheaders = @headers.merge 'Content-Type'=>'application/xml'
|
77
|
+
ActiveResource::HttpMock.respond_to do |mock|
|
78
|
+
mock.get '/todo_items/133184178/comments/74197051.xml', @headers, fixture_for('comments/74197051'), 200
|
79
|
+
mock.get '/todo_items/133184178/comments.xml', @headers, fixture_for('comments'), 200
|
80
|
+
mock.put '/todo_items/133184178/comments/74197051.xml', @headers, '', 200
|
81
|
+
mock.post '/todo_items/133184178/comments.xml', pheaders, fixture_for('comments/74197051'), 200
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "when a comment is changed and then called the #save on it" do
|
86
|
+
it do
|
87
|
+
comment = @ticket.comment(comment_id)
|
88
|
+
comment.body = "updated comment"
|
89
|
+
comment.save.should be_true
|
90
|
+
comment.body.should be_eql("updated comment")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "when #comment! is call" do
|
95
|
+
subject { @ticket.comment!(:body => 'hello there boys and girls') }
|
96
|
+
it { should be_an_instance_of(comment_class) }
|
97
|
+
it { subject.body.should_not be_nil }
|
98
|
+
it { subject.id.should_not be_nil }
|
99
|
+
it { subject.ticket_id.should_not be_nil }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
{"comment":{"attachments_count":0,"author_id":5654019,"body":"<div>Hello There<br /></div>","commentable_id":62509330,"commentable_type":"TodoItem","created_at":"2010-07-23 23:13:39 UTC","emailed_from":null,"id":74197051,"author_name":"Kia Kroas","attachments":[]}}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<comment>
|
3
|
+
<attachments-count type="integer">0</attachments-count>
|
4
|
+
<author-id type="integer">5654019</author-id>
|
5
|
+
<body><div>Hello There<br /></div></body>
|
6
|
+
<commentable-id type="integer">62509330</commentable-id>
|
7
|
+
<commentable-type>TodoItem</commentable-type>
|
8
|
+
<created-at type="datetime">2010-07-23T23:13:39Z</created-at>
|
9
|
+
<emailed-from nil="true"></emailed-from>
|
10
|
+
<id type="integer">74197051</id>
|
11
|
+
<author-name>Kia Kroas</author-name>
|
12
|
+
<attachments type="array"/>
|
13
|
+
</comment>
|
14
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
{"comment":{"attachments_count":0,"author_id":5654019,"body":"<div>Something's off.<br /></div>","commentable_id":62509330,"commentable_type":"TodoItem","created_at":"2010-07-23 23:14:24 UTC","emailed_from":null,"id":74197096,"author_name":"Kia Kroas","attachments":[]}}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<comment>
|
3
|
+
<attachments-count type="integer">0</attachments-count>
|
4
|
+
<author-id type="integer">5654019</author-id>
|
5
|
+
<body><div>Something's off.<br /></div></body>
|
6
|
+
<commentable-id type="integer">62509330</commentable-id>
|
7
|
+
<commentable-type>TodoItem</commentable-type>
|
8
|
+
<created-at type="datetime">2010-07-23T23:14:24Z</created-at>
|
9
|
+
<emailed-from nil="true"></emailed-from>
|
10
|
+
<id type="integer">74197096</id>
|
11
|
+
<author-name>Kia Kroas</author-name>
|
12
|
+
<attachments type="array"/>
|
13
|
+
</comment>
|
14
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
{"comments":[{"attachments_count":0,"author_id":5654019,"body":"<div>Hello There<br /></div>","commentable_id":62509330,"commentable_type":"TodoItem","created_at":"2010-07-23 23:13:39 UTC","emailed_from":null,"id":74197051,"author_name":"Kia Kroas"},{"attachments_count":0,"author_id":5654019,"body":"<div>Hm, why is the title different?<br /></div>","commentable_id":62509330,"commentable_type":"TodoItem","created_at":"2010-07-23 23:14:06 UTC","emailed_from":null,"id":74197080,"author_name":"Kia Kroas"},{"attachments_count":0,"author_id":5654019,"body":"<div>This doesn't seem right.<br /></div>","commentable_id":62509330,"commentable_type":"TodoItem","created_at":"2010-07-23 23:14:16 UTC","emailed_from":null,"id":74197085,"author_name":"Kia Kroas"},{"attachments_count":0,"author_id":5654019,"body":"<div>Something's off.<br /></div>","commentable_id":62509330,"commentable_type":"TodoItem","created_at":"2010-07-23 23:14:24 UTC","emailed_from":null,"id":74197096,"author_name":"Kia Kroas"}]}
|
@@ -0,0 +1,47 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<comments type="array" count="4">
|
3
|
+
<comment>
|
4
|
+
<attachments-count type="integer">0</attachments-count>
|
5
|
+
<author-id type="integer">5654019</author-id>
|
6
|
+
<body><div>Hello There<br /></div></body>
|
7
|
+
<commentable-id type="integer">62509330</commentable-id>
|
8
|
+
<commentable-type>TodoItem</commentable-type>
|
9
|
+
<created-at type="datetime">2010-07-23T23:13:39Z</created-at>
|
10
|
+
<emailed-from nil="true"></emailed-from>
|
11
|
+
<id type="integer">74197051</id>
|
12
|
+
<author-name>Kia Kroas</author-name>
|
13
|
+
</comment>
|
14
|
+
<comment>
|
15
|
+
<attachments-count type="integer">0</attachments-count>
|
16
|
+
<author-id type="integer">5654019</author-id>
|
17
|
+
<body><div>Hm, why is the title different?<br /></div></body>
|
18
|
+
<commentable-id type="integer">62509330</commentable-id>
|
19
|
+
<commentable-type>TodoItem</commentable-type>
|
20
|
+
<created-at type="datetime">2010-07-23T23:14:06Z</created-at>
|
21
|
+
<emailed-from nil="true"></emailed-from>
|
22
|
+
<id type="integer">74197080</id>
|
23
|
+
<author-name>Kia Kroas</author-name>
|
24
|
+
</comment>
|
25
|
+
<comment>
|
26
|
+
<attachments-count type="integer">0</attachments-count>
|
27
|
+
<author-id type="integer">5654019</author-id>
|
28
|
+
<body><div>This doesn't seem right.<br /></div></body>
|
29
|
+
<commentable-id type="integer">62509330</commentable-id>
|
30
|
+
<commentable-type>TodoItem</commentable-type>
|
31
|
+
<created-at type="datetime">2010-07-23T23:14:16Z</created-at>
|
32
|
+
<emailed-from nil="true"></emailed-from>
|
33
|
+
<id type="integer">74197085</id>
|
34
|
+
<author-name>Kia Kroas</author-name>
|
35
|
+
</comment>
|
36
|
+
<comment>
|
37
|
+
<attachments-count type="integer">0</attachments-count>
|
38
|
+
<author-id type="integer">5654019</author-id>
|
39
|
+
<body><div>Something's off.<br /></div></body>
|
40
|
+
<commentable-id type="integer">62509330</commentable-id>
|
41
|
+
<commentable-type>TodoItem</commentable-type>
|
42
|
+
<created-at type="datetime">2010-07-23T23:14:24Z</created-at>
|
43
|
+
<emailed-from nil="true"></emailed-from>
|
44
|
+
<id type="integer">74197096</id>
|
45
|
+
<author-name>Kia Kroas</author-name>
|
46
|
+
</comment>
|
47
|
+
</comments>
|
@@ -0,0 +1 @@
|
|
1
|
+
{"count":{"active":5,"on_hold":2,"archived":11}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"project":{"announcement":"Announcement.","created_on":"2010-07-20","id":5220065,"last_changed_on":"2010-07-23 06:31:39 UTC","name":"Ticketmaster-basecamp","show_announcement":false,"show_writeboards":true,"start_page":"log","status":"active","company":{"id":1971191,"name":"Kia Kroas"}}}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<project>
|
3
|
+
<announcement>Announcement.</announcement>
|
4
|
+
<created-on type="date">2010-07-20</created-on>
|
5
|
+
<id type="integer">5220065</id>
|
6
|
+
<last-changed-on type="datetime">2010-07-23T06:31:39Z</last-changed-on>
|
7
|
+
<name>Ticketmaster-basecamp</name>
|
8
|
+
<show-announcement type="boolean">false</show-announcement>
|
9
|
+
<show-writeboards type="boolean">true</show-writeboards>
|
10
|
+
<start-page>log</start-page>
|
11
|
+
<status>active</status>
|
12
|
+
<company>
|
13
|
+
<id type="integer">1971191</id>
|
14
|
+
<name>Kia Kroas</name>
|
15
|
+
</company>
|
16
|
+
</project>
|
@@ -0,0 +1 @@
|
|
1
|
+
{}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"projects":[{"announcement":"Announcement.","created_on":"2010-07-20","id":5220065,"last_changed_on":"2010-07-23 06:31:39 UTC","name":"Ticketmaster-basecamp","show_announcement":false,"show_writeboards":true,"start_page":"log","status":"active","company":{"id":1971191,"name":"Kia Kroas"}}]}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<projects type="array">
|
3
|
+
<project>
|
4
|
+
<announcement>Announcement.</announcement>
|
5
|
+
<created-on type="date">2010-07-20</created-on>
|
6
|
+
<id type="integer">5220065</id>
|
7
|
+
<last-changed-on type="datetime">2010-07-23T06:31:39Z</last-changed-on>
|
8
|
+
<name>Ticketmaster-basecamp</name>
|
9
|
+
<show-announcement type="boolean">false</show-announcement>
|
10
|
+
<show-writeboards type="boolean">true</show-writeboards>
|
11
|
+
<start-page>log</start-page>
|
12
|
+
<status>active</status>
|
13
|
+
<company>
|
14
|
+
<id type="integer">1971191</id>
|
15
|
+
<name>Kia Kroas</name>
|
16
|
+
</company>
|
17
|
+
</project>
|
18
|
+
</projects>
|
19
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<todo-item>
|
3
|
+
<comments-count type="integer">0</comments-count>
|
4
|
+
<completed type="boolean">false</completed>
|
5
|
+
<content>hudnthdau</content>
|
6
|
+
<created-at type="datetime">2010-07-21T01:14:34Z</created-at>
|
7
|
+
<updated-at type="datetime">2010-07-20T23:36:49Z</updated-at>
|
8
|
+
<creator-id type="integer">5654019</creator-id>
|
9
|
+
<due-at type="datetime" nil="true"></due-at>
|
10
|
+
<id type="integer">62509330</id>
|
11
|
+
<position type="integer">1</position>
|
12
|
+
<todo-list-id type="integer">9973518</todo-list-id>
|
13
|
+
<created-on type="datetime" deprecated="true">2010-07-21T01:14:34Z</created-on>
|
14
|
+
<creator-name>Kia Kroas</creator-name>
|
15
|
+
</todo-item>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<todo-list>
|
3
|
+
<completed-count type="integer">0</completed-count>
|
4
|
+
<description>etauhnotehunoteh tnheontu honetuh osneh noe hosneuh toneuh</description>
|
5
|
+
<id type="integer">9972756</id>
|
6
|
+
<milestone-id type="integer" nil="true"></milestone-id>
|
7
|
+
<name>Cheese</name>
|
8
|
+
<position type="integer">2</position>
|
9
|
+
<private type="boolean">false</private>
|
10
|
+
<project-id type="integer">5220065</project-id>
|
11
|
+
<tracked type="boolean">false</tracked>
|
12
|
+
<uncompleted-count type="integer">6</uncompleted-count>
|
13
|
+
<complete>false</complete>
|
14
|
+
</todo-list>
|