bloomy 0.1.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/README.md +19 -18
- data/bloomy.gemspec +1 -1
- data/lib/bloomy/client.rb +10 -7
- data/lib/bloomy/configuration.rb +2 -2
- data/lib/bloomy/operations/headlines.rb +107 -0
- data/lib/bloomy/operations/issues.rb +8 -4
- data/lib/bloomy/operations/scorecard.rb +106 -0
- data/lib/bloomy/operations/todos.rb +29 -0
- data/lib/bloomy/version.rb +1 -1
- metadata +6 -5
- data/lib/bloomy/operations/measurables.rb +0 -77
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 492d10b82ab6034c0113b74c8d70352ef604039018f9fcfeca60924ded9414da
|
4
|
+
data.tar.gz: 2ff5fe5f2e515ee6949ed33caaa67112a24caf47a07cada9c2dfaf88edceaedd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7414ba3b18b68878812929e5b82ce23253051d1f04a1ee2dbfcec418871db4255c44253d7497b6305cf86b7b60398affe0eade73bd16838fbb4a4d31bf2c1858
|
7
|
+
data.tar.gz: 067e2ab5d9b5f92a8da3c9489c8bb3318bd5818a9adeb21e867fd05e7357bf3e24ce986c8250c31128435e8e084ede3199aeee3cbab749fa1922cb4dbbd69ce7
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -1,28 +1,26 @@
|
|
1
1
|
# Bloomy
|
2
2
|
|
3
|
-
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/bloomy.svg)](https://badge.fury.io/rb/bloomy)[![RSpec Tests](https://github.com/franccesco/bloomy/actions/workflows/main.yml/badge.svg)](https://github.com/franccesco/bloomy/actions/workflows/main.yml) [![Deploy Docs](https://github.com/franccesco/bloomy/actions/workflows/deploy_docs.yml/badge.svg)](https://github.com/franccesco/bloomy/actions/workflows/deploy_docs.yml)
|
4
|
+
|
5
|
+
Bloomy is a Ruby library for interacting with the Bloom Growth API. It provides convenient methods for getting user details, todos, rocks, meetings, measurables, and issues.
|
4
6
|
|
5
7
|
## Installation
|
6
8
|
|
7
9
|
Add this line to your application's Gemfile:
|
8
10
|
|
9
11
|
```ruby
|
10
|
-
|
12
|
+
bundle add bloomy
|
11
13
|
```
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
```sh
|
16
|
-
bundle install
|
17
|
-
```
|
18
|
-
|
19
|
-
Or install it yourself as:
|
15
|
+
Or install it to your system:
|
20
16
|
|
21
17
|
```sh
|
22
18
|
gem install bloomy
|
23
19
|
```
|
24
20
|
|
25
|
-
##
|
21
|
+
## Get Started
|
22
|
+
|
23
|
+
You can find the [full docs here](https://franccesco.github.io/bloomy/) but here's a quick overview to get you started.
|
26
24
|
|
27
25
|
### Initialize the Configuration
|
28
26
|
|
@@ -36,20 +34,23 @@ config = Bloomy::Configuration.new
|
|
36
34
|
|
37
35
|
### Configure the API Key
|
38
36
|
|
39
|
-
You can configure the API key using your username and password. Optionally, you can store the API key locally for future use.
|
37
|
+
You can configure the API key using your username and password. Optionally, you can store the API key locally under `~/.bloomy/config.yaml` for future use.
|
40
38
|
|
41
39
|
```ruby
|
42
40
|
config.configure_api_key("your_username", "your_password", store_key: true)
|
43
41
|
```
|
44
42
|
|
45
|
-
|
43
|
+
You can also set an `BG_API_KEY` environment variable and it will be loaded automatically for you once you initialize a client. A configuration is useful if you plan to use a fixed API key for your operations. However, you can also pass an API key when initializing a client without doing any configuration.
|
46
44
|
|
47
45
|
## Client Initialization
|
48
46
|
|
49
47
|
Once the configuration is set up, you can initialize the client. The client provides access to various features such as managing users, todos, rocks, meetings, measurables, and issues.
|
50
48
|
|
49
|
+
> [!NOTE]
|
50
|
+
> Passing an API key is entirely optional and only useful if you plan to use different API keys to manage different organizations. This will bypass the regular configuration process.
|
51
|
+
|
51
52
|
```ruby
|
52
|
-
client = Bloomy::Client.new
|
53
|
+
client = Bloomy::Client.new(api_key: "abc...")
|
53
54
|
```
|
54
55
|
|
55
56
|
## Using Client Features
|
@@ -102,16 +103,16 @@ rocks = client.rock.list
|
|
102
103
|
new_rock = client.rock.create(title: "New Rock", meeting_id: 1)
|
103
104
|
```
|
104
105
|
|
105
|
-
###
|
106
|
+
### Scorecard Management
|
106
107
|
|
107
108
|
To interact with measurable-related features:
|
108
109
|
|
109
110
|
```ruby
|
110
|
-
# Get
|
111
|
-
|
111
|
+
# Get user scorecard
|
112
|
+
user_scorecard = client.scorecard.list(user_id: 1)
|
112
113
|
|
113
|
-
# Get
|
114
|
-
|
114
|
+
# Get a meeting scorecard
|
115
|
+
meeting_scorecard = client.scorecard.list(meeting_id: 1)
|
115
116
|
```
|
116
117
|
|
117
118
|
### Issue Management
|
data/bloomy.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.summary = "Manage your Bloom Growth account from the command line."
|
12
12
|
spec.homepage = "https://github.com/franccesco/bloomy"
|
13
13
|
spec.required_ruby_version = ">= 2.6.0"
|
14
|
-
spec.licenses = ["
|
14
|
+
spec.licenses = ["Apache-2.0"]
|
15
15
|
|
16
16
|
# spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
|
17
17
|
|
data/lib/bloomy/client.rb
CHANGED
@@ -5,14 +5,15 @@ require_relative "operations/users"
|
|
5
5
|
require_relative "operations/todos"
|
6
6
|
require_relative "operations/rocks"
|
7
7
|
require_relative "operations/meetings"
|
8
|
-
require_relative "operations/
|
8
|
+
require_relative "operations/scorecard"
|
9
9
|
require_relative "operations/issues"
|
10
|
+
require_relative "operations/headlines"
|
10
11
|
|
11
12
|
module Bloomy
|
12
13
|
# The Client class is the main entry point for interacting with the Bloomy API.
|
13
|
-
# It provides methods for managing
|
14
|
+
# It provides methods for managing Bloom Growth features.
|
14
15
|
class Client
|
15
|
-
attr_reader :configuration, :user, :todo, :rock, :meeting, :
|
16
|
+
attr_reader :configuration, :user, :todo, :rock, :meeting, :scorecard, :issue, :headline
|
16
17
|
|
17
18
|
# Initializes a new Client instance
|
18
19
|
#
|
@@ -21,23 +22,25 @@ module Bloomy
|
|
21
22
|
# client.meetings.list
|
22
23
|
# client.user.details
|
23
24
|
# client.meeting.delete(id)
|
24
|
-
def initialize
|
25
|
-
@configuration = Configuration.new
|
25
|
+
def initialize(api_key = nil)
|
26
|
+
@configuration = Configuration.new unless api_key
|
27
|
+
@api_key = api_key || @configuration.api_key
|
26
28
|
@base_url = "https://app.bloomgrowth.com/api/v1"
|
27
29
|
@conn = Faraday.new(url: @base_url) do |faraday|
|
28
30
|
faraday.response :json
|
29
31
|
faraday.adapter Faraday.default_adapter
|
30
32
|
faraday.headers["Accept"] = "*/*"
|
31
33
|
faraday.headers["Content-Type"] = "application/json"
|
32
|
-
faraday.headers["Authorization"] = "Bearer #{
|
34
|
+
faraday.headers["Authorization"] = "Bearer #{@api_key}"
|
33
35
|
end
|
34
36
|
@user = User.new(@conn)
|
35
37
|
@user_id = @user.default_user_id
|
36
38
|
@todo = Todo.new(@conn, @user_id)
|
37
39
|
@rock = Rock.new(@conn, @user_id)
|
38
40
|
@meeting = Meeting.new(@conn, @user_id)
|
39
|
-
@
|
41
|
+
@scorecard = Scorecard.new(@conn, @user_id)
|
40
42
|
@issue = Issue.new(@conn, @user_id)
|
43
|
+
@headline = Headline.new(@conn, @user_id)
|
41
44
|
end
|
42
45
|
end
|
43
46
|
end
|
data/lib/bloomy/configuration.rb
CHANGED
@@ -11,11 +11,11 @@ module Bloomy
|
|
11
11
|
|
12
12
|
# Initializes a new Configuration instance
|
13
13
|
#
|
14
|
-
# @param [String, nil]
|
14
|
+
# @param [String, nil] api_key Pass an optional API key
|
15
15
|
# @example
|
16
16
|
# config = Bloomy::Configuration.new(api_key)
|
17
17
|
def initialize(api_key = nil)
|
18
|
-
@api_key = api_key || ENV["
|
18
|
+
@api_key = api_key || ENV["BG_API_KEY"] || load_api_key
|
19
19
|
end
|
20
20
|
|
21
21
|
# Configures the API key using the provided username and password
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Headline
|
4
|
+
# Initializes a new headline instance
|
5
|
+
#
|
6
|
+
# @param conn [Object] the connection object to interact with the API
|
7
|
+
# @param user_id [Integer] the ID of the user
|
8
|
+
def initialize(conn, user_id)
|
9
|
+
@conn = conn
|
10
|
+
@user_id = user_id
|
11
|
+
end
|
12
|
+
|
13
|
+
# Creates a new headline
|
14
|
+
#
|
15
|
+
# @param meeting_id [Integer] the ID of the meeting
|
16
|
+
# @param title [String] the title of the headline
|
17
|
+
# @param owner_id [Integer] the ID of the owner
|
18
|
+
# @param notes [String] additional notes for the headline
|
19
|
+
# @return [Hash] the created headline details
|
20
|
+
def create(meeting_id, title, owner_id: @user_id, notes: nil)
|
21
|
+
response = @conn.post("/api/v1/L10/#{meeting_id}/headlines",
|
22
|
+
{title: title, ownerId: owner_id, notes: notes}.to_json)
|
23
|
+
raise "Failed to create headline" unless response.status == 200
|
24
|
+
|
25
|
+
{
|
26
|
+
id: response.body["Id"],
|
27
|
+
title: response.body["Title"],
|
28
|
+
owner_id: response.body["OwnerId"],
|
29
|
+
notes: response.body["Notes"]
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
# Updates a headline
|
34
|
+
#
|
35
|
+
# @param headline_id [Integer] the ID of the headline to update
|
36
|
+
# @param title [String] the new title of the headline
|
37
|
+
# @return [Hash] the updated headline details
|
38
|
+
def update(headline_id, title)
|
39
|
+
response = @conn.put("/api/v1/headline/#{headline_id}", {title: title}.to_json)
|
40
|
+
raise "Failed to update headline" unless response.status == 200
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
# Get headline details
|
45
|
+
#
|
46
|
+
# @param headline_id [Integer] the ID of the headline
|
47
|
+
# @return [Hash] the details of the headline
|
48
|
+
def details(headline_id)
|
49
|
+
response = @conn.get("/api/v1/headline/#{headline_id}?Include_Origin=true")
|
50
|
+
raise "Failed to get headline details" unless response.status == 200
|
51
|
+
|
52
|
+
{
|
53
|
+
id: response.body["Id"],
|
54
|
+
title: response.body["Name"],
|
55
|
+
meeting_details: {
|
56
|
+
id: response.body["OriginId"],
|
57
|
+
name: response.body["Origin"]
|
58
|
+
},
|
59
|
+
owner_details: {
|
60
|
+
id: response.body["Owner"]["Id"],
|
61
|
+
name: response.body["Owner"]["Name"]
|
62
|
+
},
|
63
|
+
archived: response.body["Archived"],
|
64
|
+
created_at: response.body["CreateTime"],
|
65
|
+
closed_at: response.body["CloseTime"]
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
# Get user headlines
|
70
|
+
#
|
71
|
+
# @param user_id [Integer] the ID of the user
|
72
|
+
# @return [Array] the list of headlines for the user
|
73
|
+
def user_headlines(user_id: @user_id)
|
74
|
+
response = @conn.get("/api/v1/headline/users/#{user_id}")
|
75
|
+
raise "Failed to list headlines" unless response.status == 200
|
76
|
+
response.body.map do |headline|
|
77
|
+
{
|
78
|
+
id: headline["Id"],
|
79
|
+
title: headline["Name"],
|
80
|
+
meeting_details: {
|
81
|
+
id: headline["OriginId"],
|
82
|
+
name: headline["Origin"]
|
83
|
+
},
|
84
|
+
owner_details: {
|
85
|
+
id: headline["Owner"]["Id"],
|
86
|
+
name: headline["Owner"]["Name"]
|
87
|
+
},
|
88
|
+
archived: headline["Archived"],
|
89
|
+
created_at: headline["CreateTime"],
|
90
|
+
closed_at: headline["CloseTime"]
|
91
|
+
}
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Deletes a headline
|
96
|
+
#
|
97
|
+
# @param meeting_id [Integer] the ID of the meeting
|
98
|
+
# @param headline_id [Integer] the ID of the headline to delete
|
99
|
+
# @return [Boolean] true if the deletion was successful
|
100
|
+
def delete(meeting_id, headline_id)
|
101
|
+
response = @conn.delete("/api/v1/L10/#{meeting_id}/headlines/#{headline_id}")
|
102
|
+
|
103
|
+
# Raise an issue if response.status != 200
|
104
|
+
raise "Failed to delete headline" unless response.status == 200
|
105
|
+
true
|
106
|
+
end
|
107
|
+
end
|
@@ -74,17 +74,21 @@ class Issue
|
|
74
74
|
|
75
75
|
# Creates a new issue
|
76
76
|
#
|
77
|
-
# @param
|
77
|
+
# @param title [String] the title of the new issue
|
78
78
|
# @param meeting_id [Integer] the ID of the meeting associated with the issue
|
79
79
|
# @return [Hash] a hash containing the new issue's ID and title
|
80
80
|
# @example
|
81
81
|
# issue.create("New Issue", 456)
|
82
82
|
# #=> { id: 789, title: "New Issue" }
|
83
|
-
def create(
|
84
|
-
response = @conn.post("issues/create", {title:
|
83
|
+
def create(meeting_id:, title:, user_id: @user_id, notes: nil)
|
84
|
+
response = @conn.post("issues/create", {title: title, meetingid: meeting_id, ownerid: user_id, notes: notes}.to_json)
|
85
85
|
{
|
86
86
|
id: response.body["Id"],
|
87
|
-
|
87
|
+
meeting_id: response.body["OriginId"],
|
88
|
+
meeting_title: response.body["Origin"],
|
89
|
+
title: response.body["Name"],
|
90
|
+
user_id: response.body["Owner"]["Id"],
|
91
|
+
details_url: response.body["DetailsUrl"]
|
88
92
|
}
|
89
93
|
end
|
90
94
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
# Class to handle all the operations related to scorecards
|
6
|
+
# @note
|
7
|
+
# This class is already initialized via the client and usable as `client.scorecard.method`
|
8
|
+
class Scorecard
|
9
|
+
# Initializes a new Scorecard instance
|
10
|
+
#
|
11
|
+
# @param conn [Object] the connection object to interact with the API
|
12
|
+
# @param user_id [Integer] the ID of the user
|
13
|
+
def initialize(conn, user_id)
|
14
|
+
@conn = conn
|
15
|
+
@user_id = user_id
|
16
|
+
end
|
17
|
+
|
18
|
+
# Retrieves the current week details
|
19
|
+
#
|
20
|
+
# @return [Hash] a hash containing current week details
|
21
|
+
# @example
|
22
|
+
# client.scorecard.current_week
|
23
|
+
# #=> { id: 123, week_number: 24, week_start: "2024-06-10", week_end: "2024-06-16" }
|
24
|
+
def current_week
|
25
|
+
response = @conn.get("weeks/current").body
|
26
|
+
{
|
27
|
+
id: response["Id"],
|
28
|
+
week_number: response["ForWeekNumber"],
|
29
|
+
week_start: response["LocalDate"]["Date"],
|
30
|
+
week_end: response["ForWeek"]
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
# Retrieves the scorecards for a user or a meeting.
|
35
|
+
#
|
36
|
+
# @param user_id [Integer, nil] the ID of the user (defaults to initialized user_id)
|
37
|
+
# @param meeting_id [Integer, nil] the ID of the meeting
|
38
|
+
# @param show_empty [Boolean] whether to include scores with nil values (default: false)
|
39
|
+
# @param week_offset [Integer, nil] offset for the week number to filter scores
|
40
|
+
# @raise [ArgumentError] if both `user_id` and `meeting_id` are provided
|
41
|
+
# @return [Array<Hash>] an array of hashes containing scorecard details
|
42
|
+
# @example
|
43
|
+
# # Fetch scorecards for the current user
|
44
|
+
# client.scorecard.list
|
45
|
+
#
|
46
|
+
# # Fetch scorecards for a specific user
|
47
|
+
# client.scorecard.list(user_id: 42)
|
48
|
+
#
|
49
|
+
# # Fetch scorecards for a specific meeting
|
50
|
+
# client.scorecard.list(meeting_id: 99)
|
51
|
+
def list(user_id: nil, meeting_id: nil, show_empty: false, week_offset: nil)
|
52
|
+
if user_id && meeting_id
|
53
|
+
raise ArgumentError, "Please provide either `user_id` or `meeting_id`, not both."
|
54
|
+
end
|
55
|
+
|
56
|
+
if meeting_id
|
57
|
+
response = @conn.get("scorecard/meeting/#{meeting_id}").body
|
58
|
+
else
|
59
|
+
user_id ||= @user_id
|
60
|
+
response = @conn.get("scorecard/user/#{user_id}").body
|
61
|
+
end
|
62
|
+
|
63
|
+
scorecards = response["Scores"].map do |scorecard|
|
64
|
+
{
|
65
|
+
id: scorecard["Id"],
|
66
|
+
measurable_id: scorecard["MeasurableId"],
|
67
|
+
accountable_user_id: scorecard["AccountableUserId"],
|
68
|
+
title: scorecard["MeasurableName"],
|
69
|
+
target: scorecard["Target"],
|
70
|
+
value: scorecard["Measured"],
|
71
|
+
week: scorecard["Week"],
|
72
|
+
updated_at: scorecard["DateEntered"]
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
if week_offset
|
77
|
+
week_data = current_week
|
78
|
+
week_id = week_data[:week_number] - week_offset
|
79
|
+
scorecards.select! { |scorecard| scorecard[:week] == week_id }
|
80
|
+
end
|
81
|
+
|
82
|
+
scorecards.select! { |scorecard| scorecard[:value] || show_empty } unless show_empty
|
83
|
+
scorecards
|
84
|
+
end
|
85
|
+
|
86
|
+
# Updates the score for a measurable item for a specific week.
|
87
|
+
#
|
88
|
+
# @param measurable_id [Integer] the ID of the measurable item.
|
89
|
+
# @param score [Numeric] the score to be assigned to the measurable item.
|
90
|
+
# @param week_offset [Integer] the number of weeks to offset from the current week (default is 0).
|
91
|
+
# @return [Boolean] true if the score was successfully updated, false otherwise.
|
92
|
+
# @example
|
93
|
+
# client.scorecard.score(measurable_id: 123, score: 5)
|
94
|
+
# #=> true
|
95
|
+
# @note
|
96
|
+
# The `week_offset` parameter is useful when updating scores for previous weeks.
|
97
|
+
# For example, to update the score for the previous week, you can set `week_offset` to 1.
|
98
|
+
# To update a future week's score, you can set `week_offset` to a negative value.
|
99
|
+
def score(measurable_id:, score:, week_offset: 0)
|
100
|
+
week_data = current_week
|
101
|
+
week_id = week_data[:week_number] - week_offset
|
102
|
+
|
103
|
+
response = @conn.put("measurables/#{measurable_id}/week/#{week_id}", {value: score}.to_json)
|
104
|
+
response.success?
|
105
|
+
end
|
106
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "date"
|
4
|
+
|
3
5
|
# Class to handle all the operations related to todos
|
4
6
|
class Todo
|
5
7
|
# Initializes a new Todo instance
|
@@ -67,4 +69,31 @@ class Todo
|
|
67
69
|
response = @conn.post("/api/v1/todo/#{todo_id}/complete?status=true")
|
68
70
|
{status: response.status}
|
69
71
|
end
|
72
|
+
|
73
|
+
# Updates an existing todo
|
74
|
+
#
|
75
|
+
# @param todo_id [Integer] the ID of the todo to update
|
76
|
+
# @param title [String, nil] the new title of the todo (optional)
|
77
|
+
# @param due_date [String, nil] the new due date of the todo (optional)
|
78
|
+
# @return [Hash] a hash containing the updated todo's details
|
79
|
+
# @example
|
80
|
+
# todo.update(1, title: "Updated Todo", due_date: "2024-11-01T01:41:41.528Z")
|
81
|
+
# #=> { id: 1, title: "Updated Todo", due_date: "2024-11-01T01:41:41.528Z", ... }
|
82
|
+
def update(todo_id:, title: nil, due_date: nil)
|
83
|
+
payload = {}
|
84
|
+
payload[:title] = title if title
|
85
|
+
payload[:dueDate] = due_date if due_date
|
86
|
+
|
87
|
+
raise ArgumentError, "At least one field must be provided" if payload.empty?
|
88
|
+
|
89
|
+
response = @conn.put("/api/v1/todo/#{todo_id}", payload.to_json)
|
90
|
+
raise "Failed to update todo. Status: #{response.status}" unless response.status == 200
|
91
|
+
|
92
|
+
{
|
93
|
+
id: todo_id,
|
94
|
+
title: title,
|
95
|
+
due_date: due_date,
|
96
|
+
updated_at: DateTime.now.to_s
|
97
|
+
}
|
98
|
+
end
|
70
99
|
end
|
data/lib/bloomy/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bloomy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Franccesco Orozco
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -57,17 +57,18 @@ files:
|
|
57
57
|
- lib/bloomy.rb
|
58
58
|
- lib/bloomy/client.rb
|
59
59
|
- lib/bloomy/configuration.rb
|
60
|
+
- lib/bloomy/operations/headlines.rb
|
60
61
|
- lib/bloomy/operations/issues.rb
|
61
|
-
- lib/bloomy/operations/measurables.rb
|
62
62
|
- lib/bloomy/operations/meetings.rb
|
63
63
|
- lib/bloomy/operations/rocks.rb
|
64
|
+
- lib/bloomy/operations/scorecard.rb
|
64
65
|
- lib/bloomy/operations/todos.rb
|
65
66
|
- lib/bloomy/operations/users.rb
|
66
67
|
- lib/bloomy/version.rb
|
67
68
|
- sig/bloomy.rbs
|
68
69
|
homepage: https://github.com/franccesco/bloomy
|
69
70
|
licenses:
|
70
|
-
-
|
71
|
+
- Apache-2.0
|
71
72
|
metadata:
|
72
73
|
homepage_uri: https://github.com/franccesco/bloomy
|
73
74
|
rubygems_mfa_required: 'true'
|
@@ -86,7 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
86
87
|
- !ruby/object:Gem::Version
|
87
88
|
version: '0'
|
88
89
|
requirements: []
|
89
|
-
rubygems_version: 3.5.
|
90
|
+
rubygems_version: 3.5.17
|
90
91
|
signing_key:
|
91
92
|
specification_version: 4
|
92
93
|
summary: Manage your Bloom Growth account from the command line.
|
@@ -1,77 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "json"
|
4
|
-
|
5
|
-
# Class to handle all the operations related to measurables
|
6
|
-
# @note
|
7
|
-
# This class is already initialized via the client and usable as `client.measurable.method`
|
8
|
-
class Measurable
|
9
|
-
# Initializes a new Measurable instance
|
10
|
-
#
|
11
|
-
# @param conn [Object] the connection object to interact with the API
|
12
|
-
# @param user_id [Integer] the ID of the user
|
13
|
-
def initialize(conn, user_id)
|
14
|
-
@conn = conn
|
15
|
-
@user_id = user_id
|
16
|
-
end
|
17
|
-
|
18
|
-
# Retrieves the current week details
|
19
|
-
#
|
20
|
-
# @return [Hash] a hash containing current week details
|
21
|
-
# @example
|
22
|
-
# client.measurable.current_week
|
23
|
-
# #=> { id: 123, week_number: 24, week_start: "2024-06-10", week_end: "2024-06-16" }
|
24
|
-
def current_week
|
25
|
-
response = @conn.get("weeks/current").body
|
26
|
-
{
|
27
|
-
id: response["Id"],
|
28
|
-
week_number: response["ForWeekNumber"],
|
29
|
-
week_start: response["LocalDate"]["Date"],
|
30
|
-
week_end: response["ForWeek"]
|
31
|
-
}
|
32
|
-
end
|
33
|
-
|
34
|
-
# Retrieves the scorecard for the user
|
35
|
-
#
|
36
|
-
# @param current_week_only [Boolean] whether to include only the current week's scores (default: true)
|
37
|
-
# @param show_empty [Boolean] whether to include scores with nil values (default: true)
|
38
|
-
# @return [Array<Hash>] an array of hashes containing scorecard details
|
39
|
-
# @example
|
40
|
-
# client.measurable.scorecard
|
41
|
-
# #=> [{ id: 123, title: "Sales", target: 100, value: 80, updated_at: "2024-06-12", week_number: 24 }, ...]
|
42
|
-
def scorecard(current_week_only: true, show_empty: true)
|
43
|
-
response = @conn.get("scorecard/user/mine").body
|
44
|
-
scorecards = response["Scores"].map do |scorecard|
|
45
|
-
{
|
46
|
-
id: scorecard["Id"],
|
47
|
-
title: scorecard["MeasurableName"],
|
48
|
-
target: scorecard["Target"],
|
49
|
-
value: scorecard["Measured"],
|
50
|
-
updated_at: scorecard["DateEntered"],
|
51
|
-
week_number: scorecard["ForWeek"]
|
52
|
-
}
|
53
|
-
end
|
54
|
-
|
55
|
-
if current_week_only
|
56
|
-
week_id = current_week[:week_number]
|
57
|
-
scorecards.select do |scorecard|
|
58
|
-
scorecard[:week_number] == week_id && (show_empty || scorecard[:value].nil?)
|
59
|
-
end
|
60
|
-
else
|
61
|
-
scorecards.select { |scorecard| show_empty || scorecard[:value].nil? }
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
# Updates a scorecard with a new measured value
|
66
|
-
#
|
67
|
-
# @param scorecard_id [Integer] the ID of the scorecard to update
|
68
|
-
# @param measured [Numeric] the new measured value
|
69
|
-
# @return [Boolean] true if the operation was successful, false otherwise
|
70
|
-
# @example
|
71
|
-
# client.measurable.update(1, 85)
|
72
|
-
# #=> true
|
73
|
-
def update(scorecard_id, measured)
|
74
|
-
response = @conn.put("scores/#{scorecard_id}", {value: measured}.to_json).status
|
75
|
-
response == 200
|
76
|
-
end
|
77
|
-
end
|