bloomy 0.1.1 → 0.3.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: b0d0f6f6172769244a6783a916bebd1543662f84f6e53af17437c2f09484f1cf
4
- data.tar.gz: 7ad965fcfbcac1501e16c2431a2e91c88f16f5854ea3b3be9eebdaf2ec222baf
3
+ metadata.gz: 787640980ef91fe249c30313f21be2230cc0671de398f714f38e1200fc104a6f
4
+ data.tar.gz: 6c2bb8a0b8e78371674fe5f18bc66ab44d91629d03484863442f4d3953c59707
5
5
  SHA512:
6
- metadata.gz: 37ef8b9fb6ee8bb2f13e8ba0481a0b4ea40d1c24fe944df8dae8dbbcf37c8734f7d05c2a3267699466e2a8955e4f0424fe73ba80e1e3e25ca3b9848e6aae045d
7
- data.tar.gz: bb9965e3a7701ba7d0fd3ec5566f1e516e172cde06d6d7fe65c294e4f6be5da88fde0cedba512f5ec93cc95d8cf9289fbc15cc94e004999ec1c9361d7a7e6de6
6
+ metadata.gz: da4639a0e6e6e633f972d31df14818ed64e3b690f565c7308f49ae53a08c061b74d944f4d7088f8ab024ed54b4301d4186a9747802c34b24c2b7f476afdab77a
7
+ data.tar.gz: 6f4674b867eec7d42f5735c1c7a6725ff173ee2c8f7a1c8b22ef329ed8aa9f384e40632235a578e4d1efe654bccdda75255abbc9ab35313c11375d1815944dcb
data/.rubocop.yml CHANGED
@@ -25,3 +25,6 @@ Naming/AccessorMethodName:
25
25
 
26
26
  Gemspec/DevelopmentDependencies:
27
27
  Enabled: false
28
+
29
+ Style/StringLiterals:
30
+ EnforcedStyle: double_quotes
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Bloomy
2
- [![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)
2
+
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)
3
4
 
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.
5
6
 
@@ -8,22 +9,18 @@ Bloomy is a Ruby library for interacting with the Bloom Growth API. It provides
8
9
  Add this line to your application's Gemfile:
9
10
 
10
11
  ```ruby
11
- gem 'bloomy'
12
- ```
13
-
14
- And then execute:
15
-
16
- ```sh
17
- bundle install
12
+ bundle add bloomy
18
13
  ```
19
14
 
20
- Or install it yourself as:
15
+ Or install it to your system:
21
16
 
22
17
  ```sh
23
18
  gem install bloomy
24
19
  ```
25
20
 
26
- ## Configuration
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.
27
24
 
28
25
  ### Initialize the Configuration
29
26
 
@@ -106,16 +103,16 @@ rocks = client.rock.list
106
103
  new_rock = client.rock.create(title: "New Rock", meeting_id: 1)
107
104
  ```
108
105
 
109
- ### Measurable Management
106
+ ### Scorecard Management
110
107
 
111
108
  To interact with measurable-related features:
112
109
 
113
110
  ```ruby
114
- # Get current week details
115
- current_week = client.measurable.current_week
111
+ # Get user scorecard
112
+ user_scorecard = client.scorecard.list(user_id: 1)
116
113
 
117
- # Get the scorecard for the user
118
- scorecard = client.measurable.scorecard
114
+ # Get a meeting scorecard
115
+ meeting_scorecard = client.scorecard.list(meeting_id: 1)
119
116
  ```
120
117
 
121
118
  ### Issue Management
data/lib/bloomy/client.rb CHANGED
@@ -3,16 +3,17 @@
3
3
  require "faraday"
4
4
  require_relative "operations/users"
5
5
  require_relative "operations/todos"
6
- require_relative "operations/rocks"
6
+ require_relative "operations/goals"
7
7
  require_relative "operations/meetings"
8
- require_relative "operations/measurables"
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 users, todos, rocks, meetings, measurables, and issues.
14
+ # It provides methods for managing Bloom Growth features.
14
15
  class Client
15
- attr_reader :configuration, :user, :todo, :rock, :meeting, :measurable, :issue
16
+ attr_reader :configuration, :user, :todo, :goal, :meeting, :scorecard, :issue, :headline
16
17
 
17
18
  # Initializes a new Client instance
18
19
  #
@@ -35,10 +36,11 @@ module Bloomy
35
36
  @user = User.new(@conn)
36
37
  @user_id = @user.default_user_id
37
38
  @todo = Todo.new(@conn, @user_id)
38
- @rock = Rock.new(@conn, @user_id)
39
+ @goal = Goal.new(@conn, @user_id)
39
40
  @meeting = Meeting.new(@conn, @user_id)
40
- @measurable = Measurable.new(@conn, @user_id)
41
+ @scorecard = Scorecard.new(@conn, @user_id)
41
42
  @issue = Issue.new(@conn, @user_id)
43
+ @headline = Headline.new(@conn, @user_id)
42
44
  end
43
45
  end
44
46
  end
@@ -11,7 +11,7 @@ module Bloomy
11
11
 
12
12
  # Initializes a new Configuration instance
13
13
  #
14
- # @param [String, nil] optional_parameter Pass an optional API key
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)
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Class to handle all the operations related to goals
4
+ class Goal
5
+ # Initializes a new Goal instance
6
+ #
7
+ # @param conn [Object] the connection object to interact with the API
8
+ # @param user_id [Integer] the ID of the user
9
+ def initialize(conn, user_id)
10
+ @conn = conn
11
+ @user_id = user_id
12
+ end
13
+
14
+ # Lists all goals for a specific user
15
+ #
16
+ # @param user_id [Integer] the ID of the user (default is the initialized user ID)
17
+ # @param archived [Boolean] whether to include archived goals (default: false)
18
+ # @return [Array<Hash>] an array of hashes containing goal details or a hash with active and archived goals
19
+ # @example
20
+ # client.goal.list
21
+ # #=> [{ id: 1, title: "Complete project", created_at: "2024-06-10", ... }, ...]
22
+ def list(user_id: @user_id, archived: false)
23
+ active_goals = @conn.get("rocks/user/#{user_id}?include_origin=true").body.map do |goal|
24
+ {
25
+ id: goal["Id"],
26
+ title: goal["Name"],
27
+ created_at: goal["CreateTime"],
28
+ due_date: goal["DueDate"],
29
+ status: goal["Complete"] ? "Completed" : "Incomplete",
30
+ meeting_id: goal["Origins"].empty? ? nil : goal["Origins"][0]["Id"],
31
+ meeting_name: goal["Origins"].empty? ? nil : goal["Origins"][0]["Name"]
32
+ }
33
+ end
34
+
35
+ archived ? {active: active_goals, archived: get_archived_goals(user_id: @user_id)} : active_goals
36
+ end
37
+
38
+ # Creates a new goal
39
+ #
40
+ # @param title [String] the title of the new goal
41
+ # @param meeting_id [Integer] the ID of the meeting associated with the goal
42
+ # @param user_id [Integer] the ID of the user responsible for the goal (default: initialized user ID)
43
+ # @return [Hash] a hash containing the new goal's details
44
+ # @example
45
+ # client.goal.create(title: "New Goal", meeting_id: 1)
46
+ # #=> { goal_id: 1, title: "New Goal", meeting_id: 1, ... }
47
+ def create(title:, meeting_id:, user_id: @user_id)
48
+ payload = {title: title, accountableUserId: user_id}.to_json
49
+ response = @conn.post("/api/v1/L10/#{meeting_id}/rocks", payload).body
50
+ {
51
+ goal_id: response["Id"],
52
+ title: title,
53
+ meeting_id: meeting_id,
54
+ meeting_name: response["Origins"][0]["Name"],
55
+ user_id: user_id,
56
+ user_name: response["Owner"]["Name"],
57
+ created_at: DateTime.parse(response["CreateTime"])
58
+ }
59
+ end
60
+
61
+ # Deletes a goal
62
+ #
63
+ # @param goal_id [Integer] the ID of the goal to delete
64
+ # @return [Hash] a hash containing the status of the delete operation
65
+ # @example
66
+ # client.goal.delete(1)
67
+ # #=> { status: 200 }
68
+ def delete(goal_id)
69
+ response = @conn.delete("/api/v1/rocks/#{goal_id}")
70
+ {status: response.status}
71
+ end
72
+
73
+ # Updates a goal
74
+ #
75
+ # @param goal_id [Integer] the ID of the goal to update
76
+ # @param title [String] the new title of the goal
77
+ # @param accountable_user [Integer] the ID of the user responsible for the goal (default: initialized user ID)
78
+ # @return [Hash] a hash containing the status of the update operation
79
+ # @example
80
+ # client.goal.update(goal_id: 1, title: "Updated Goal")
81
+ # #=> { status: 200 }
82
+ def update(goal_id:, title:, accountable_user: @user_id)
83
+ payload = {title: title, accountableUserId: accountable_user}.to_json
84
+ response = @conn.put("/api/v1/rocks/#{goal_id}", payload)
85
+ {status: response.status}
86
+ end
87
+
88
+ private
89
+
90
+ # Retrieves all archived goals for a specific user (private method)
91
+ #
92
+ # @param user_id [Integer] the ID of the user (default is the initialized user ID)
93
+ # @return [Array<Hash>] an array of hashes containing archived goal details
94
+ # @example
95
+ # goal.send(:get_archived_goals)
96
+ # #=> [{ id: 1, title: "Archived Goal", created_at: "2024-06-10", ... }, ...]
97
+ def get_archived_goals(user_id: @user_id)
98
+ response = @conn.get("archivedrocks/user/#{user_id}").body
99
+ response.map do |goal|
100
+ {
101
+ id: goal["Id"],
102
+ title: goal["Name"],
103
+ created_at: goal["CreateTime"],
104
+ due_date: goal["DueDate"],
105
+ status: goal["Complete"] ? "Complete" : "Incomplete"
106
+ }
107
+ end
108
+ end
109
+ end
@@ -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 issue_title [String] the title of the new issue
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(issue_title, meeting_id)
84
- response = @conn.post("issues/create", {title: issue_title, meetingid: meeting_id}.to_json)
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
- title: response.body["Name"]
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bloomy
4
- VERSION = "0.1.1"
4
+ VERSION = "0.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bloomy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.0
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-06-19 00:00:00.000000000 Z
11
+ date: 2024-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -57,10 +57,11 @@ files:
57
57
  - lib/bloomy.rb
58
58
  - lib/bloomy/client.rb
59
59
  - lib/bloomy/configuration.rb
60
+ - lib/bloomy/operations/goals.rb
61
+ - lib/bloomy/operations/headlines.rb
60
62
  - lib/bloomy/operations/issues.rb
61
- - lib/bloomy/operations/measurables.rb
62
63
  - lib/bloomy/operations/meetings.rb
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
@@ -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.11
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
@@ -1,109 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Class to handle all the operations related to rocks
4
- class Rock
5
- # Initializes a new Rock instance
6
- #
7
- # @param conn [Object] the connection object to interact with the API
8
- # @param user_id [Integer] the ID of the user
9
- def initialize(conn, user_id)
10
- @conn = conn
11
- @user_id = user_id
12
- end
13
-
14
- # Lists all rocks for a specific user
15
- #
16
- # @param user_id [Integer] the ID of the user (default is the initialized user ID)
17
- # @param archived [Boolean] whether to include archived rocks (default: false)
18
- # @return [Array<Hash>] an array of hashes containing rock details or a hash with active and archived rocks
19
- # @example
20
- # client.rock.list
21
- # #=> [{ id: 1, title: "Complete project", created_at: "2024-06-10", ... }, ...]
22
- def list(user_id: @user_id, archived: false)
23
- active_rocks = @conn.get("rocks/user/#{user_id}?include_origin=true").body.map do |rock|
24
- {
25
- id: rock["Id"],
26
- title: rock["Name"],
27
- created_at: rock["CreateTime"],
28
- due_date: rock["DueDate"],
29
- status: rock["Complete"] ? "Completed" : "Incomplete",
30
- meeting_id: rock["Origins"].empty? ? nil : rock["Origins"][0]["Id"],
31
- meeting_name: rock["Origins"].empty? ? nil : rock["Origins"][0]["Name"]
32
- }
33
- end
34
-
35
- archived ? {active: active_rocks, archived: get_archived_rocks(user_id: @user_id)} : active_rocks
36
- end
37
-
38
- # Creates a new rock
39
- #
40
- # @param title [String] the title of the new rock
41
- # @param meeting_id [Integer] the ID of the meeting associated with the rock
42
- # @param user_id [Integer] the ID of the user responsible for the rock (default: initialized user ID)
43
- # @return [Hash] a hash containing the new rock's details
44
- # @example
45
- # client.rock.create(title: "New Rock", meeting_id: 1)
46
- # #=> { rock_id: 1, title: "New Rock", meeting_id: 1, ... }
47
- def create(title:, meeting_id:, user_id: @user_id)
48
- payload = {title: title, accountableUserId: user_id}.to_json
49
- response = @conn.post("/api/v1/L10/#{meeting_id}/rocks", payload).body
50
- {
51
- rock_id: response["Id"],
52
- title: title,
53
- meeting_id: meeting_id,
54
- meeting_name: response["Origins"][0]["Name"],
55
- user_id: user_id,
56
- user_name: response["Owner"]["Name"],
57
- created_at: DateTime.parse(response["CreateTime"])
58
- }
59
- end
60
-
61
- # Deletes a rock
62
- #
63
- # @param rock_id [Integer] the ID of the rock to delete
64
- # @return [Hash] a hash containing the status of the delete operation
65
- # @example
66
- # client.rock.delete(1)
67
- # #=> { status: 200 }
68
- def delete(rock_id)
69
- response = @conn.delete("/api/v1/rocks/#{rock_id}")
70
- {status: response.status}
71
- end
72
-
73
- # Updates a rock
74
- #
75
- # @param rock_id [Integer] the ID of the rock to update
76
- # @param title [String] the new title of the rock
77
- # @param accountable_user [Integer] the ID of the user responsible for the rock (default: initialized user ID)
78
- # @return [Hash] a hash containing the status of the update operation
79
- # @example
80
- # client.rock.update(rock_id: 1, title: "Updated Rock")
81
- # #=> { status: 200 }
82
- def update(rock_id:, title:, accountable_user: @user_id)
83
- payload = {title: title, accountableUserId: accountable_user}.to_json
84
- response = @conn.put("/api/v1/rocks/#{rock_id}", payload)
85
- {status: response.status}
86
- end
87
-
88
- private
89
-
90
- # Retrieves all archived rocks for a specific user (private method)
91
- #
92
- # @param user_id [Integer] the ID of the user (default is the initialized user ID)
93
- # @return [Array<Hash>] an array of hashes containing archived rock details
94
- # @example
95
- # rock.send(:get_archived_rocks)
96
- # #=> [{ id: 1, title: "Archived Rock", created_at: "2024-06-10", ... }, ...]
97
- def get_archived_rocks(user_id: @user_id)
98
- response = @conn.get("archivedrocks/user/#{user_id}").body
99
- response.map do |rock|
100
- {
101
- id: rock["Id"],
102
- title: rock["Name"],
103
- created_at: rock["CreateTime"],
104
- due_date: rock["DueDate"],
105
- status: rock["Complete"] ? "Complete" : "Incomplete"
106
- }
107
- end
108
- end
109
- end