bloomy 0.3.0 → 0.5.4

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 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