bloomy 0.3.0 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 787640980ef91fe249c30313f21be2230cc0671de398f714f38e1200fc104a6f
4
- data.tar.gz: 6c2bb8a0b8e78371674fe5f18bc66ab44d91629d03484863442f4d3953c59707
3
+ metadata.gz: 5967a74a2cb5758a74e4877ab46a57eeba59f85a023039c1252d47087007bfd7
4
+ data.tar.gz: 6ded65188a434b4a3fa47cb9007b5c1e10e97b88266c6442e4e74684b7f7f552
5
5
  SHA512:
6
- metadata.gz: da4639a0e6e6e633f972d31df14818ed64e3b690f565c7308f49ae53a08c061b74d944f4d7088f8ab024ed54b4301d4186a9747802c34b24c2b7f476afdab77a
7
- data.tar.gz: 6f4674b867eec7d42f5735c1c7a6725ff173ee2c8f7a1c8b22ef329ed8aa9f384e40632235a578e4d1efe654bccdda75255abbc9ab35313c11375d1815944dcb
6
+ metadata.gz: d5eaeb394ba3edbd99e433ab9760f510a9a0e219c5b0de8cf2fe3ef0cac7a03a12fbf3325515e3485629186d600724e7e8001d32070baf400a23b9453fd64476
7
+ data.tar.gz: 9298429c7361153eb4f58e35604defb752362add6f43bb253413c21abe11e2ae4f6d4997c03df337e2f12dcc8097685333ab68c7f0b12656b8f3594804f773fa
data/.rubocop.yml CHANGED
@@ -1,30 +1,10 @@
1
- AllCops:
2
- NewCops: enable
3
- SuggestExtensions: false
4
-
5
- Gemspec/RequiredRubyVersion:
6
- Enabled: false
7
-
8
- Metrics/AbcSize:
9
- Enabled: false
10
-
11
- Metrics/BlockLength:
12
- Enabled: false
13
-
14
- Metrics/CyclomaticComplexity:
15
- Enabled: false
16
-
17
- Metrics/MethodLength:
18
- Enabled: false
19
-
20
- Metrics/PerceivedComplexity:
21
- Enabled: false
22
-
23
- Naming/AccessorMethodName:
24
- Enabled: false
25
-
26
- Gemspec/DevelopmentDependencies:
27
- Enabled: false
28
-
29
- Style/StringLiterals:
30
- EnforcedStyle: double_quotes
1
+ require:
2
+ - standard
3
+ - standard-custom
4
+ - standard-performance
5
+ - rubocop-performance
6
+
7
+ inherit_gem:
8
+ standard: config/base.yml
9
+ standard-custom: config/base.yml
10
+ standard-performance: config/base.yml
data/lib/bloomy/client.rb CHANGED
@@ -25,6 +25,9 @@ module Bloomy
25
25
  def initialize(api_key = nil)
26
26
  @configuration = Configuration.new unless api_key
27
27
  @api_key = api_key || @configuration.api_key
28
+
29
+ raise ArgumentError, "No API key provided. Set it in configuration or pass it directly." unless @api_key
30
+
28
31
  @base_url = "https://app.bloomgrowth.com/api/v1"
29
32
  @conn = Faraday.new(url: @base_url) do |faraday|
30
33
  faraday.response :json
@@ -34,13 +37,12 @@ module Bloomy
34
37
  faraday.headers["Authorization"] = "Bearer #{@api_key}"
35
38
  end
36
39
  @user = User.new(@conn)
37
- @user_id = @user.default_user_id
38
- @todo = Todo.new(@conn, @user_id)
39
- @goal = Goal.new(@conn, @user_id)
40
- @meeting = Meeting.new(@conn, @user_id)
41
- @scorecard = Scorecard.new(@conn, @user_id)
42
- @issue = Issue.new(@conn, @user_id)
43
- @headline = Headline.new(@conn, @user_id)
40
+ @todo = Todo.new(@conn)
41
+ @goal = Goal.new(@conn)
42
+ @meeting = Meeting.new(@conn)
43
+ @scorecard = Scorecard.new(@conn)
44
+ @issue = Issue.new(@conn)
45
+ @headline = Headline.new(@conn)
44
46
  end
45
47
  end
46
48
  end
@@ -1,14 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bloomy/utils/get_user_id"
4
+
3
5
  # Class to handle all the operations related to goals
4
6
  class Goal
7
+ include Bloomy::Utilities::UserIdUtility
5
8
  # Initializes a new Goal instance
6
9
  #
7
10
  # @param conn [Object] the connection object to interact with the API
8
- # @param user_id [Integer] the ID of the user
9
- def initialize(conn, user_id)
11
+ def initialize(conn)
10
12
  @conn = conn
11
- @user_id = user_id
12
13
  end
13
14
 
14
15
  # Lists all goals for a specific user
@@ -19,7 +20,7 @@ class Goal
19
20
  # @example
20
21
  # client.goal.list
21
22
  # #=> [{ id: 1, title: "Complete project", created_at: "2024-06-10", ... }, ...]
22
- def list(user_id: @user_id, archived: false)
23
+ def list(user_id = self.user_id, archived: false)
23
24
  active_goals = @conn.get("rocks/user/#{user_id}?include_origin=true").body.map do |goal|
24
25
  {
25
26
  id: goal["Id"],
@@ -28,11 +29,11 @@ class Goal
28
29
  due_date: goal["DueDate"],
29
30
  status: goal["Complete"] ? "Completed" : "Incomplete",
30
31
  meeting_id: goal["Origins"].empty? ? nil : goal["Origins"][0]["Id"],
31
- meeting_name: goal["Origins"].empty? ? nil : goal["Origins"][0]["Name"]
32
+ meeting_title: goal["Origins"].empty? ? nil : goal["Origins"][0]["Name"]
32
33
  }
33
34
  end
34
35
 
35
- archived ? {active: active_goals, archived: get_archived_goals(user_id: @user_id)} : active_goals
36
+ archived ? {active: active_goals, archived: get_archived_goals(self.user_id)} : active_goals
36
37
  end
37
38
 
38
39
  # Creates a new goal
@@ -44,14 +45,14 @@ class Goal
44
45
  # @example
45
46
  # client.goal.create(title: "New Goal", meeting_id: 1)
46
47
  # #=> { goal_id: 1, title: "New Goal", meeting_id: 1, ... }
47
- def create(title:, meeting_id:, user_id: @user_id)
48
+ def create(title:, meeting_id:, user_id: self.user_id)
48
49
  payload = {title: title, accountableUserId: user_id}.to_json
49
50
  response = @conn.post("/api/v1/L10/#{meeting_id}/rocks", payload).body
50
51
  {
51
52
  goal_id: response["Id"],
52
53
  title: title,
53
54
  meeting_id: meeting_id,
54
- meeting_name: response["Origins"][0]["Name"],
55
+ meeting_title: response["Origins"][0]["Name"],
55
56
  user_id: user_id,
56
57
  user_name: response["Owner"]["Name"],
57
58
  created_at: DateTime.parse(response["CreateTime"])
@@ -67,7 +68,7 @@ class Goal
67
68
  # #=> { status: 200 }
68
69
  def delete(goal_id)
69
70
  response = @conn.delete("/api/v1/rocks/#{goal_id}")
70
- {status: response.status}
71
+ response.success?
71
72
  end
72
73
 
73
74
  # Updates a goal
@@ -79,10 +80,10 @@ class Goal
79
80
  # @example
80
81
  # client.goal.update(goal_id: 1, title: "Updated Goal")
81
82
  # #=> { status: 200 }
82
- def update(goal_id:, title:, accountable_user: @user_id)
83
+ def update(goal_id:, title:, accountable_user: user_id)
83
84
  payload = {title: title, accountableUserId: accountable_user}.to_json
84
85
  response = @conn.put("/api/v1/rocks/#{goal_id}", payload)
85
- {status: response.status}
86
+ response.success?
86
87
  end
87
88
 
88
89
  private
@@ -94,7 +95,7 @@ class Goal
94
95
  # @example
95
96
  # goal.send(:get_archived_goals)
96
97
  # #=> [{ id: 1, title: "Archived Goal", created_at: "2024-06-10", ... }, ...]
97
- def get_archived_goals(user_id: @user_id)
98
+ def get_archived_goals(user_id = self.user_id)
98
99
  response = @conn.get("archivedrocks/user/#{user_id}").body
99
100
  response.map do |goal|
100
101
  {
@@ -1,23 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bloomy/utils/get_user_id"
4
+
3
5
  class Headline
6
+ include Bloomy::Utilities::UserIdUtility
4
7
  # Initializes a new headline instance
5
8
  #
6
9
  # @param conn [Object] the connection object to interact with the API
7
- # @param user_id [Integer] the ID of the user
8
- def initialize(conn, user_id)
10
+ def initialize(conn)
9
11
  @conn = conn
10
- @user_id = user_id
11
12
  end
12
13
 
13
14
  # Creates a new headline
14
15
  #
15
16
  # @param meeting_id [Integer] the ID of the meeting
16
17
  # @param title [String] the title of the headline
17
- # @param owner_id [Integer] the ID of the owner
18
+ # @param owner_id [Integer] the ID of the headline owner
18
19
  # @param notes [String] additional notes for the headline
19
20
  # @return [Hash] the created headline details
20
- def create(meeting_id, title, owner_id: @user_id, notes: nil)
21
+ def create(meeting_id, title, owner_id: user_id, notes: nil)
21
22
  response = @conn.post("/api/v1/L10/#{meeting_id}/headlines",
22
23
  {title: title, ownerId: owner_id, notes: notes}.to_json)
23
24
  raise "Failed to create headline" unless response.status == 200
@@ -26,7 +27,7 @@ class Headline
26
27
  id: response.body["Id"],
27
28
  title: response.body["Title"],
28
29
  owner_id: response.body["OwnerId"],
29
- notes: response.body["Notes"]
30
+ notes_url: response.body["DetailsUrl"]
30
31
  }
31
32
  end
32
33
 
@@ -52,9 +53,10 @@ class Headline
52
53
  {
53
54
  id: response.body["Id"],
54
55
  title: response.body["Name"],
56
+ notes_url: response.body["DetailsUrl"],
55
57
  meeting_details: {
56
58
  id: response.body["OriginId"],
57
- name: response.body["Origin"]
59
+ title: response.body["Origin"]
58
60
  },
59
61
  owner_details: {
60
62
  id: response.body["Owner"]["Id"],
@@ -66,20 +68,35 @@ class Headline
66
68
  }
67
69
  end
68
70
 
69
- # Get user headlines
71
+ # Get headlines for a user or a meeting.
70
72
  #
71
- # @param user_id [Integer] the ID of the user
72
- # @return [Array] the list of headlines for the user
73
- def user_headlines(user_id: @user_id)
74
- response = @conn.get("/api/v1/headline/users/#{user_id}")
75
- raise "Failed to list headlines" unless response.status == 200
73
+ # @param user_id [Integer, nil] the ID of the user (defaults to initialized user_id)
74
+ # @param meeting_id [Integer, nil] the ID of the meeting
75
+ # @raise [ArgumentError] if both `user_id` and `meeting_id` are provided
76
+ # @return [Array<Hash>] the list of headlines
77
+ # @example
78
+ # # Fetch headlines for a user
79
+ # client.headline.list
80
+ # #=> [{ id: 1, title: "Headline Title", meeting_details: { id: 1, name: "Team Meeting" }, ... }, ...]
81
+ def list(user_id: nil, meeting_id: nil)
82
+ raise ArgumentError, "Please provide either `user_id` or `meeting_id`, not both." if user_id && meeting_id
83
+
84
+ if meeting_id
85
+ response = @conn.get("/api/v1/l10/#{meeting_id}/headlines")
86
+ else
87
+ user_id ||= self.user_id
88
+ response = @conn.get("/api/v1/headline/users/#{user_id}")
89
+ end
90
+
91
+ raise "Failed to list headlines" unless response.success?
92
+
76
93
  response.body.map do |headline|
77
94
  {
78
95
  id: headline["Id"],
79
96
  title: headline["Name"],
80
97
  meeting_details: {
81
98
  id: headline["OriginId"],
82
- name: headline["Origin"]
99
+ title: headline["Origin"]
83
100
  },
84
101
  owner_details: {
85
102
  id: headline["Owner"]["Id"],
@@ -99,9 +116,6 @@ class Headline
99
116
  # @return [Boolean] true if the deletion was successful
100
117
  def delete(meeting_id, headline_id)
101
118
  response = @conn.delete("/api/v1/L10/#{meeting_id}/headlines/#{headline_id}")
102
-
103
- # Raise an issue if response.status != 200
104
- raise "Failed to delete headline" unless response.status == 200
105
- true
119
+ response.success?
106
120
  end
107
121
  end
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "json"
4
+ require "bloomy/utils/get_user_id"
4
5
 
5
6
  # Class to handle all the operations related to issues
6
7
  class Issue
8
+ include Bloomy::Utilities::UserIdUtility
7
9
  # Initializes a new Issue instance
8
10
  #
9
11
  # @param conn [Object] the connection object to interact with the API
10
- # @param user_id [Integer] the ID of the user
11
- def initialize(conn, user_id)
12
+ def initialize(conn)
12
13
  @conn = conn
13
- @user_id = user_id
14
14
  end
15
15
 
16
16
  # Retrieves details of a specific issue
@@ -30,7 +30,7 @@ class Issue
30
30
  completed_at: response["CloseTime"],
31
31
  meeting_details: {
32
32
  id: response["OriginId"],
33
- name: response["Origin"]
33
+ title: response["Origin"]
34
34
  },
35
35
  owner_details: {
36
36
  id: response["Owner"]["Id"],
@@ -39,15 +39,33 @@ class Issue
39
39
  }
40
40
  end
41
41
 
42
- # Lists issues for a specific user
42
+ # Lists issues for a specific user or meeting
43
43
  #
44
- # @param user_id [Integer] the ID of the user (default is the initialized user ID)
44
+ # @param user_id [Integer, nil] the ID of the user (defaults to initialized user_id)
45
+ # @param meeting_id [Integer, nil] the ID of the meeting
46
+ # @raise [ArgumentError] if both `user_id` and `meeting_id` are provided
45
47
  # @return [Array<Hash>] an array of hashes containing issues details
46
48
  # @example
49
+ # # Fetch issues for the current user
47
50
  # issue.list
48
- # #=> [{ id: 123, title: "Issue Title", notes_url: "http://details.url", ... }, ...]
49
- def list(user_id: @user_id)
50
- response = @conn.get("issues/users/#{user_id}").body
51
+ #
52
+ # # Fetch issues for a specific user
53
+ # issue.list(user_id: 42)
54
+ #
55
+ # # Fetch issues for a specific meeting
56
+ # issue.list(meeting_id: 99)
57
+ def list(user_id: nil, meeting_id: nil)
58
+ if user_id && meeting_id
59
+ raise ArgumentError, "Please provide either `user_id` or `meeting_id`, not both."
60
+ end
61
+
62
+ if meeting_id
63
+ response = @conn.get("l10/#{meeting_id}/issues").body
64
+ else
65
+ user_id ||= self.user_id
66
+ response = @conn.get("issues/users/#{user_id}").body
67
+ end
68
+
51
69
  response.map do |issue|
52
70
  {
53
71
  id: issue["Id"],
@@ -55,7 +73,7 @@ class Issue
55
73
  notes_url: issue["DetailsUrl"],
56
74
  created_at: issue["CreateTime"],
57
75
  meeting_id: issue["OriginId"],
58
- meeting_name: issue["Origin"]
76
+ meeting_title: issue["Origin"]
59
77
  }
60
78
  end
61
79
  end
@@ -68,19 +86,21 @@ class Issue
68
86
  # issue.complete(123)
69
87
  # #=> true
70
88
  def complete(issue_id)
71
- response = @conn.post("issues/#{issue_id}/complete", {complete: true}.to_json).status
72
- response == 200
89
+ response = @conn.post("issues/#{issue_id}/complete", {complete: true}.to_json)
90
+ response.success?
73
91
  end
74
92
 
75
93
  # Creates a new issue
76
94
  #
77
- # @param title [String] the title of the new issue
78
95
  # @param meeting_id [Integer] the ID of the meeting associated with the issue
96
+ # @param title [String] the title of the new issue
97
+ # @param user_id [Integer] the ID of the user responsible for the issue (default: initialized user ID)
98
+ # @param notes [String, nil] the notes for the issue (optional)
79
99
  # @return [Hash] a hash containing the new issue's ID and title
80
100
  # @example
81
- # issue.create("New Issue", 456)
101
+ # issue.create(meeting_id: 123, title: "New Issue")
82
102
  # #=> { id: 789, title: "New Issue" }
83
- def create(meeting_id:, title:, user_id: @user_id, notes: nil)
103
+ def create(meeting_id:, title:, user_id: self.user_id, notes: nil)
84
104
  response = @conn.post("issues/create", {title: title, meetingid: meeting_id, ownerid: user_id, notes: notes}.to_json)
85
105
  {
86
106
  id: response.body["Id"],
@@ -88,7 +108,7 @@ class Issue
88
108
  meeting_title: response.body["Origin"],
89
109
  title: response.body["Name"],
90
110
  user_id: response.body["Owner"]["Id"],
91
- details_url: response.body["DetailsUrl"]
111
+ notes_url: response.body["DetailsUrl"]
92
112
  }
93
113
  end
94
114
  end
@@ -1,16 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bloomy/utils/get_user_id"
4
+
3
5
  # Class to handle all the operations related to meeting
4
6
  # @note
5
7
  # This class is already initialized via the client and usable as `client.measurable.method`
6
8
  class Meeting
9
+ include Bloomy::Utilities::UserIdUtility
7
10
  # Initializes a new Meeting instance
8
11
  #
9
12
  # @param conn [Object] the connection object to interact with the API
10
- # @param user_id [Integer] the ID of the user
11
- def initialize(conn, user_id)
13
+ def initialize(conn)
12
14
  @conn = conn
13
- @user_id = user_id
14
15
  end
15
16
 
16
17
  # Lists all meetings for a specific user
@@ -20,7 +21,7 @@ class Meeting
20
21
  # @example
21
22
  # client.meeting.list
22
23
  # #=> [{ id: 123, name: "Team Meeting" }, ...]
23
- def list(user_id: @user_id)
24
+ def list(user_id = self.user_id)
24
25
  response = @conn.get("L10/#{user_id}/list").body
25
26
  response.map { |meeting| {id: meeting["Id"], name: meeting["Name"]} }
26
27
  end
@@ -99,7 +100,7 @@ class Meeting
99
100
  response.map do |measurable|
100
101
  {
101
102
  id: measurable["Id"],
102
- name: measurable["Name"].strip,
103
+ title: measurable["Name"].strip,
103
104
  target: measurable["Target"],
104
105
  operator: measurable["Direction"],
105
106
  format: measurable["Modifiers"],
@@ -131,7 +132,7 @@ class Meeting
131
132
  measurables = metrics(meeting_id)
132
133
  {
133
134
  id: meeting[:id],
134
- name: meeting[:name],
135
+ title: meeting[:name],
135
136
  attendees: attendees,
136
137
  issues: issues,
137
138
  todos: todos,
@@ -148,7 +149,7 @@ class Meeting
148
149
  # @example
149
150
  # client.meeting.create(title: "New Meeting", attendees: [2, 3])
150
151
  # #=> { meeting_id: 1, title: "New Meeting", attendees: [2, 3] }
151
- def create(title:, add_self: true, attendees: [])
152
+ def create(title, add_self: true, attendees: [])
152
153
  payload = {title: title, addSelf: add_self}.to_json
153
154
  response = @conn.post("L10/create", payload).body
154
155
  meeting_id = response["meetingId"]
@@ -165,6 +166,7 @@ class Meeting
165
166
  # @example
166
167
  # client.meeting.delete(1)
167
168
  def delete(meeting_id)
168
- @conn.delete("L10/#{meeting_id}")
169
+ response = @conn.delete("L10/#{meeting_id}")
170
+ response.success?
169
171
  end
170
172
  end
@@ -1,18 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "json"
4
+ require "bloomy/utils/get_user_id"
4
5
 
5
6
  # Class to handle all the operations related to scorecards
6
7
  # @note
7
8
  # This class is already initialized via the client and usable as `client.scorecard.method`
8
9
  class Scorecard
10
+ include Bloomy::Utilities::UserIdUtility
11
+
9
12
  # Initializes a new Scorecard instance
10
13
  #
11
14
  # @param conn [Object] the connection object to interact with the API
12
- # @param user_id [Integer] the ID of the user
13
- def initialize(conn, user_id)
15
+ def initialize(conn)
14
16
  @conn = conn
15
- @user_id = user_id
16
17
  end
17
18
 
18
19
  # Retrieves the current week details
@@ -48,15 +49,17 @@ class Scorecard
48
49
  #
49
50
  # # Fetch scorecards for a specific meeting
50
51
  # client.scorecard.list(meeting_id: 99)
52
+ # @note
53
+ # The `week_offset` parameter is useful when fetching scores for previous or future weeks.
54
+ # For example, to fetch scores for the previous week, you can set `week_offset` to -1.
55
+ # To fetch scores for a future week, you can set `week_offset` to a positive value.
51
56
  def list(user_id: nil, meeting_id: nil, show_empty: false, week_offset: nil)
52
- if user_id && meeting_id
53
- raise ArgumentError, "Please provide either `user_id` or `meeting_id`, not both."
54
- end
57
+ raise ArgumentError, "Please provide either `user_id` or `meeting_id`, not both." if user_id && meeting_id
55
58
 
56
59
  if meeting_id
57
60
  response = @conn.get("scorecard/meeting/#{meeting_id}").body
58
61
  else
59
- user_id ||= @user_id
62
+ user_id ||= self.user_id
60
63
  response = @conn.get("scorecard/user/#{user_id}").body
61
64
  end
62
65
 
@@ -69,14 +72,15 @@ class Scorecard
69
72
  target: scorecard["Target"],
70
73
  value: scorecard["Measured"],
71
74
  week: scorecard["Week"],
75
+ week_id: scorecard["ForWeek"],
72
76
  updated_at: scorecard["DateEntered"]
73
77
  }
74
78
  end
75
79
 
76
80
  if week_offset
77
81
  week_data = current_week
78
- week_id = week_data[:week_number] - week_offset
79
- scorecards.select! { |scorecard| scorecard[:week] == week_id }
82
+ week_id = week_data[:week_number] + week_offset
83
+ scorecards.select! { |scorecard| scorecard[:week_id] == week_id }
80
84
  end
81
85
 
82
86
  scorecards.select! { |scorecard| scorecard[:value] || show_empty } unless show_empty
@@ -94,11 +98,11 @@ class Scorecard
94
98
  # #=> true
95
99
  # @note
96
100
  # The `week_offset` parameter is useful when updating scores for previous weeks.
97
- # For example, to update the score for the previous week, you can set `week_offset` to 1.
98
- # To update a future week's score, you can set `week_offset` to a negative value.
101
+ # For example, to update the score for the previous week, you can set `week_offset` to -1.
102
+ # To update a future week's score, you can set `week_offset` to a positive value.
99
103
  def score(measurable_id:, score:, week_offset: 0)
100
104
  week_data = current_week
101
- week_id = week_data[:week_number] - week_offset
105
+ week_id = week_data[:week_number] + week_offset
102
106
 
103
107
  response = @conn.put("measurables/#{measurable_id}/week/#{week_id}", {value: score}.to_json)
104
108
  response.success?
@@ -1,31 +1,52 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "date"
4
+ require_relative "../utils/get_user_id"
4
5
 
5
6
  # Class to handle all the operations related to todos
6
7
  class Todo
8
+ include Bloomy::Utilities::UserIdUtility
9
+
7
10
  # Initializes a new Todo instance
8
11
  #
9
12
  # @param conn [Object] the connection object to interact with the API
10
- # @param user_id [Integer] the ID of the user
11
- def initialize(conn, user_id)
13
+ def initialize(conn)
12
14
  @conn = conn
13
- @user_id = user_id
14
15
  end
15
16
 
16
- # Lists all todos for a specific user
17
+ # Lists all todos for a specific user or meeting
17
18
  #
18
- # @param user_id [Integer] the ID of the user (default is the initialized user ID)
19
+ # @param user_id [Integer, nil] the ID of the user (default is the initialized user ID)
20
+ # @param meeting_id [Integer, nil] the ID of the meeting
19
21
  # @return [Array<Hash>] an array of hashes containing todo details
22
+ # @raise [ArgumentError] if both `user_id` and `meeting_id` are provided
20
23
  # @example
24
+ # # Fetch todos for the current user
21
25
  # client.todo.list
22
- # #=> [{ id: 1, title: "Finish report", due_date: "2024-06-10", ... }, ...]
23
- def list(user_id: @user_id)
24
- response = @conn.get("todo/user/#{user_id}").body
26
+ # #=> [{ id: 1, title: "New Todo", due_date: "2024-06-15", ... }]
27
+ #
28
+ # # Fetch todos for a specific user
29
+ # client.todo.list(user_id: 42)
30
+ # # => [{ id: 1, title: "New Todo", due_date: "2024-06-15", ... }]
31
+ #
32
+ # # Fetch todos for a specific meeting
33
+ # client.todo.list(meeting_id: 99)
34
+ # # => [{ id: 1, title: "New Todo", due_date: "2024-06-15", ... }]
35
+ def list(user_id: nil, meeting_id: nil)
36
+ raise ArgumentError, "Please provide either `user_id` or `meeting_id`, not both." if user_id && meeting_id
37
+
38
+ if meeting_id
39
+ response = @conn.get("l10/#{meeting_id}/todos").body
40
+ else
41
+ user_id ||= self.user_id
42
+ response = @conn.get("todo/user/#{user_id}").body
43
+ end
44
+
25
45
  response.map do |todo|
26
46
  {
27
47
  id: todo["Id"],
28
48
  title: todo["Name"],
49
+ notes_url: todo["DetailsUrl"],
29
50
  due_date: todo["DueDate"],
30
51
  created_at: todo["CreateTime"],
31
52
  completed_at: todo["CompleteTime"],
@@ -40,21 +61,23 @@ class Todo
40
61
  # @param meeting_id [Integer] the ID of the meeting associated with the todo
41
62
  # @param due_date [String, nil] the due date of the todo (optional)
42
63
  # @param user_id [Integer] the ID of the user responsible for the todo (default: initialized user ID)
64
+ # @param notes [String, nil] additional notes for the todo (optional)
43
65
  # @return [Hash] a hash containing the new todo's details
44
66
  # @example
45
67
  # client.todo.create(title: "New Todo", meeting_id: 1, due_date: "2024-06-15")
46
68
  # #=> { id: 1, title: "New Todo", meeting_name: "Team Meeting", ... }
47
- def create(title:, meeting_id:, due_date: nil, user_id: @user_id)
48
- payload = {title: title, accountableUserId: user_id}
69
+ def create(title:, meeting_id:, due_date: nil, user_id: self.user_id, notes: nil)
70
+ payload = {title: title, accountableUserId: user_id, notes: notes}
49
71
  payload[:dueDate] = due_date if due_date
50
72
  response = @conn.post("/api/v1/L10/#{meeting_id}/todos", payload.to_json).body
51
73
 
52
74
  {
53
75
  id: response["Id"],
54
76
  title: response["Name"],
55
- meeting_name: response["Origin"],
77
+ meeting_title: response["Origin"],
56
78
  meeting_id: response["OriginId"],
57
- due_date: response["DueDate"]
79
+ due_date: response["DueDate"],
80
+ notes_url: response["DetailsUrl"]
58
81
  }
59
82
  end
60
83
 
@@ -67,7 +90,7 @@ class Todo
67
90
  # #=> { status: 200 }
68
91
  def complete(todo_id)
69
92
  response = @conn.post("/api/v1/todo/#{todo_id}/complete?status=true")
70
- {status: response.status}
93
+ response.success?
71
94
  end
72
95
 
73
96
  # Updates an existing todo
@@ -96,4 +119,30 @@ class Todo
96
119
  updated_at: DateTime.now.to_s
97
120
  }
98
121
  end
122
+
123
+ # Retrieves the details of a specific todo item by its ID.
124
+ #
125
+ # @param todo_id [String] The ID of the todo item to retrieve.
126
+ # @return [Hash] A hash containing the details of the todo item.
127
+ # @raise [RuntimeError] If the request to retrieve the todo details fails.
128
+ # @example
129
+ # client.todo.details(1)
130
+ # #=> { id: 1, title: "Updated Todo", due_date: "2024-11-01T01:41:41.528Z", ... }
131
+ def details(todo_id)
132
+ response = @conn.get("/api/v1/todo/#{todo_id}")
133
+ raise "Failed to get todo details. Status: #{response.status}" unless response.success?
134
+
135
+ todo = response.body
136
+ {
137
+ id: todo["Id"],
138
+ meeting_id: todo["OriginId"],
139
+ meeting_title: todo["Origin"],
140
+ title: todo["Name"],
141
+ notes_url: todo["DetailsUrl"],
142
+ due_date: todo["DueDate"],
143
+ created_at: todo["CreateTime"],
144
+ completed_at: todo["CompleteTime"],
145
+ status: todo["Complete"] ? "Complete" : "Incomplete"
146
+ }
147
+ end
99
148
  end
@@ -1,26 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "bloomy/utils/get_user_id"
4
+
3
5
  # Class to handle all the operations related to users
4
6
  class User
5
- attr_reader :default_user_id
7
+ include Bloomy::Utilities::UserIdUtility
6
8
 
7
9
  # Initializes a new User instance
8
10
  #
9
11
  # @param conn [Object] the connection object to interact with the API
10
12
  def initialize(conn)
11
13
  @conn = conn
12
- @default_user_id = current_user_id
13
- end
14
-
15
- # Retrieves the current user's ID
16
- #
17
- # @return [Integer] the ID of the current user
18
- # @example
19
- # client.user.current_user_id
20
- # #=> 1
21
- def current_user_id
22
- response = @conn.get("users/mine").body
23
- response["Id"]
24
14
  end
25
15
 
26
16
  # Retrieves details of a specific user
@@ -33,13 +23,12 @@ class User
33
23
  # @example
34
24
  # client.user.details
35
25
  # #=> {name: "John Doe", id: 1, image_url: "http://example.com/image.jpg", ...}
36
- def details(user_id: @default_user_id, direct_reports: false, positions: false, all: false)
26
+ def details(user_id = self.user_id, direct_reports: false, positions: false, all: false)
37
27
  response = @conn.get("users/#{user_id}").body
38
28
  user_details = {name: response["Name"], id: response["Id"], image_url: response["ImageUrl"]}
39
29
 
40
- user_details[:direct_reports] = direct_reports(user_id: user_id) if direct_reports || all
41
- user_details[:positions] = positions(user_id: user_id) if positions || all
42
-
30
+ user_details[:direct_reports] = direct_reports(user_id) if direct_reports || all
31
+ user_details[:positions] = positions(user_id) if positions || all
43
32
  user_details
44
33
  end
45
34
 
@@ -50,7 +39,7 @@ class User
50
39
  # @example
51
40
  # client.user.direct_reports
52
41
  # #=> [{name: "Jane Smith", id: 2, image_url: "http://example.com/image.jpg"}, ...]
53
- def direct_reports(user_id: @default_user_id)
42
+ def direct_reports(user_id = self.user_id)
54
43
  direct_reports_response = @conn.get("users/#{user_id}/directreports").body
55
44
  direct_reports_response.map { |report| {name: report["Name"], id: report["Id"], image_url: report["ImageUrl"]} }
56
45
  end
@@ -62,7 +51,7 @@ class User
62
51
  # @example
63
52
  # user.positions
64
53
  # #=> [{name: "Manager", id: 3}, ...]
65
- def positions(user_id: @default_user_id)
54
+ def positions(user_id = self.user_id)
66
55
  position_response = @conn.get("users/#{user_id}/seats").body
67
56
  position_response.map do |position|
68
57
  {name: position["Group"]["Position"]["Name"], id: position["Group"]["Position"]["Id"]}
@@ -0,0 +1,22 @@
1
+ module Bloomy
2
+ module Utilities
3
+ module UserIdUtility
4
+ # Lazy loads the user_id of the default user
5
+ #
6
+ # @return [String] the user_id of the default user
7
+ def user_id
8
+ @user_id ||= default_user_id
9
+ end
10
+
11
+ private
12
+
13
+ # Returns the user_id of the default user
14
+ #
15
+ # @return [String] The user_id of the default user
16
+ def default_user_id
17
+ response = @conn.get("users/mine").body
18
+ response["Id"]
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bloomy
4
- VERSION = "0.3.0"
4
+ VERSION = "0.5.4"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bloomy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Franccesco Orozco
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-04 00:00:00.000000000 Z
11
+ date: 2024-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -64,6 +64,7 @@ files:
64
64
  - lib/bloomy/operations/scorecard.rb
65
65
  - lib/bloomy/operations/todos.rb
66
66
  - lib/bloomy/operations/users.rb
67
+ - lib/bloomy/utils/get_user_id.rb
67
68
  - lib/bloomy/version.rb
68
69
  - sig/bloomy.rbs
69
70
  homepage: https://github.com/franccesco/bloomy