bloomy 0.11.5 → 0.12.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d071b4ec08a9bf16f615031f8bf83901546630686140df746419c8f1c1740673
4
- data.tar.gz: 76788aef37b387aaaf778485764cd1155db7b08ac0dce50c697bf4ffa49c0d86
3
+ metadata.gz: 7bdff815414812cb7824504342fb4e3b12a2bf7e34b9780275fc1e598c4101dc
4
+ data.tar.gz: '0687ba4239c6e4fbcc03d0e6e0405f18488705fd83b95014e7b70f8c1ad06c51'
5
5
  SHA512:
6
- metadata.gz: 12d11081a1bd2789961c9862724dffa5cac215855086c995eecc5753ddaaa07e5f51100a9bb153432654e4cfc2caa9d23e68b0ce3036913ef44f7a91cfa68c21
7
- data.tar.gz: 233d127739f77c8c4d608a979fb0bc53277945f2af6d1f62c00081c668a22aa3741015d5b1c2d43f08c7c2f4988e41c03377c7f846eda6bdd65e06a24d44304a
6
+ metadata.gz: 03a0f56e7947c6615b7ae0819c081b81d98f79e7b41451c62feb30c0c4bb2d17fc20b743317997d68c5b15e7cfaf06f69844e2be26d192da773b35b46ed77f56
7
+ data.tar.gz: c336b3966589127d7e56170428515910139799d2de6bcb01b214a62c6d5a00663afa750363351dbf91663b7427001c28deb47ca5f5c76efa33a63f035077a8df
data/lib/bloomy/client.rb CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "faraday"
4
4
 
5
- require "bloomy/types/items"
6
5
  require "bloomy/operations/users"
7
6
  require "bloomy/operations/todos"
8
7
  require "bloomy/operations/goals"
@@ -10,7 +9,6 @@ require "bloomy/operations/meetings"
10
9
  require "bloomy/operations/scorecard"
11
10
  require "bloomy/operations/issues"
12
11
  require "bloomy/operations/headlines"
13
- require "bloomy/utils/plugin_loader"
14
12
 
15
13
  module Bloomy
16
14
  # The Client class is the main entry point for interacting with the Bloomy API.
@@ -46,9 +44,6 @@ module Bloomy
46
44
  @scorecard = Scorecard.new(@conn)
47
45
  @issue = Issue.new(@conn)
48
46
  @headline = Headline.new(@conn)
49
-
50
- # Initialize plugins
51
- Bloomy::Utilities::Plugin.apply(self)
52
47
  end
53
48
  end
54
49
  end
@@ -19,22 +19,22 @@ module Bloomy
19
19
  #
20
20
  # @param user_id [Integer] the ID of the user (default is the initialized user ID)
21
21
  # @param archived [Boolean] whether to include archived goals (default: false)
22
- # @return [Array<GoalItem>, Hash] Returns either:
23
- # - An array of GoalItem objects if archived is false
24
- # - A hash with :active and :archived arrays of GoalItem objects if archived is true
22
+ # @return [Array<Hash>, Hash] Returns either:
23
+ # - An array of goal hashes if archived is false
24
+ # - A hash with :active and :archived arrays of goal hashes if archived is true
25
25
  # @example List active goals
26
26
  # client.goal.list
27
- # #=> [#<GoalItem id: 1, title: "Complete project", ...>]
27
+ # #=> [{ id: 1, title: "Complete project", ... }]
28
28
  #
29
29
  # @example List both active and archived goals
30
30
  # client.goal.list(archived: true)
31
31
  # #=> {
32
- # active: [#<GoalItem id: 1, ...>],
33
- # archived: [#<GoalItem id: 2, ...>]
32
+ # active: [{ id: 1, ... }],
33
+ # archived: [{ id: 2, ... }]
34
34
  # }
35
35
  def list(user_id = self.user_id, archived: false)
36
36
  active_goals = @conn.get("rocks/user/#{user_id}?include_origin=true").body.map do |goal|
37
- Types::GoalItem.new(
37
+ {
38
38
  id: goal["Id"],
39
39
  user_id: goal["Owner"]["Id"],
40
40
  user_name: goal["Owner"]["Name"],
@@ -44,7 +44,7 @@ module Bloomy
44
44
  status: goal["Complete"] ? "Completed" : "Incomplete",
45
45
  meeting_id: goal["Origins"].empty? ? nil : goal["Origins"][0]["Id"],
46
46
  meeting_title: goal["Origins"].empty? ? nil : goal["Origins"][0]["Name"]
47
- )
47
+ }
48
48
  end
49
49
 
50
50
  archived ? {active: active_goals, archived: get_archived_goals(user_id)} : active_goals
@@ -55,7 +55,7 @@ module Bloomy
55
55
  # @param title [String] the title of the new goal
56
56
  # @param meeting_id [Integer] the ID of the meeting associated with the goal
57
57
  # @param user_id [Integer] the ID of the user responsible for the goal (default: initialized user ID)
58
- # @return [GoalItem] the newly created goal
58
+ # @return [Hash] the newly created goal
59
59
  # @example
60
60
  # client.goal.create(title: "New Goal", meeting_id: 1)
61
61
  # #=> { goal_id: 1, title: "New Goal", meeting_id: 1, ... }
@@ -63,7 +63,7 @@ module Bloomy
63
63
  payload = {title: title, accountableUserId: user_id}.to_json
64
64
  response = @conn.post("L10/#{meeting_id}/rocks", payload).body
65
65
 
66
- Types::GoalItem.new(
66
+ {
67
67
  id: response["Id"],
68
68
  user_id: user_id,
69
69
  user_name: response["Owner"]["Name"],
@@ -72,7 +72,7 @@ module Bloomy
72
72
  meeting_title: response["Origins"][0]["Name"],
73
73
  status: {complete: 2, on: 1, off: 0}.key(response["Completion"]).to_s,
74
74
  created_at: response["CreateTime"]
75
- )
75
+ }
76
76
  end
77
77
 
78
78
  # Deletes a goal
@@ -139,20 +139,20 @@ module Bloomy
139
139
  # Retrieves all archived goals for a specific user (private method)
140
140
  #
141
141
  # @param user_id [Integer] the ID of the user (default is the initialized user ID)
142
- # @return [Array<GoalItem>] an array of GoalItem objects containing archived goal details
142
+ # @return [Array<Hash>] an array of hashes containing archived goal details
143
143
  # @example
144
144
  # goal.send(:get_archived_goals)
145
145
  # #=> [{ id: 1, title: "Archived Goal", created_at: "2024-06-10", ... }, ...]
146
146
  def get_archived_goals(user_id = self.user_id)
147
147
  response = @conn.get("archivedrocks/user/#{user_id}").body
148
148
  response.map do |goal|
149
- Types::GoalItem.new(
149
+ {
150
150
  id: goal["Id"],
151
151
  title: goal["Name"],
152
152
  created_at: goal["CreateTime"],
153
153
  due_date: goal["DueDate"],
154
154
  status: goal["Complete"] ? "Complete" : "Incomplete"
155
- )
155
+ }
156
156
  end
157
157
  end
158
158
  end
@@ -18,18 +18,18 @@ module Bloomy
18
18
  # @param title [String] the title of the headline
19
19
  # @param owner_id [Integer] the ID of the headline owner
20
20
  # @param notes [String] additional notes for the headline
21
- # @return [HeadlineItem] containing id, title, owner_details, and notes_url
21
+ # @return [Hash] containing id, title, owner_details, and notes_url
22
22
  def create(meeting_id:, title:, owner_id: user_id, notes: nil)
23
23
  response = @conn.post("/api/v1/L10/#{meeting_id}/headlines",
24
24
  {title: title, ownerId: owner_id, notes: notes}.to_json)
25
25
  raise "Failed to create headline" unless response.status == 200
26
26
 
27
- Types::HeadlineItem.new(
27
+ {
28
28
  id: response.body["Id"],
29
29
  title: response.body["Name"],
30
- owner_details: Types::UserItem.new(id: response.body["OwnerId"]),
30
+ owner_details: {id: response.body["OwnerId"]},
31
31
  notes_url: response.body["DetailsUrl"]
32
- )
32
+ }
33
33
  end
34
34
 
35
35
  # Updates a headline
@@ -46,28 +46,28 @@ module Bloomy
46
46
  # Get headline details
47
47
  #
48
48
  # @param headline_id [Integer] the ID of the headline
49
- # @return [HeadlineItem] containing id, title, notes_url, meeting_details,
50
- # owner_details, archived, created_at, and closed_at
49
+ # @return [Hash] containing id, title, notes_url, meeting_details,
50
+ # owner_details, archived, created_at, and closed_at
51
51
  def details(headline_id)
52
52
  response = @conn.get("/api/v1/headline/#{headline_id}?Include_Origin=true")
53
53
  raise "Failed to get headline details" unless response.status == 200
54
54
 
55
- Types::HeadlineItem.new(
55
+ {
56
56
  id: response.body["Id"],
57
57
  title: response.body["Name"],
58
58
  notes_url: response.body["DetailsUrl"],
59
- meeting_details: Types::MeetingItem.new(
59
+ meeting_details: {
60
60
  id: response.body["OriginId"],
61
61
  title: response.body["Origin"]
62
- ),
63
- owner_details: Types::UserItem.new(
62
+ },
63
+ owner_details: {
64
64
  id: response.body["Owner"]["Id"],
65
65
  name: response.body["Owner"]["Name"]
66
- ),
66
+ },
67
67
  archived: response.body["Archived"],
68
68
  created_at: response.body["CreateTime"],
69
69
  closed_at: response.body["CloseTime"]
70
- )
70
+ }
71
71
  end
72
72
 
73
73
  # Get headlines for a user or a meeting.
@@ -75,7 +75,7 @@ module Bloomy
75
75
  # @param user_id [Integer, nil] the ID of the user (defaults to initialized user_id)
76
76
  # @param meeting_id [Integer, nil] the ID of the meeting
77
77
  # @raise [ArgumentError] if both `user_id` and `meeting_id` are provided
78
- # @return [Array<HeadlineItem>] a list of headlines containing:
78
+ # @return [Array<Hash>] a list of headlines containing:
79
79
  # - id
80
80
  # - title
81
81
  # - meeting_details
@@ -86,15 +86,15 @@ module Bloomy
86
86
  # @example
87
87
  # client.headline.list
88
88
  # #=> [
89
- # #<HeadlineItem
89
+ # {
90
90
  # id: 1,
91
91
  # title: "Headline Title",
92
- # meeting_details: #<MeetingItem id: 1, title: "Team Meeting">,
93
- # owner_details: #<UserItem id: 1, name: "John Doe">,
92
+ # meeting_details: { id: 1, title: "Team Meeting" },
93
+ # owner_details: { id: 1, name: "John Doe" },
94
94
  # archived: false,
95
95
  # created_at: "2023-01-01",
96
96
  # closed_at: nil
97
- # >
97
+ # }
98
98
  # ]
99
99
  def list(user_id: nil, meeting_id: nil)
100
100
  raise ArgumentError, "Please provide either `user_id` or `meeting_id`, not both." if user_id && meeting_id
@@ -109,21 +109,21 @@ module Bloomy
109
109
  raise "Failed to list headlines" unless response.success?
110
110
 
111
111
  response.body.map do |headline|
112
- Types::HeadlineItem.new(
112
+ {
113
113
  id: headline["Id"],
114
114
  title: headline["Name"],
115
- meeting_details: Types::MeetingItem.new(
115
+ meeting_details: {
116
116
  id: headline["OriginId"],
117
117
  title: headline["Origin"]
118
- ),
119
- owner_details: Types::UserItem.new(
118
+ },
119
+ owner_details: {
120
120
  id: headline["Owner"]["Id"],
121
121
  name: headline["Owner"]["Name"]
122
- ),
122
+ },
123
123
  archived: headline["Archived"],
124
124
  created_at: headline["CreateTime"],
125
125
  closed_at: headline["CloseTime"]
126
- )
126
+ }
127
127
  end
128
128
  end
129
129
 
@@ -21,11 +21,11 @@ module Bloomy
21
21
  # Retrieves detailed information about a specific issue
22
22
  #
23
23
  # @param issue_id [Integer] Unique identifier of the issue
24
- # @return [Types::IssueDetails] Detailed information about the issue
24
+ # @return [Hash] Detailed information about the issue
25
25
  # @raise [ApiError] When the API request fails or returns invalid data
26
26
  def details(issue_id)
27
27
  response = @conn.get("issues/#{issue_id}").body
28
- Types::IssueItem.new(
28
+ {
29
29
  id: response["Id"],
30
30
  title: response["Name"],
31
31
  notes_url: response["DetailsUrl"],
@@ -35,14 +35,14 @@ module Bloomy
35
35
  meeting_title: response["Origin"],
36
36
  user_id: response["Owner"]["Id"],
37
37
  user_name: response["Owner"]["Name"]
38
- )
38
+ }
39
39
  end
40
40
 
41
41
  # Lists issues filtered by user or meeting
42
42
  #
43
43
  # @param user_id [Integer, nil] Unique identifier of the user (optional)
44
44
  # @param meeting_id [Integer, nil] Unique identifier of the meeting (optional)
45
- # @return [Array<Types::IssueItem>] List of issues matching the filter criteria
45
+ # @return [Array<Hash>] List of issues matching the filter criteria
46
46
  # @raise [ArgumentError] When both user_id and meeting_id are provided
47
47
  # @raise [ApiError] When the API request fails or returns invalid data
48
48
  def list(user_id: nil, meeting_id: nil)
@@ -53,14 +53,14 @@ module Bloomy
53
53
  response = meeting_id ? @conn.get("l10/#{meeting_id}/issues").body : @conn.get("issues/users/#{user_id || self.user_id}").body
54
54
 
55
55
  response.map do |issue|
56
- Types::IssueItem.new(
56
+ {
57
57
  id: issue["Id"],
58
58
  title: issue["Name"],
59
59
  notes_url: issue["DetailsUrl"],
60
60
  created_at: issue["CreateTime"],
61
61
  meeting_id: issue["OriginId"],
62
62
  meeting_title: issue["Origin"]
63
- )
63
+ }
64
64
  end
65
65
  end
66
66
 
@@ -80,19 +80,19 @@ module Bloomy
80
80
  # @param title [String] Title/name of the issue
81
81
  # @param user_id [Integer] Unique identifier of the issue owner (defaults to current user)
82
82
  # @param notes [String, nil] Additional notes or description for the issue (optional)
83
- # @return [Types::IssueItem] Newly created issue details
83
+ # @return [Hash] Newly created issue details
84
84
  # @raise [ApiError] When the API request fails or returns invalid data
85
85
  # @raise [ArgumentError] When required parameters are missing or invalid
86
86
  def create(meeting_id:, title:, user_id: self.user_id, notes: nil)
87
87
  response = @conn.post("issues/create", {title: title, meetingid: meeting_id, ownerid: user_id, notes: notes}.to_json)
88
- Types::IssueItem.new(
88
+ {
89
89
  id: response.body["Id"],
90
90
  meeting_id: response.body["OriginId"],
91
91
  meeting_title: response.body["Origin"],
92
92
  title: response.body["Name"],
93
93
  user_id: response.body["Owner"]["Id"],
94
94
  notes_url: response.body["DetailsUrl"]
95
- )
95
+ }
96
96
  end
97
97
  end
98
98
  end
@@ -24,7 +24,7 @@ module Bloomy
24
24
  # #=> [{ id: 123, name: "Team Meeting" }, ...]
25
25
  def list(user_id = self.user_id)
26
26
  response = @conn.get("L10/#{user_id}/list").body
27
- response.map { |meeting| Types::MeetingItem.new(id: meeting["Id"], title: meeting["Name"]) }
27
+ response.map { |meeting| {id: meeting["Id"], title: meeting["Name"]} }
28
28
  end
29
29
 
30
30
  # Lists all attendees for a specific meeting
@@ -36,7 +36,7 @@ module Bloomy
36
36
  # #=> [{ name: "John Doe", id: 1 }, ...]
37
37
  def attendees(meeting_id)
38
38
  response = @conn.get("L10/#{meeting_id}/attendees").body
39
- response.map { |attendee| Types::UserItem.new(id: attendee["Id"], name: attendee["Name"]) }
39
+ response.map { |attendee| {id: attendee["Id"], name: attendee["Name"]} }
40
40
  end
41
41
 
42
42
  # Lists all issues for a specific meeting
@@ -50,7 +50,7 @@ module Bloomy
50
50
  def issues(meeting_id, include_closed: false)
51
51
  response = @conn.get("L10/#{meeting_id}/issues?include_resolved=#{include_closed}").body
52
52
  response.map do |issue|
53
- Types::IssueItem.new(
53
+ {
54
54
  id: issue["Id"],
55
55
  title: issue["Name"],
56
56
  notes_url: issue["DetailsUrl"],
@@ -60,7 +60,7 @@ module Bloomy
60
60
  user_name: issue.dig("Owner", "Name"),
61
61
  meeting_id: meeting_id,
62
62
  meeting_title: issue["Origin"]
63
- )
63
+ }
64
64
  end
65
65
  end
66
66
 
@@ -75,19 +75,17 @@ module Bloomy
75
75
  def todos(meeting_id, include_closed: false)
76
76
  response = @conn.get("L10/#{meeting_id}/todos?INCLUDE_CLOSED=#{include_closed}").body
77
77
  response.map do |todo|
78
- Types::TodoItem.new(
79
- {
80
- id: todo["Id"],
81
- title: todo["Name"],
82
- due_date: todo["DueDate"],
83
- notes_url: todo["DetailsUrl"],
84
- status: todo["Complete"] ? "Complete" : "Incomplete",
85
- created_at: todo["CreateTime"],
86
- completed_at: todo["CompleteTime"],
87
- user_id: todo.dig("Owner", "Id"),
88
- user_name: todo.dig("Owner", "Name")
89
- }
90
- )
78
+ {
79
+ id: todo["Id"],
80
+ title: todo["Name"],
81
+ due_date: todo["DueDate"],
82
+ notes_url: todo["DetailsUrl"],
83
+ status: todo["Complete"] ? "Complete" : "Incomplete",
84
+ created_at: todo["CreateTime"],
85
+ completed_at: todo["CompleteTime"],
86
+ user_id: todo.dig("Owner", "Id"),
87
+ user_name: todo.dig("Owner", "Name")
88
+ }
91
89
  end
92
90
  end
93
91
 
@@ -105,7 +103,7 @@ module Bloomy
105
103
  response.map do |measurable|
106
104
  next unless measurable["Id"] && measurable["Name"]
107
105
 
108
- Types::MetricItem.new(
106
+ {
109
107
  id: measurable["Id"],
110
108
  title: measurable["Name"].to_s.strip,
111
109
  target: measurable["Target"].to_f,
@@ -115,7 +113,7 @@ module Bloomy
115
113
  user_name: measurable.dig("Owner", "Name"),
116
114
  admin_id: measurable.dig("Admin", "Id"),
117
115
  admin_name: measurable.dig("Admin", "Name")
118
- )
116
+ }
119
117
  end.compact
120
118
  end
121
119
 
@@ -128,15 +126,15 @@ module Bloomy
128
126
  # client.meeting.details(1)
129
127
  # #=> { id: 1, name: "Team Meeting", attendees: [...], issues: [...], todos: [...], metrics: [...] }
130
128
  def details(meeting_id, include_closed: false)
131
- meeting = list.find { |m| m.id == meeting_id }
132
- Types::MeetingDetails.new(
133
- id: meeting.id,
134
- title: meeting.title,
129
+ meeting = list.find { |m| m[:id] == meeting_id }
130
+ {
131
+ id: meeting[:id],
132
+ title: meeting[:title],
135
133
  attendees: attendees(meeting_id),
136
134
  issues: issues(meeting_id, include_closed: include_closed),
137
135
  todos: todos(meeting_id, include_closed: include_closed),
138
136
  metrics: metrics(meeting_id)
139
- )
137
+ }
140
138
  end
141
139
 
142
140
  # Creates a new meeting
@@ -19,18 +19,18 @@ module Bloomy
19
19
 
20
20
  # Retrieves the current week details
21
21
  #
22
- # @return [Types::WeekItem] an object containing current week details
22
+ # @return [Hash] a hash containing current week details
23
23
  # @example
24
24
  # client.scorecard.current_week
25
- # #=> #<Types::WeekItem @id=123, @week_number=24, @week_start="2024-06-10", @week_end="2024-06-16">
25
+ # #=> { id: 123, week_number: 24, week_start: "2024-06-10", week_end: "2024-06-16" }
26
26
  def current_week
27
27
  response = @conn.get("weeks/current").body
28
- Types::WeekItem.new(
28
+ {
29
29
  id: response["Id"],
30
30
  week_number: response["ForWeekNumber"],
31
31
  week_start: response["LocalDate"]["Date"],
32
32
  week_end: response["ForWeek"]
33
- )
33
+ }
34
34
  end
35
35
 
36
36
  # Retrieves the scorecards for a user or a meeting.
@@ -40,7 +40,7 @@ module Bloomy
40
40
  # @param show_empty [Boolean] whether to include scores with nil values (default: false)
41
41
  # @param week_offset [Integer, nil] offset for the week number to filter scores
42
42
  # @raise [ArgumentError] if both `user_id` and `meeting_id` are provided
43
- # @return [Array<Types::ScorecardItem>] an array of scorecard items
43
+ # @return [Array<Hash>] an array of scorecard hashes
44
44
  # @example
45
45
  # # Fetch scorecards for the current user
46
46
  # client.scorecard.list
@@ -65,7 +65,7 @@ module Bloomy
65
65
  end
66
66
 
67
67
  scorecards = response["Scores"].map do |scorecard|
68
- Types::ScorecardItem.new(
68
+ {
69
69
  id: scorecard["Id"],
70
70
  measurable_id: scorecard["MeasurableId"],
71
71
  accountable_user_id: scorecard["AccountableUserId"],
@@ -75,16 +75,16 @@ module Bloomy
75
75
  week: scorecard["Week"],
76
76
  week_id: scorecard["ForWeek"],
77
77
  updated_at: scorecard["DateEntered"]
78
- )
78
+ }
79
79
  end
80
80
 
81
81
  if week_offset
82
82
  week_data = current_week
83
- week_id = week_data.week_number + week_offset
84
- scorecards.select! { |scorecard| scorecard.week_id == week_id }
83
+ week_id = week_data[:week_number] + week_offset
84
+ scorecards.select! { |scorecard| scorecard[:week_id] == week_id }
85
85
  end
86
86
 
87
- scorecards.select! { |scorecard| scorecard.value || show_empty } unless show_empty
87
+ scorecards.select! { |scorecard| scorecard[:value] || show_empty } unless show_empty
88
88
  scorecards
89
89
  end
90
90
 
@@ -19,12 +19,12 @@ module Bloomy
19
19
  #
20
20
  # @param user_id [Integer, nil] the ID of the user (default is the initialized user ID)
21
21
  # @param meeting_id [Integer, nil] the ID of the meeting
22
- # @return [Array<TodoItem>] an array of TodoItem objects
22
+ # @return [Array<Hash>] an array of todo hashes
23
23
  # @raise [ArgumentError] if both `user_id` and `meeting_id` are provided
24
24
  # @example
25
25
  # # Fetch todos for the current user
26
26
  # client.todo.list
27
- # #=> [#<TodoItem id: 1, title: "New Todo", due_date: "2024-06-15", ...>]
27
+ # #=> [{ id: 1, title: "New Todo", due_date: "2024-06-15", ... }]
28
28
  def list(user_id: nil, meeting_id: nil)
29
29
  raise ArgumentError, "Please provide either `user_id` or `meeting_id`, not both." if user_id && meeting_id
30
30
 
@@ -36,7 +36,7 @@ module Bloomy
36
36
  end
37
37
 
38
38
  response.map do |todo|
39
- Types::TodoItem.new(
39
+ {
40
40
  id: todo["Id"],
41
41
  title: todo["Name"],
42
42
  notes_url: todo["DetailsUrl"],
@@ -44,7 +44,7 @@ module Bloomy
44
44
  created_at: todo["CreateTime"],
45
45
  completed_at: todo["CompleteTime"],
46
46
  status: todo["Complete"] ? "Complete" : "Incomplete"
47
- )
47
+ }
48
48
  end
49
49
  end
50
50
 
@@ -55,23 +55,23 @@ module Bloomy
55
55
  # @param due_date [String, nil] the due date of the todo (optional)
56
56
  # @param user_id [Integer] the ID of the user responsible for the todo (default: initialized user ID)
57
57
  # @param notes [String, nil] additional notes for the todo (optional)
58
- # @return [TodoItem] the newly created todo item
58
+ # @return [Hash] the newly created todo hash
59
59
  # @example
60
60
  # client.todo.create(title: "New Todo", meeting_id: 1, due_date: "2024-06-15")
61
- # #=> #<TodoItem id: 1, title: "New Todo", due_date: "2024-06-15", ...>
61
+ # #=> { id: 1, title: "New Todo", due_date: "2024-06-15", ... }
62
62
  def create(title:, meeting_id:, due_date: nil, user_id: self.user_id, notes: nil)
63
63
  payload = {title: title, accountableUserId: user_id, notes: notes}
64
64
  payload[:dueDate] = due_date if due_date
65
65
  response = @conn.post("/api/v1/L10/#{meeting_id}/todos", payload.to_json).body
66
66
 
67
- Types::TodoItem.new(
67
+ {
68
68
  id: response["Id"],
69
69
  title: response["Name"],
70
70
  notes_url: response["DetailsUrl"],
71
71
  due_date: response["DueDate"],
72
72
  created_at: DateTime.now.to_s,
73
73
  status: "Incomplete"
74
- )
74
+ }
75
75
  end
76
76
 
77
77
  # Marks a todo as complete
@@ -91,12 +91,12 @@ module Bloomy
91
91
  # @param todo_id [Integer] the ID of the todo to update
92
92
  # @param title [String, nil] the new title of the todo (optional)
93
93
  # @param due_date [String, nil] the new due date of the todo (optional)
94
- # @return [TodoItem] the updated todo item
94
+ # @return [Hash] the updated todo hash
95
95
  # @raise [ArgumentError] if no update fields are provided
96
96
  # @raise [RuntimeError] if the update request fails
97
97
  # @example
98
98
  # todo.update(todo_id: 1, title: "Updated Todo", due_date: "2024-11-01")
99
- # #=> #<TodoItem id: 1, title: "Updated Todo", due_date: "2024-11-01", ...>
99
+ # #=> { id: 1, title: "Updated Todo", due_date: "2024-11-01", ... }
100
100
  def update(todo_id:, title: nil, due_date: nil)
101
101
  payload = {}
102
102
  payload[:title] = title if title
@@ -107,29 +107,29 @@ module Bloomy
107
107
  response = @conn.put("/api/v1/todo/#{todo_id}", payload.to_json)
108
108
  raise "Failed to update todo. Status: #{response.status}" unless response.status == 200
109
109
 
110
- Types::TodoItem.new(
110
+ {
111
111
  id: todo_id,
112
112
  title: title,
113
113
  due_date: due_date,
114
114
  created_at: nil,
115
115
  status: "Incomplete"
116
- )
116
+ }
117
117
  end
118
118
 
119
119
  # Retrieves the details of a specific todo item by its ID.
120
120
  #
121
121
  # @param todo_id [Integer] The ID of the todo item to retrieve.
122
- # @return [TodoItem] The requested todo item
122
+ # @return [Hash] The requested todo hash
123
123
  # @raise [RuntimeError] If the request to retrieve the todo details fails.
124
124
  # @example
125
125
  # client.todo.details(1)
126
- # #=> #<TodoItem id: 1, title: "Updated Todo", due_date: "2024-11-01", ...>
126
+ # #=> { id: 1, title: "Updated Todo", due_date: "2024-11-01", ... }
127
127
  def details(todo_id)
128
128
  response = @conn.get("/api/v1/todo/#{todo_id}")
129
129
  raise "Failed to get todo details. Status: #{response.status}" unless response.success?
130
130
 
131
131
  todo = response.body
132
- Types::TodoItem.new(
132
+ {
133
133
  id: todo["Id"],
134
134
  title: todo["Name"],
135
135
  notes_url: todo["DetailsUrl"],
@@ -137,7 +137,7 @@ module Bloomy
137
137
  created_at: todo["CreateTime"],
138
138
  completed_at: todo["CompleteTime"],
139
139
  status: todo["Complete"] ? "Complete" : "Incomplete"
140
- )
140
+ }
141
141
  end
142
142
  end
143
143
  end
@@ -20,99 +20,84 @@ module Bloomy
20
20
  # @param direct_reports [Boolean] whether to include direct reports (default: false)
21
21
  # @param positions [Boolean] whether to include positions (default: false)
22
22
  # @param all [Boolean] whether to include both direct reports and positions (default: false)
23
- # @return [Types::UserItem] a UserItem object containing user details
24
- # @example
25
- # client.user.details
26
- # #=> #<Types::UserItem id: 1, name: "John Doe", image_url: "http://example.com/image.jpg">
23
+ # @return [Hash] a hash containing user details
27
24
  def details(user_id = self.user_id, direct_reports: false, positions: false, all: false)
28
25
  response = @conn.get("users/#{user_id}").body
29
- user_details = Types::UserItem.new(
26
+ user_details = {
30
27
  id: response["Id"],
31
28
  name: response["Name"],
32
29
  image_url: response["ImageUrl"]
33
- )
30
+ }
34
31
 
35
- user_details.direct_reports = direct_reports(user_id) if direct_reports || all
36
- user_details.positions = positions(user_id) if positions || all
32
+ user_details[:direct_reports] = direct_reports(user_id) if direct_reports || all
33
+ user_details[:positions] = positions(user_id) if positions || all
37
34
  user_details
38
35
  end
39
36
 
40
37
  # Retrieves direct reports of a specific user
41
38
  #
42
39
  # @param user_id [Integer] the ID of the user (default: the current user ID)
43
- # @return [Array<Types::UserItem>] an array of UserItem objects containing direct report details
44
- # @example
45
- # client.user.direct_reports
46
- # #=> [#<Types::UserItem name: "Jane Smith", id: 2, image_url: "http://example.com/image.jpg">, ...]
40
+ # @return [Array<Hash>] an array of hashes containing direct report details
47
41
  def direct_reports(user_id = self.user_id)
48
42
  direct_reports_response = @conn.get("users/#{user_id}/directreports").body
49
43
  direct_reports_response.map do |report|
50
- Types::UserItem.new(
44
+ {
51
45
  name: report["Name"],
52
46
  id: report["Id"],
53
47
  image_url: report["ImageUrl"]
54
- )
48
+ }
55
49
  end
56
50
  end
57
51
 
58
52
  # Retrieves positions of a specific user
59
53
  #
60
54
  # @param user_id [Integer] the ID of the user (default: the current user ID)
61
- # @return [Array<Types::UserItem>] an array of UserItem objects containing position details
62
- # @example
63
- # user.positions
64
- # #=> [#<Types::UserItem name: "Manager", id: 3>, ...]
55
+ # @return [Array<Hash>] an array of hashes containing position details
65
56
  def positions(user_id = self.user_id)
66
57
  position_response = @conn.get("users/#{user_id}/seats").body
67
58
  position_response.map do |position|
68
- Types::UserItem.new(
59
+ {
69
60
  name: position["Group"]["Position"]["Name"],
70
61
  id: position["Group"]["Position"]["Id"]
71
- )
62
+ }
72
63
  end
73
64
  end
74
65
 
75
66
  # Searches for users based on a search term
76
67
  #
77
68
  # @param term [String] the search term
78
- # @return [Array<Types::UserItem>] an array of UserItem objects containing search results
79
- # @example
80
- # user.search("John")
81
- # #=> [#<Types::UserItem id: 1, name: "John Doe", description: "Developer", ...>, ...]
69
+ # @return [Array<Hash>] an array of hashes containing search results
82
70
  def search(term)
83
71
  response = @conn.get("search/user", term: term).body
84
72
  response.map do |user|
85
- Types::UserItem.new(
73
+ {
86
74
  id: user["Id"],
87
75
  name: user["Name"],
88
76
  description: user["Description"],
89
77
  email: user["Email"],
90
78
  organization_id: user["OrganizationId"],
91
79
  image_url: user["ImageUrl"]
92
- )
80
+ }
93
81
  end
94
82
  end
95
83
 
96
84
  # Retrieves all users in the system
97
85
  #
98
86
  # @param include_placeholders [Boolean] whether to include placeholder users (default: false)
99
- # @return [Array<Types::UserItem>] an array of UserItem objects containing user details
100
- # @example
101
- # user.all
102
- # #=> [#<Types::UserItem id: 1, name: "John Doe", email: "john@example.com", ...>, ...]
87
+ # @return [Array<Hash>] an array of hashes containing user details
103
88
  def all(include_placeholders: false)
104
89
  users = @conn.get("search/all", term: "%").body
105
90
  users
106
91
  .select { |user| user["ResultType"] == "User" }
107
92
  .reject { |user| !include_placeholders && user["ImageUrl"] == "/i/userplaceholder" }
108
93
  .map do |user|
109
- Types::UserItem.new(
94
+ {
110
95
  id: user["Id"],
111
96
  name: user["Name"],
112
97
  email: user["Email"],
113
98
  position: user["Description"],
114
99
  image_url: user["ImageUrl"]
115
- )
100
+ }
116
101
  end
117
102
  end
118
103
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bloomy
4
- VERSION = "0.11.5"
4
+ VERSION = "0.12.0"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bloomy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.5
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Franccesco Orozco
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-01-23 00:00:00.000000000 Z
10
+ date: 2025-02-19 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: faraday
@@ -64,9 +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/types/items.rb
68
67
  - lib/bloomy/utils/get_user_id.rb
69
- - lib/bloomy/utils/plugin_loader.rb
70
68
  - lib/bloomy/version.rb
71
69
  - sig/bloomy.rbs
72
70
  homepage: https://github.com/franccesco/bloomy
@@ -1,119 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bloomy
4
- module Types
5
- TodoItem = Struct.new(
6
- :id,
7
- :title,
8
- :notes_url,
9
- :due_date,
10
- :created_at,
11
- :completed_at,
12
- :status,
13
- :user_name,
14
- :user_id,
15
- keyword_init: true
16
- )
17
-
18
- HeadlineItem = Struct.new(
19
- :id,
20
- :title,
21
- :notes_url,
22
- :meeting_details,
23
- :owner_details,
24
- :archived,
25
- :created_at,
26
- :closed_at,
27
- keyword_init: true
28
- )
29
-
30
- MeetingItem = Struct.new(
31
- :id,
32
- :title,
33
- keyword_init: true
34
- )
35
-
36
- MeetingDetails = Struct.new(
37
- :id,
38
- :title,
39
- :attendees,
40
- :issues,
41
- :todos,
42
- :metrics,
43
- keyword_init: true
44
- )
45
-
46
- MetricItem = Struct.new(
47
- :id,
48
- :title,
49
- :target,
50
- :operator,
51
- :format,
52
- :user_id,
53
- :user_name,
54
- :admin_id,
55
- :admin_name,
56
- keyword_init: true
57
- )
58
-
59
- UserItem = Struct.new(
60
- :id,
61
- :name,
62
- :image_url,
63
- :email,
64
- :description,
65
- :organization_id,
66
- :position,
67
- :direct_reports,
68
- :positions,
69
- keyword_init: true
70
- )
71
-
72
- GoalItem = Struct.new(
73
- :id,
74
- :title,
75
- :created_at,
76
- :due_date,
77
- :status,
78
- :meeting_id,
79
- :meeting_title,
80
- :user_id,
81
- :user_name,
82
- keyword_init: true
83
- )
84
-
85
- IssueItem = Struct.new(
86
- :id,
87
- :title,
88
- :notes_url,
89
- :created_at,
90
- :completed_at,
91
- :meeting_id,
92
- :meeting_title,
93
- :user_id,
94
- :user_name,
95
- keyword_init: true
96
- )
97
-
98
- WeekItem = Struct.new(
99
- :id,
100
- :week_number,
101
- :week_start,
102
- :week_end,
103
- keyword_init: true
104
- )
105
-
106
- ScorecardItem = Struct.new(
107
- :id,
108
- :measurable_id,
109
- :accountable_user_id,
110
- :title,
111
- :target,
112
- :value,
113
- :week,
114
- :week_id,
115
- :updated_at,
116
- keyword_init: true
117
- )
118
- end
119
- end
@@ -1,28 +0,0 @@
1
- module Bloomy
2
- module Utilities
3
- module Plugin
4
- # A collection of registered plugins.
5
- @plugins = []
6
-
7
- class << self
8
- # Registers a plugin module.
9
- #
10
- # @param plugin_module [Module] The plugin module to register.
11
- # @return [void]
12
- def register(plugin_module)
13
- @plugins << plugin_module
14
- end
15
-
16
- # Applies all registered plugins to the given client.
17
- #
18
- # @param client [Object] The client to which the plugins will be applied.
19
- # @return [void]
20
- def apply(client)
21
- @plugins.each do |plugin|
22
- plugin.apply(client)
23
- end
24
- end
25
- end
26
- end
27
- end
28
- end