tracker_api 0.2.12 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +1 -1
- data/lib/tracker_api.rb +5 -3
- data/lib/tracker_api/client.rb +12 -2
- data/lib/tracker_api/endpoints/epic.rb +8 -0
- data/lib/tracker_api/endpoints/story.rb +2 -0
- data/lib/tracker_api/resources/account.rb +1 -1
- data/lib/tracker_api/resources/activity.rb +2 -2
- data/lib/tracker_api/resources/change.rb +1 -1
- data/lib/tracker_api/resources/comment.rb +4 -4
- data/lib/tracker_api/resources/epic.rb +5 -5
- data/lib/tracker_api/resources/iteration.rb +2 -2
- data/lib/tracker_api/resources/label.rb +1 -1
- data/lib/tracker_api/resources/me.rb +4 -4
- data/lib/tracker_api/resources/membership_summary.rb +1 -1
- data/lib/tracker_api/resources/notification.rb +1 -1
- data/lib/tracker_api/resources/person.rb +1 -1
- data/lib/tracker_api/resources/primary_resource.rb +1 -1
- data/lib/tracker_api/resources/project.rb +11 -10
- data/lib/tracker_api/resources/project_membership.rb +1 -1
- data/lib/tracker_api/resources/shared/base.rb +30 -0
- data/lib/tracker_api/resources/shared/collection.rb +17 -0
- data/lib/tracker_api/resources/story.rb +31 -17
- data/lib/tracker_api/resources/task.rb +1 -1
- data/lib/tracker_api/version.rb +1 -1
- data/lib/virtus/attribute/nullify_blank.rb +27 -0
- data/lib/virtus/dirty_attribute.rb +104 -0
- data/lib/virtus/dirty_attribute/session.rb +54 -0
- data/test/client_test.rb +16 -1
- data/test/minitest_helper.rb +1 -0
- data/test/story_test.rb +10 -3
- data/test/vcr/cassettes/client_done_iterations_with_pagination.json +1 -1
- data/test/vcr/cassettes/client_get_all_stories_with_pagination.json +1 -1
- data/test/vcr/cassettes/client_get_limited_stories_with_no_pagination.json +1 -1
- data/test/vcr/cassettes/client_get_single_epic_by_epic_id.json +1 -0
- data/test/vcr/cassettes/client_get_single_story_by_story_id.json +1 -1
- data/test/vcr/cassettes/create_story.json +1 -1
- data/test/vcr/cassettes/create_story_with_lengthy_params.json +1 -1
- data/test/vcr/cassettes/create_task.json +1 -1
- data/test/vcr/cassettes/get_all_projects.json +1 -1
- data/test/vcr/cassettes/get_another_story.json +1 -1
- data/test/vcr/cassettes/get_current_iteration.json +1 -1
- data/test/vcr/cassettes/get_done_iterations.json +1 -1
- data/test/vcr/cassettes/get_epics.json +1 -1
- data/test/vcr/cassettes/get_iteration_by_number.json +1 -1
- data/test/vcr/cassettes/get_labels.json +1 -1
- data/test/vcr/cassettes/get_me.json +1 -1
- data/test/vcr/cassettes/get_my_activities.json +1 -1
- data/test/vcr/cassettes/get_owners_for_story.json +1 -1
- data/test/vcr/cassettes/get_project.json +1 -1
- data/test/vcr/cassettes/get_project_activity.json +1 -1
- data/test/vcr/cassettes/get_project_with_epics.json +1 -1
- data/test/vcr/cassettes/get_project_with_labels.json +1 -1
- data/test/vcr/cassettes/get_story.json +1 -1
- data/test/vcr/cassettes/get_story_activity.json +1 -1
- data/test/vcr/cassettes/get_story_comments.json +1 -1
- data/test/vcr/cassettes/get_story_owners.json +1 -1
- data/test/vcr/cassettes/get_story_with_tasks.json +1 -1
- data/test/vcr/cassettes/get_tasks.json +1 -1
- data/test/vcr/cassettes/get_tasks_for_story.json +1 -1
- data/test/vcr/cassettes/get_tasks_when_stories_filtered.json +1 -1
- data/test/vcr/cassettes/get_unscheduled_stories.json +1 -1
- data/test/vcr/cassettes/get_unscheduled_story.json +1 -1
- data/test/vcr/cassettes/save_story.json +1 -1
- data/test/vcr/cassettes/save_story_with_multiple_changes.json +1 -1
- data/test/vcr/cassettes/save_story_with_new_label.json +1 -1
- data/test/vcr/cassettes/update_story_to_create_activity.json +1 -1
- data/tracker_api.gemspec +2 -0
- metadata +23 -5
- data/lib/tracker_api/resources/shared/has_id.rb +0 -18
- data/test/vcr/cassettes/get_story_with_owners.json +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3fbc8caee5a56cdf59e58fc545d0390f76685dc2
|
4
|
+
data.tar.gz: cae843ef9bdc193e763d440db310a79e9fb7fe4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81a23229a778910df741e89fea770bec3096cadeb85c40dc9f79b587fc8fa1e6617c4e853f7f0722d6eb6037162276d49a6f6132e0501a8dfd0fdd1aa6db2e58
|
7
|
+
data.tar.gz: 5be684a973dd96a30c032fd50179790505bab01ba8be8a61d0fb7b9a9bd30ec8a25bb697b8836764f116e7c0070f130d21d69f548e7e80c67ea171c19e4da36c
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -53,7 +53,7 @@ story.activity # Get
|
|
53
53
|
|
54
54
|
story.name = 'Save the Ewoks' # Update a single story attribute
|
55
55
|
story.attributes = { name: 'Save the Ewoks', description: '...' } # Update multiple story attributes
|
56
|
-
story.
|
56
|
+
story.add_label('Endor') # Add a new label to an existing story
|
57
57
|
story.save # Save changes made to a story
|
58
58
|
|
59
59
|
story = TrackerApi::Resources::Story.new( client: client,
|
data/lib/tracker_api.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
require 'tracker_api/version'
|
2
2
|
|
3
3
|
# dependencies
|
4
|
-
require 'virtus'
|
5
4
|
require 'faraday'
|
6
5
|
require 'faraday_middleware'
|
6
|
+
|
7
7
|
if defined?(ActiveSupport)
|
8
8
|
require 'active_support/core_ext/object/blank'
|
9
9
|
else
|
10
10
|
require 'core_ext/object/blank'
|
11
11
|
end
|
12
12
|
require 'equalizer'
|
13
|
-
|
13
|
+
|
14
14
|
require 'multi_json'
|
15
|
+
require 'representable/json'
|
15
16
|
|
16
17
|
# stdlib
|
17
18
|
require 'addressable/uri'
|
@@ -51,7 +52,8 @@ module TrackerApi
|
|
51
52
|
|
52
53
|
module Resources
|
53
54
|
module Shared
|
54
|
-
autoload :
|
55
|
+
autoload :Base, 'tracker_api/resources/shared/base'
|
56
|
+
autoload :Collection, 'tracker_api/resources/shared/collection'
|
55
57
|
end
|
56
58
|
autoload :Activity, 'tracker_api/resources/activity'
|
57
59
|
autoload :Account, 'tracker_api/resources/account'
|
data/lib/tracker_api/client.rb
CHANGED
@@ -138,9 +138,19 @@ module TrackerApi
|
|
138
138
|
# Get information about a client story without knowing what project the story belongs to
|
139
139
|
#
|
140
140
|
# @param [String] story_id
|
141
|
+
# @param [Hash] params
|
141
142
|
# @return [TrackerApi::Resources::Story]
|
142
|
-
def story(story_id)
|
143
|
-
Endpoints::Story.new(self).get_story(story_id)
|
143
|
+
def story(story_id, params={})
|
144
|
+
Endpoints::Story.new(self).get_story(story_id, params)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Get information about an epic without knowing what project the epic belongs to
|
148
|
+
#
|
149
|
+
# @param [String] epic_id
|
150
|
+
# @param [Hash] params
|
151
|
+
# @return [TrackerApi::Resources::Epic]
|
152
|
+
def epic(epic_id, params={})
|
153
|
+
Endpoints::Epic.new(self).get_epic(epic_id, params)
|
144
154
|
end
|
145
155
|
|
146
156
|
# Get notifications for the authenticated person
|
@@ -13,6 +13,12 @@ module TrackerApi
|
|
13
13
|
Resources::Epic.new({ client: client, project_id: project_id }.merge(data))
|
14
14
|
end
|
15
15
|
|
16
|
+
def get_epic(epic_id, params={})
|
17
|
+
data = client.get("/epics/#{epic_id}", params: params).body
|
18
|
+
|
19
|
+
Resources::Epic.new({ client: client }.merge(data))
|
20
|
+
end
|
21
|
+
|
16
22
|
def create(project_id, params={})
|
17
23
|
data = client.post("/projects/#{project_id}/epics", params: params).body
|
18
24
|
|
@@ -25,6 +31,8 @@ module TrackerApi
|
|
25
31
|
data = client.put("/projects/#{epic.project_id}/epics/#{epic.id}", params: params).body
|
26
32
|
|
27
33
|
epic.attributes = data
|
34
|
+
epic.clean!
|
35
|
+
epic
|
28
36
|
end
|
29
37
|
end
|
30
38
|
end
|
@@ -11,8 +11,8 @@ module TrackerApi
|
|
11
11
|
attribute :project_version, Integer
|
12
12
|
attribute :message, String
|
13
13
|
attribute :highlight, String
|
14
|
-
attribute :changes,
|
15
|
-
attribute :primary_resources,
|
14
|
+
attribute :changes, Shared::Collection[Change]
|
15
|
+
attribute :primary_resources, Shared::Collection[PrimaryResource]
|
16
16
|
attribute :project, Project
|
17
17
|
attribute :performed_by, Person
|
18
18
|
attribute :occurred_at, DateTime
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module TrackerApi
|
2
2
|
module Resources
|
3
3
|
class Comment
|
4
|
-
include Shared::
|
4
|
+
include Shared::Base
|
5
5
|
|
6
6
|
attribute :story_id, Integer
|
7
7
|
attribute :epic_id, Integer
|
@@ -9,11 +9,11 @@ module TrackerApi
|
|
9
9
|
attribute :person_id, Integer
|
10
10
|
attribute :created_at, DateTime
|
11
11
|
attribute :updated_at, DateTime
|
12
|
-
attribute :file_attachment_ids,
|
13
|
-
attribute :google_attachment_ids,
|
12
|
+
attribute :file_attachment_ids, Shared::Collection[Integer]
|
13
|
+
attribute :google_attachment_ids, Shared::Collection[Integer]
|
14
14
|
attribute :commit_identifier, String
|
15
15
|
attribute :commit_type, String
|
16
16
|
attribute :kind, String
|
17
17
|
end
|
18
18
|
end
|
19
|
-
end
|
19
|
+
end
|
@@ -1,16 +1,16 @@
|
|
1
1
|
module TrackerApi
|
2
2
|
module Resources
|
3
3
|
class Epic
|
4
|
-
include Shared::
|
4
|
+
include Shared::Base
|
5
5
|
|
6
6
|
attribute :client
|
7
7
|
|
8
|
-
attribute :comment_ids,
|
9
|
-
attribute :comments,
|
8
|
+
attribute :comment_ids, Shared::Collection[Integer]
|
9
|
+
attribute :comments, Shared::Collection[Comment]
|
10
10
|
attribute :created_at, DateTime
|
11
11
|
attribute :description, String
|
12
|
-
attribute :follower_ids,
|
13
|
-
attribute :followers,
|
12
|
+
attribute :follower_ids, Shared::Collection[Integer]
|
13
|
+
attribute :followers, Shared::Collection[Person]
|
14
14
|
attribute :kind, String
|
15
15
|
attribute :label, Label
|
16
16
|
attribute :label_id, Integer
|
@@ -13,8 +13,8 @@ module TrackerApi
|
|
13
13
|
attribute :planned, Boolean
|
14
14
|
attribute :project_id, Integer
|
15
15
|
attribute :start, DateTime
|
16
|
-
attribute :stories, [Story]
|
17
|
-
attribute :story_ids, [Integer]
|
16
|
+
attribute :stories, Shared::Collection[Story]
|
17
|
+
attribute :story_ids, Shared::Collection[Integer]
|
18
18
|
attribute :team_strength, Float
|
19
19
|
|
20
20
|
def stories=(data)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module TrackerApi
|
2
2
|
module Resources
|
3
3
|
class Me
|
4
|
-
include Shared::
|
4
|
+
include Shared::Base
|
5
5
|
|
6
6
|
attribute :name, String
|
7
7
|
attribute :initials, String
|
@@ -9,9 +9,9 @@ module TrackerApi
|
|
9
9
|
attribute :time_zone, TimeZone
|
10
10
|
attribute :api_token, String
|
11
11
|
attribute :has_google_identity, Boolean
|
12
|
-
attribute :project_ids,
|
13
|
-
attribute :projects, [MembershipSummary]
|
14
|
-
attribute :workspace_ids,
|
12
|
+
attribute :project_ids, Shared::Collection[Integer]
|
13
|
+
attribute :projects, Shared::Collection[MembershipSummary]
|
14
|
+
attribute :workspace_ids, Shared::Collection[Integer]
|
15
15
|
attribute :email, String
|
16
16
|
attribute :receives_in_app_notifications, Boolean
|
17
17
|
attribute :kind, String
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module TrackerApi
|
2
2
|
module Resources
|
3
3
|
class Project
|
4
|
-
include Shared::
|
4
|
+
include Shared::Base
|
5
5
|
|
6
6
|
attribute :client
|
7
7
|
|
@@ -17,14 +17,14 @@ module TrackerApi
|
|
17
17
|
attribute :enable_incoming_emails, Boolean
|
18
18
|
attribute :enable_planned_mode, Boolean
|
19
19
|
attribute :enable_tasks, Boolean
|
20
|
-
attribute :epic_ids,
|
21
|
-
attribute :epics,
|
20
|
+
attribute :epic_ids, Shared::Collection[Integer]
|
21
|
+
attribute :epics, Shared::Collection[Epic]
|
22
22
|
attribute :has_google_domain, Boolean
|
23
23
|
attribute :initial_velocity, Integer
|
24
24
|
attribute :iteration_length, Integer
|
25
25
|
attribute :kind, String
|
26
|
-
attribute :label_ids,
|
27
|
-
attribute :labels,
|
26
|
+
attribute :label_ids, Shared::Collection[Integer]
|
27
|
+
attribute :labels, Shared::Collection[Label]
|
28
28
|
attribute :name, String
|
29
29
|
attribute :number_of_done_iterations_to_show, Integer
|
30
30
|
attribute :point_scale, String
|
@@ -54,7 +54,7 @@ module TrackerApi
|
|
54
54
|
# @param [Hash] params
|
55
55
|
# @return [Array[Label]] labels of this project
|
56
56
|
def labels(params = {})
|
57
|
-
if @labels && @labels.
|
57
|
+
if @labels && @labels.present?
|
58
58
|
@labels
|
59
59
|
else
|
60
60
|
@labels = Endpoints::Labels.new(client).get(id, params)
|
@@ -66,10 +66,11 @@ module TrackerApi
|
|
66
66
|
# @param [Hash] params
|
67
67
|
# @return [Array[Epic]] epics associated with this project
|
68
68
|
def epics(params={})
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
69
|
+
if @epics && @epics.present?
|
70
|
+
@epics
|
71
|
+
else
|
72
|
+
@epics = Endpoints::Epics.new(client).get(id, params)
|
73
|
+
end
|
73
74
|
end
|
74
75
|
|
75
76
|
# Provides a list of all the iterations in the project.
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'virtus'
|
2
|
+
if Virtus::Attribute::NullifyBlank.method_defined?(:coerce)
|
3
|
+
require 'virtus/attribute/nullify_blank'
|
4
|
+
else
|
5
|
+
raise """
|
6
|
+
WARNING: The above monkey patch can't be applied as expected.
|
7
|
+
See discussion here: https://github.com/dashofcode/tracker_api/commit/27599e7e2169776c32bbff8c972a31b930452879
|
8
|
+
"""
|
9
|
+
end
|
10
|
+
require 'virtus/dirty_attribute'
|
11
|
+
|
12
|
+
module TrackerApi
|
13
|
+
module Resources
|
14
|
+
module Shared
|
15
|
+
module Base
|
16
|
+
def self.included(base)
|
17
|
+
base.class_eval do
|
18
|
+
include Virtus.model(nullify_blank: true)
|
19
|
+
include Virtus::DirtyAttribute
|
20
|
+
include Virtus::DirtyAttribute::InitiallyClean
|
21
|
+
|
22
|
+
include Equalizer.new(:id)
|
23
|
+
|
24
|
+
attribute :id, Integer
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module TrackerApi
|
2
|
+
module Resources
|
3
|
+
module Shared
|
4
|
+
class Collection < Array
|
5
|
+
def <<(item)
|
6
|
+
warn """
|
7
|
+
WARNING: Direct mutation of an attribute value skips coercion
|
8
|
+
and dirty tracking. Please use direct assignment or the
|
9
|
+
specialized add_* methods to get expected behavior.
|
10
|
+
https://github.com/solnic/virtus#important-note-about-member-coercions
|
11
|
+
"""
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,37 +1,37 @@
|
|
1
1
|
module TrackerApi
|
2
2
|
module Resources
|
3
3
|
class Story
|
4
|
-
include Shared::
|
4
|
+
include Shared::Base
|
5
5
|
|
6
6
|
attribute :client
|
7
7
|
|
8
8
|
attribute :accepted_at, DateTime
|
9
|
-
attribute :comment_ids,
|
10
|
-
attribute :comments,
|
9
|
+
attribute :comment_ids, Shared::Collection[Integer]
|
10
|
+
attribute :comments, Shared::Collection[Comment]
|
11
11
|
attribute :created_at, DateTime
|
12
12
|
attribute :current_state, String # (accepted, delivered, finished, started, rejected, planned, unstarted, unscheduled)
|
13
13
|
attribute :deadline, DateTime
|
14
14
|
attribute :description, String
|
15
15
|
attribute :estimate, Float
|
16
16
|
attribute :external_id, String
|
17
|
-
attribute :follower_ids,
|
18
|
-
attribute :followers,
|
17
|
+
attribute :follower_ids, Shared::Collection[Integer]
|
18
|
+
attribute :followers, Shared::Collection[Person]
|
19
19
|
attribute :integration_id, Integer
|
20
20
|
attribute :kind, String
|
21
|
-
attribute :label_ids,
|
22
|
-
attribute :labels,
|
21
|
+
attribute :label_ids, Shared::Collection[Integer]
|
22
|
+
attribute :labels, Shared::Collection[Label]
|
23
23
|
attribute :name, String
|
24
24
|
attribute :owned_by_id, Integer # deprecated!
|
25
25
|
attribute :owned_by, Person
|
26
|
-
attribute :owner_ids,
|
27
|
-
attribute :owners,
|
26
|
+
attribute :owner_ids, Shared::Collection[Integer]
|
27
|
+
attribute :owners, Shared::Collection[Person]
|
28
28
|
attribute :planned_iteration_number, Integer
|
29
29
|
attribute :project_id, Integer
|
30
30
|
attribute :requested_by, Person
|
31
31
|
attribute :requested_by_id, Integer
|
32
32
|
attribute :story_type, String # (feature, bug, chore, release)
|
33
|
-
attribute :task_ids,
|
34
|
-
attribute :tasks,
|
33
|
+
attribute :task_ids, Shared::Collection[Integer]
|
34
|
+
attribute :tasks, Shared::Collection[Task]
|
35
35
|
attribute :updated_at, DateTime
|
36
36
|
attribute :url, String
|
37
37
|
|
@@ -39,7 +39,7 @@ module TrackerApi
|
|
39
39
|
class UpdateRepresenter < Representable::Decorator
|
40
40
|
include Representable::JSON
|
41
41
|
|
42
|
-
property :follower_ids
|
42
|
+
property :follower_ids, if: ->(options) { !options[:input].blank? }
|
43
43
|
property :name
|
44
44
|
property :description
|
45
45
|
property :story_type
|
@@ -48,7 +48,7 @@ module TrackerApi
|
|
48
48
|
property :accepted_at
|
49
49
|
property :deadline
|
50
50
|
property :requested_by_id
|
51
|
-
property :owner_ids
|
51
|
+
property :owner_ids, if: ->(options) { !options[:input].blank? }
|
52
52
|
collection :labels, class: Label, decorator: Label::UpdateRepresenter, render_empty: true
|
53
53
|
property :integration_id
|
54
54
|
property :external_id
|
@@ -59,6 +59,20 @@ module TrackerApi
|
|
59
59
|
@label_list ||= labels.collect(&:name).join(',')
|
60
60
|
end
|
61
61
|
|
62
|
+
# Adds a new label to the story.
|
63
|
+
#
|
64
|
+
# @param [Label|Hash|String] label
|
65
|
+
def add_label(label)
|
66
|
+
new_label = if label.kind_of?(String)
|
67
|
+
Label.new(name: label)
|
68
|
+
else
|
69
|
+
label
|
70
|
+
end
|
71
|
+
|
72
|
+
# Use attribute writer to get coercion and dirty tracking.
|
73
|
+
self.labels = @labels.dup.push(new_label)
|
74
|
+
end
|
75
|
+
|
62
76
|
# Provides a list of all the activity performed on the story.
|
63
77
|
#
|
64
78
|
# @param [Hash] params
|
@@ -72,7 +86,7 @@ module TrackerApi
|
|
72
86
|
# @param [Hash] params
|
73
87
|
# @return [Array[Comment]]
|
74
88
|
def comments(params = {})
|
75
|
-
if params.blank? && @comments.
|
89
|
+
if params.blank? && @comments.present?
|
76
90
|
@comments
|
77
91
|
else
|
78
92
|
@comments = Endpoints::Comments.new(client).get(project_id, id, params)
|
@@ -84,7 +98,7 @@ module TrackerApi
|
|
84
98
|
# @param [Hash] params
|
85
99
|
# @return [Array[Task]]
|
86
100
|
def tasks(params = {})
|
87
|
-
if params.blank? && @tasks.
|
101
|
+
if params.blank? && @tasks.present?
|
88
102
|
@tasks
|
89
103
|
else
|
90
104
|
@tasks = Endpoints::Tasks.new(client).get(project_id, id, params)
|
@@ -96,7 +110,7 @@ module TrackerApi
|
|
96
110
|
# @param [Hash] params
|
97
111
|
# @return [Array[Person]]
|
98
112
|
def owners(params = {})
|
99
|
-
if params.blank? && @owners.
|
113
|
+
if params.blank? && @owners.present?
|
100
114
|
@owners
|
101
115
|
else
|
102
116
|
@owners = Endpoints::StoryOwners.new(client).get(project_id, id, params)
|
@@ -113,7 +127,7 @@ module TrackerApi
|
|
113
127
|
def save
|
114
128
|
raise ArgumentError, 'Can not update a story with an unknown project_id.' if project_id.nil?
|
115
129
|
|
116
|
-
Endpoints::Story.new(client).update(self, UpdateRepresenter.new(self))
|
130
|
+
Endpoints::Story.new(client).update(self, UpdateRepresenter.new(Story.new(self.dirty_attributes)))
|
117
131
|
end
|
118
132
|
end
|
119
133
|
end
|