tracker_api 0.2.12 → 1.0.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.
- 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
|