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 +4 -4
- data/lib/bloomy/client.rb +0 -5
- data/lib/bloomy/operations/goals.rb +14 -14
- data/lib/bloomy/operations/headlines.rb +23 -23
- data/lib/bloomy/operations/issues.rb +9 -9
- data/lib/bloomy/operations/meetings.rb +22 -24
- data/lib/bloomy/operations/scorecard.rb +10 -10
- data/lib/bloomy/operations/todos.rb +16 -16
- data/lib/bloomy/operations/users.rb +17 -32
- data/lib/bloomy/version.rb +1 -1
- metadata +2 -4
- data/lib/bloomy/types/items.rb +0 -119
- data/lib/bloomy/utils/plugin_loader.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7bdff815414812cb7824504342fb4e3b12a2bf7e34b9780275fc1e598c4101dc
|
4
|
+
data.tar.gz: '0687ba4239c6e4fbcc03d0e6e0405f18488705fd83b95014e7b70f8c1ad06c51'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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<
|
23
|
-
# - An array of
|
24
|
-
# - A hash with :active and :archived arrays of
|
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
|
-
# #=> [
|
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: [
|
33
|
-
# archived: [
|
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
|
-
|
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 [
|
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
|
-
|
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<
|
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
|
-
|
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 [
|
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
|
-
|
27
|
+
{
|
28
28
|
id: response.body["Id"],
|
29
29
|
title: response.body["Name"],
|
30
|
-
owner_details:
|
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 [
|
50
|
-
#
|
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
|
-
|
55
|
+
{
|
56
56
|
id: response.body["Id"],
|
57
57
|
title: response.body["Name"],
|
58
58
|
notes_url: response.body["DetailsUrl"],
|
59
|
-
meeting_details:
|
59
|
+
meeting_details: {
|
60
60
|
id: response.body["OriginId"],
|
61
61
|
title: response.body["Origin"]
|
62
|
-
|
63
|
-
owner_details:
|
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<
|
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
|
-
#
|
89
|
+
# {
|
90
90
|
# id: 1,
|
91
91
|
# title: "Headline Title",
|
92
|
-
# meeting_details:
|
93
|
-
# owner_details:
|
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
|
-
|
112
|
+
{
|
113
113
|
id: headline["Id"],
|
114
114
|
title: headline["Name"],
|
115
|
-
meeting_details:
|
115
|
+
meeting_details: {
|
116
116
|
id: headline["OriginId"],
|
117
117
|
title: headline["Origin"]
|
118
|
-
|
119
|
-
owner_details:
|
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 [
|
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
|
-
|
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<
|
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
|
-
|
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 [
|
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
|
-
|
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|
|
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|
|
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
|
-
|
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
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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
|
-
|
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
|
132
|
-
|
133
|
-
id: meeting
|
134
|
-
title: meeting
|
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 [
|
22
|
+
# @return [Hash] a hash containing current week details
|
23
23
|
# @example
|
24
24
|
# client.scorecard.current_week
|
25
|
-
# #=>
|
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
|
-
|
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<
|
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
|
-
|
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
|
84
|
-
scorecards.select! { |scorecard| scorecard
|
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
|
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<
|
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
|
-
# #=> [
|
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
|
-
|
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 [
|
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
|
-
# #=>
|
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
|
-
|
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 [
|
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
|
-
# #=>
|
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
|
-
|
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 [
|
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
|
-
# #=>
|
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
|
-
|
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 [
|
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 =
|
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
|
36
|
-
user_details
|
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<
|
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
|
-
|
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<
|
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
|
-
|
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<
|
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
|
-
|
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<
|
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
|
-
|
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
|
data/lib/bloomy/version.rb
CHANGED
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.
|
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-
|
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
|
data/lib/bloomy/types/items.rb
DELETED
@@ -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
|