bloomy 0.11.5 → 0.12.0

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