matey 0.1.1 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/devcontainer.json +1 -1
  3. data/CHANGELOG.md +1 -1
  4. data/COLOR_SCHEMES.md +24 -0
  5. data/COMPONENTS.md +75 -0
  6. data/Gemfile +2 -13
  7. data/Gemfile.lock +148 -143
  8. data/README.md +53 -100
  9. data/app/components/matey/active_users_component.html.erb +2 -2
  10. data/app/components/matey/active_users_component.rb +5 -3
  11. data/app/components/{application_component.rb → matey/application_component.rb} +3 -1
  12. data/app/components/matey/bounce_rate_component.html.erb +35 -0
  13. data/app/components/matey/bounce_rate_component.rb +24 -0
  14. data/app/components/matey/browser_os_breakdown_component.html.erb +38 -0
  15. data/app/components/matey/browser_os_breakdown_component.rb +11 -0
  16. data/app/components/matey/daily_active_users_component.html.erb +15 -0
  17. data/app/components/matey/daily_active_users_component.rb +11 -0
  18. data/app/components/matey/new_activity_component.html.erb +2 -2
  19. data/app/components/matey/new_activity_component.rb +5 -3
  20. data/app/components/matey/new_users_component.html.erb +2 -2
  21. data/app/components/matey/new_users_component.rb +5 -3
  22. data/app/components/matey/top_events_component.html.erb +2 -2
  23. data/app/components/matey/top_events_component.rb +4 -2
  24. data/app/components/matey/top_visited_pages_table_component.html.erb +2 -2
  25. data/app/components/matey/top_visited_pages_table_component.rb +4 -2
  26. data/app/components/matey/user_engagement_component.html.erb +27 -0
  27. data/app/components/matey/user_engagement_component.rb +12 -0
  28. data/app/components/matey/visits_by_day_of_week_component.html.erb +26 -0
  29. data/app/components/matey/visits_by_day_of_week_component.rb +24 -0
  30. data/docs/CONTRIBUTING.md +22 -0
  31. data/images/bounceRateComponent.png +0 -0
  32. data/images/colorSchemeBlue.png +0 -0
  33. data/images/colorSchemeNeutral.png +0 -0
  34. data/lib/helpers.rb +12 -0
  35. data/lib/matey/version.rb +1 -1
  36. data/lib/matey.rb +7 -2
  37. data/matey.gemspec +12 -5
  38. metadata +54 -12
data/README.md CHANGED
@@ -4,25 +4,24 @@
4
4
  ![GitHub issues](https://img.shields.io/github/issues-raw/harled/matey)
5
5
  ![GitHub Repo stars](https://img.shields.io/github/stars/harled/matey?logoColor=purple&style=social)
6
6
 
7
- 📈 User Engagement Tracking Components for [Ahoy](https://github.com/ankane/ahoy) 🏴‍☠️
7
+ 📈 User Engagement Tracking ViewComponents for [Ahoy](https://github.com/ankane/ahoy) data 🏴‍☠️
8
8
 
9
- A suite of user engagment ViewComponents for plug and play use right from your Ahoy data!
10
- No need to spend time finding what information you need and how to write the queries to set that up.
11
- Simply install the gem, input the required data and track how your users are responding to your application!
9
+ This gem provides a suite of prebuilt [ViewComponents](https://github.com/github/view_component) to observe user engagement in an Ahoy-powered Ruby on Rails application.
12
10
 
13
- Project Lead: Caitlin Henry
14
- [**caitmich**](https://github.com/caitmich) | (*caitlin@harled.ca*)
15
-
16
- This gem assumes that event data is coming from [Ahoy](https://github.com/ankane/ahoy) which is a fantastic library
17
- for tracking visits and events. Your project must have Ahoy installed and configured in order to benefit from Matey.
18
-
19
- This gem assumes that you have [Bootstrap 5.1](https://getbootstrap.com/docs/5.1/getting-started/introduction/) loaded in your project. It will work without Bootstrap, however, you will need to provide your own custom styling for the Bootstrap equivalent classes.
20
11
 
21
12
  ## Installation
22
13
 
23
- Add this line to your application's Gemfile:
14
+ `matey` depends on:
15
+ * [Ahoy](https://github.com/ankane/ahoy) installed, configured and tracking user visit and event data
16
+ * [Bootstrap 5.1](https://getbootstrap.com/docs/5.1/getting-started/introduction/) available for styling
17
+
18
+ Add this line to the Gemfile:
24
19
 
25
20
  ```ruby
21
+ # latest from rubygems
22
+ gem 'matey'
23
+
24
+ # or latest from github
26
25
  gem 'matey', github: 'harled/matey', branch: 'main'
27
26
  ```
28
27
 
@@ -30,126 +29,80 @@ And then execute:
30
29
 
31
30
  $ bundle install
32
31
 
33
- You will now have the latest version of Matey on your project. Checkout the Usage section to see what components there are and how to use them in your app!
34
-
35
32
  ## Usage
36
33
 
37
- Look here to see what components Matey offers and how to use them 🛠️
34
+ Once `matey` is installed, the next step is to render a component. The data required varies by component.
35
+ Below is an example of how the `Matey::ActiveUsersComponent` would be
36
+ called in an application. This component reports on the number of active users within the past two weeks.
38
37
 
39
- ### Common Flows
38
+ Below the component is called with two named parameters which include `events` (ahoy event data) and
39
+ the `time_window`, which is the period to report on.
40
40
 
41
- Some common flows to recognize how the named paramaters work for the components. This is what a Matey view component render line would look like in your view file:
42
-
43
- ```
44
- <%= render Matey::ComponentName.new(events: Ahoy::Event.all, time_window: 1.week) %>
41
+ ```ruby
42
+ # dashboard.html.erb
43
+ <%= render Matey::ActiveUsersComponent.new(events: Ahoy::Event.all, time_window: 1.week) %>
45
44
  ```
46
45
 
47
- Here we can see that all components begin with **`Matey::`** followed by the name of the component. The **`data`** parameter will take in Ahoy data as an ***ActiveRecordRelation*** collection.
48
-
49
- The **`time_window`** takes in an amount of time that the component will look calculate the data for and uses this to set the specific date range that the data will be taken from. This is an optional parameter and the default will be a 1 week time window.
50
-
51
- In this example, the component will take the **`Ahoy::Events`** data and show information about the week of data.
52
-
53
- **Note**: The data the component is completely limited by the extent of your [Ahoy](https://github.com/ankane/ahoy) data. Setting up events on each controller action can be seen [here](https://github.com/ankane/ahoy#ruby) and can be done in the base controller so that all other controllers inherit from here and will create Ahoy events.
54
-
55
- Also, if you have a lot of data, you can cut down the data that you are passing through by reducing the time the events have occurred, however the comparison between the current and previous `time_window` will require two time windows worth of data (ie. for data from last week, this will compare to data from 2 weeks ago)
56
-
57
- ### New Users Component
58
-
59
- ![New Users Component](./images/newUsersComponent.png)
60
-
61
- The New Users component will calculate the number of new users that have been created in the given time window and show you the amount and percentage change from the previous time period. The code should look like this:
62
-
63
- ```
64
- <%= render Matey::NewUsersComponent.new(users: User.all, time_window: 2.month) %>
65
- ```
46
+ It is that simple! There should now be a card displaying the number of active users within the past week.
66
47
 
67
- Here we are passing in all of our **User** model data for the component to find the new users that were made in the last 2 months, but we can filter this data to only include a specific subset of users or from a specific time period. The component will find the new users created in the past month and show us the increase/decrease since the last period.
68
- ### Active Users
48
+ View the available component color schemes [here](COLOR_SCHEMES.md).
69
49
 
70
- ![Active Users Component](./images/activeUsersComponent.png)
50
+ View the list of available components [here](COMPONENTS.md).
71
51
 
72
- The Active Users component will calculate the number of active users that have been created in the given time window and show you the amount and percentage change from the previous time period. This component counts active users as those who have been involved in an Ahoy event in the given time window. The code should look like this:
52
+ **Note**: The more data, the more interesting the components will be. A common and helpful pattern is to capture events on all controller actions. Details on doing this can be found [here](https://github.com/ankane/ahoy#ruby).
73
53
 
74
- ```
75
- <%= render Matey::ActiveUsersComponent.new(events: Ahoy::Event.all, time_window: 1.month) %>
76
- ```
54
+ ## Development
77
55
 
78
- Here we are passing in all of our **Ahoy::Event** model data for the component to find the user that were triggered some Ahoy Event, but we can filter this data to only include a specific subset of Ahoy Events or from a specific time period. The component will find the active users created in the past month and show us the increase/decrease since the last period.
56
+ After checking out the repository, run the following commands to get started:
79
57
 
80
- ### New Activity Component
58
+ ```bash
59
+ # install required packages
60
+ bin/setup
81
61
 
82
- ![New Activity Component](./images/newActivityComponent.png)
62
+ # install spec/sample packages
63
+ bundle install --gemfile spec/sample/Gemfile
83
64
 
84
- The New Activity component will calculate the number of Ahoy events that have been created in the given time window and show you the amount and percentage change from the previous time period. The implementation should look like:
65
+ # run test cases and ensure everything is passing
66
+ rake spec
85
67
 
86
- ```
87
- <%= render Matey::NewActivityComponent.new(events: Ahoy::Event.all, time_window: 1.month) %>
68
+ # an interactive prompt that will allow you to experiment with matey (currently broken!)
69
+ bin/console
88
70
  ```
89
71
 
90
- Here we are passing in all of our **Ahoy::Event** model data for the component to count all Ahoy Event, but we can filter this data to only include a specific subset of Ahoy Events or from a specific time period. The component will find the Ahoy events created in the past month and show us the increase/decrease since the last period.
91
- ### Top Visited Landing Pages Component
72
+ To install `matey` and make it available as a regular rubygem, run the following command: `bundle exec rake install`
92
73
 
93
- ![Top Visited Landing Pages Component](./images/topVisitedPages.png)
74
+ ### Sample Application
94
75
 
95
- The Top Visited Pages Table Component component will take advantage of **`Ahoy::Visit`** and gives you a list of the top visited paths. Just pass in the Ahoy::Visit.all and the component will calculate the top landing pages based on the visits that have been created in the given time window. The *`limit`* parameter limits the number of results and is 10 by default. The implementation should look like:
76
+ ViewComponents are pretty hard to test without a Ruby on Rails application. This repository includes a sample application that makes it easy to see how a component renders and make quick adjustments.
96
77
 
97
- ```
98
- <%= render(Matey::TopVisitedPagesTableComponent.new(events: Ahoy::Visit.all, time_window: 1.month, limit: 10)) %>
99
- ```
100
-
101
- ### Top Events Component
78
+ To use the sample application:
102
79
 
103
- ![Top Events Component](./images/topEventsComponent.png)
80
+ 1. `cd spec/sample`
81
+ 2. `bundle`
82
+ 3. `bundle exec rails s`
83
+ 4. Open a browser to `localhost:3000`
104
84
 
105
- The Top Events Component component will give you a list of the top Ahoy::Event's that are triggered by your users. Just pass in the Ahoy::Event.all and the component will calculate the top events that have been triggered in the given time window. The *`limit`* parameter limits the number of results and is 10 by default. The implementation should look like:
106
-
107
- ```
108
- <%= render(Matey::TopEventsComponent.new(events: Ahoy::Event.all, time_window: 1.month, limit: 10)) %>
109
- ```
110
-
111
- ### Custom Card Component
112
- *Coming Soon...*
113
- ### Custom Table Component
114
- *Coming Soon...*
115
- ## Development
85
+ ## Testing
116
86
 
117
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
87
+ To run the test cases:
118
88
 
119
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
89
+ 1. `rails db:test:prepare`
90
+ 2. `bundle exec rake`
120
91
 
121
- A sample application is included in this repository to help with exploring the components and testing. To use the
122
- sample application:
92
+ ## Releasing a New Version
123
93
 
124
- 1. cd spec/sample
125
- 2. bundle
126
- 3. rails s
127
- 4. Open a browser to localhost:3000
94
+ To release a new version:
128
95
 
129
- ## Testing
96
+ 1. Update the version number in `version.rb`
97
+ 2. Run `bundle exec rake release`
130
98
 
131
- Use the folloiwng steps to run the test cases:
99
+ The rake task will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
132
100
 
133
- 1. rails db:test:prepare
134
- 2. bundle exec rake
135
101
 
136
102
  ## Contributing
137
103
 
138
- Bug reports and pull requests are welcome on GitHub at https://github.com/harled/matey. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/harled/matey/blob/master/CODE_OF_CONDUCT.md).
139
-
140
- ### Contribution Steps:
141
-
142
- Want to help us out? Here are some steps to make sure you are contributing
143
-
144
- 1. Find an issue you like, or create a new issue [here](https://github.com/harled/matey/issues)
145
- - Please ask for any questions or clarifications in the associated issues or in new issues! 🤔
146
- 2. Assign yourself to the issue and create a branch , following GitHub Issue's naming scheme. 🛠️
147
- - The naming scheme should follow (#issueNumber-issue-name) ie. (#10-create-new-component)
148
- 3. Get on your local machine and [ensure you have the repo cloned](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository). Checkout the branch you just made with `git checkout branch-name` and pull the latest merged changes from the repo with `git pull origin main` to make sure you have the most up-to-date code from the repo. 👩‍💻
149
- 4. Add your amazing changes along with any documentation you feel would be useful. Then commit and push your changes. 🌟
150
- 5. Go back to the repo on GitHub and create a pull request! Then wait for an admin of the repo to get back to your pull request, address any comments and once you are finally approved, merge your code into Matey! 🎉
104
+ Please take a look at our [Contribution Guidelines](https://github.com/harled/matey/blob/main/docs/CONTRIBUTING.md).
151
105
 
152
- If you want some more tips on contributing to GitHub projects, [check out this resource from Data School](https://www.dataschool.io/how-to-contribute-on-github/).
153
106
 
154
107
  ## License
155
108
 
@@ -157,4 +110,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
157
110
 
158
111
  ## Code of Conduct
159
112
 
160
- Everyone interacting in the Matey project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/harled/matey/blob/master/CODE_OF_CONDUCT.md).
113
+ Everyone interacting in the *Matey* project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/harled/matey/blob/master/CODE_OF_CONDUCT.md).
@@ -1,4 +1,4 @@
1
- <div class="card bg-primary text-light">
1
+ <div class="card <%= @color_scheme %>">
2
2
  <div class="card-body">
3
3
  <div class="row">
4
4
  <div class="col">
@@ -6,7 +6,7 @@
6
6
  </div>
7
7
  <div class="col-auto">
8
8
  <p class="card-text text-end mb-0">
9
- <%= (@change_active_number > 0 ? "+" : "") + @change_active_number.to_s + " / " + @change_active_percent.to_s + "%" %>
9
+ <%= (@change_active_number > 0 ? "+" : "") + @change_active_number.to_s + " / " + @change_active_percent.to_s + "%" %> compared to last period.
10
10
  </p>
11
11
  </div><!-- .col -->
12
12
  </div><!-- .row -->
@@ -1,7 +1,7 @@
1
1
  require "ahoy_matey"
2
2
 
3
- class Matey::ActiveUsersComponent < ApplicationComponent
4
- def initialize(events:, time_window: 1.week)
3
+ class Matey::ActiveUsersComponent < Matey::ApplicationComponent
4
+ def initialize(events:, time_window: 1.week, color_scheme: "neutral")
5
5
  raise ArgumentError unless events.is_a?(ActiveRecord::Relation)
6
6
  raise ArgumentError unless time_window.is_a?(Integer)
7
7
 
@@ -9,8 +9,10 @@ class Matey::ActiveUsersComponent < ApplicationComponent
9
9
  previous_period = events.where(time: (2 * time_window).ago..time_window.ago).pluck(:user_id).uniq.count
10
10
 
11
11
  @change_active_number = @current_period - previous_period
12
- @change_active_percent = ((@change_active_number.to_f / (previous_period == 0 ? 1 : previous_period)) * 100).truncate(2)
12
+ @change_active_percent = ((@change_active_number.to_f / ((previous_period == 0) ? 1 : previous_period)) * 100).truncate(2)
13
13
 
14
14
  @time_window = time_window
15
+
16
+ @color_scheme = color_scheme(scheme: color_scheme)
15
17
  end
16
18
  end
@@ -1,8 +1,10 @@
1
1
  require "view_component"
2
2
  require "ahoy_matey"
3
+ require_relative "../../../lib/helpers"
3
4
 
4
- class ApplicationComponent < ViewComponent::Base
5
+ class Matey::ApplicationComponent < ViewComponent::Base
5
6
  include ActiveModel::Validations
7
+ include ColorSchemeHelper
6
8
 
7
9
  def before_render
8
10
  validate!
@@ -0,0 +1,35 @@
1
+ <div class="card <%= @color_scheme %>">
2
+ <div class="card-body">
3
+ <h5 class = "text-center"><strong>The Bounce Rate of your Application is: <u><%= @percentage_of_visits_that_were_bounced %>%</u></strong></h5>
4
+ <div>
5
+ <table class="table table-hover table-borderless table-sm">
6
+ <tr class="table-dark">
7
+ <td><strong>Total Number of Bounced Visits:</strong></td>
8
+ <td class="text-end"><%= @total_number_of_single_event_visits %></td>
9
+ </tr>
10
+ <tr class="table-dark">
11
+ <td><strong>Total Number of Visits:</strong></td>
12
+ <td class="text-end"><%= @total_number_of_user_visits %></td>
13
+ </tr>
14
+ </table>
15
+ </div>
16
+ <div>
17
+ <table class="table table-hover table-borderless table-sm">
18
+ <thead class="table-dark">
19
+ <tr>
20
+ <th>Bounced Page</th>
21
+ <th class="text-end">Bounce Count</th>
22
+ </tr>
23
+ </thead>
24
+ <tbody class="text-dark border-dark">
25
+ <% @most_bounced_pages.each do |controller_name_and_action, count| %>
26
+ <tr>
27
+ <td><%= controller_name_and_action %></td>
28
+ <td class="text-end"><%= count %></td>
29
+ </tr>
30
+ <% end %>
31
+ </tbody>
32
+ </table>
33
+ </div>
34
+ </div>
35
+ </div>
@@ -0,0 +1,24 @@
1
+ require "ahoy_matey"
2
+
3
+ class Matey::BounceRateComponent < Matey::ApplicationComponent
4
+ def initialize(events:, visits:, limit: 5, color_scheme: "neutral")
5
+ # Determine the total number of user sessions to the website
6
+ @total_number_of_user_visits = events.pluck(:visit_id).uniq.count
7
+
8
+ # First we group by visit_id and scope to visits containing ONLY 1 event
9
+ @visits_having_only_one_event = events.group(:visit_id).having("count(ahoy_events.id) == 1")
10
+ # We then count each unique occurence of a visit with 1 event
11
+ @total_number_of_single_event_visits = @visits_having_only_one_event.uniq.count
12
+
13
+ # Determine pages in which the most bounces occur
14
+ @single_event_visits_landing_page_count = visits.where(id: @visits_having_only_one_event.pluck(:visit_id)).pluck(:landing_page).tally
15
+
16
+ # Scope the results to the given limit and sort them in descending order
17
+ @most_bounced_pages = @single_event_visits_landing_page_count.sort_by { |controller_name_and_action, count| count }.last(limit).reverse
18
+
19
+ # Get the percentage as #-One-Page-Visits / Total-#-Of-Visits
20
+ @percentage_of_visits_that_were_bounced = ((@total_number_of_single_event_visits.to_f / ((@total_number_of_user_visits == 0) ? 1 : @total_number_of_user_visits)) * 100).round(1)
21
+
22
+ @color_scheme = color_scheme(scheme: color_scheme)
23
+ end
24
+ end
@@ -0,0 +1,38 @@
1
+ <div class="card <%= @color_scheme %>">
2
+ <div class="card-body">
3
+ <div class="row">
4
+ <h5 class="text-center">Browser and OS Breakdown</h5>
5
+ <div class="col">
6
+ <p class="text-center">Since <%= time_ago_in_words(@time_window.ago).titleize %> Ago</p>
7
+ <table class='table table-hover table-borderless'>
8
+ <thead class='table-dark'>
9
+ <th>Browser</th>
10
+ <th class='text-center'>Visitor Count</th>
11
+ </thead>
12
+ <tbody class='text-dark border-dark'>
13
+ <% @browsers.each do |browser_name, visitor_count| %>
14
+ <tr>
15
+ <td><%= browser_name %></td>
16
+ <td class='text-center'><%= visitor_count %></td>
17
+ </tr>
18
+ <% end %>
19
+ </tbody>
20
+ </table>
21
+ <table class='table table-hover table-borderless'>
22
+ <thead class='table-dark'>
23
+ <th>OS</th>
24
+ <th class='text-center'>Visitor Count</th>
25
+ </thead>
26
+ <tbody class='text-dark border-dark'>
27
+ <% @operating_systems.each do |operating_system, visitor_count| %>
28
+ <tr>
29
+ <td><%= operating_system %></td>
30
+ <td class='text-center'><%= visitor_count %></td>
31
+ </tr>
32
+ <% end %>
33
+ </tbody>
34
+ </table>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </div>
@@ -0,0 +1,11 @@
1
+ class Matey::BrowserOsBreakdownComponent < Matey::ApplicationComponent
2
+ def initialize(visits:, time_window:, color_scheme: "neutral")
3
+ visits_in_time_window = visits.where(started_at: time_window.ago..)
4
+ @visits_in_time_window = visits_in_time_window.count
5
+ @browsers = visits_in_time_window.group(:browser).count
6
+ @operating_systems = visits_in_time_window.group(:os).count
7
+ @time_window = time_window
8
+
9
+ @color_scheme = color_scheme(scheme: color_scheme)
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ <div class="card <%= @color_scheme %>">
2
+ <div class="card-body">
3
+ <div class="col">
4
+ <div class="col">
5
+ <h5>Daily Active Users</h5>
6
+ </div>
7
+ <div class="col-auto">
8
+ <p>Since <%= time_ago_in_words(@time_window.ago).titleize %> Ago</p>
9
+ <p><%= @distinct_user_visits_by_day %></p>
10
+ <p><%# @distinct_user_visits_by_day2 %></p>
11
+ <%# @visits.each {|e| e} %>
12
+ </div>
13
+ </div>
14
+ </div>
15
+ </div>
@@ -0,0 +1,11 @@
1
+ class Matey::DailyActiveUsersComponent < Matey::ApplicationComponent
2
+ def initialize(visits:, time_window:, color_scheme: "neutral")
3
+ @visits = visits
4
+ @time_window = time_window
5
+ visits_in_time_window = visits.where(started_at: time_window.ago..)
6
+ @distinct_user_visits_by_day = visits_in_time_window.order(:day).group(:day).uniq.count
7
+ # @distinct_user_visits_by_day2 = visits_in_time_window.order(:day).group("DATE(started_at)").map { |k, v| [k, v] }.sort
8
+
9
+ @color_scheme = color_scheme(scheme: color_scheme)
10
+ end
11
+ end
@@ -1,4 +1,4 @@
1
- <div class="card bg-primary text-light">
1
+ <div class="card <%= @color_scheme %>">
2
2
  <div class="card-body">
3
3
  <div class="row">
4
4
  <div class="col">
@@ -6,7 +6,7 @@
6
6
  </div>
7
7
  <div class="col-auto">
8
8
  <p class="card-text text-end mb-0">
9
- <%= (@change_active_number > 0 ? "+" : "") + @change_active_number.to_s + " / " + @change_active_percent.to_s + "%" %>
9
+ <%= (@change_active_number > 0 ? "+" : "") + @change_active_number.to_s + " / " + @change_active_percent.to_s + "%" %> compared to last period.
10
10
  </p>
11
11
  </div><!-- .col -->
12
12
  </div><!-- .row -->
@@ -1,5 +1,5 @@
1
- class Matey::NewActivityComponent < ApplicationComponent
2
- def initialize(events:, time_window: 1.week)
1
+ class Matey::NewActivityComponent < Matey::ApplicationComponent
2
+ def initialize(events:, time_window: 1.week, color_scheme: "neutral")
3
3
  raise ArgumentError unless events.is_a?(ActiveRecord::Relation)
4
4
  raise ArgumentError unless time_window.is_a?(Integer)
5
5
 
@@ -7,8 +7,10 @@ class Matey::NewActivityComponent < ApplicationComponent
7
7
  previous_period = events.where(time: (2 * time_window).ago..time_window.ago).pluck(:user_id).count
8
8
 
9
9
  @change_active_number = @current_period - previous_period
10
- @change_active_percent = ((@change_active_number.to_f / (previous_period == 0 ? 1 : previous_period)) * 100).truncate(2)
10
+ @change_active_percent = ((@change_active_number.to_f / ((previous_period == 0) ? 1 : previous_period)) * 100).truncate(2)
11
11
 
12
12
  @time_window = time_window
13
+
14
+ @color_scheme = color_scheme(scheme: color_scheme)
13
15
  end
14
16
  end
@@ -1,4 +1,4 @@
1
- <div class="card bg-primary text-light">
1
+ <div class="card <%= @color_scheme %>">
2
2
  <div class="card-body">
3
3
  <div class="row">
4
4
  <div class="col">
@@ -6,7 +6,7 @@
6
6
  </div>
7
7
  <div class="col-auto">
8
8
  <p class="card-text text-end mb-0">
9
- <%= (@change_new_number > 0 ? "+" : "") + @change_new_number.to_s + " / " + @change_new_percent.to_s + "%" %>
9
+ <%= (@change_new_number > 0 ? "+" : "") + @change_new_number.to_s + " / " + @change_new_percent.to_s + "%" %> compared to last period.
10
10
  </p>
11
11
  </div><!-- .col -->
12
12
  </div><!-- .row -->
@@ -1,11 +1,13 @@
1
- class Matey::NewUsersComponent < ApplicationComponent
2
- def initialize(users:, time_window: 1.week)
1
+ class Matey::NewUsersComponent < Matey::ApplicationComponent
2
+ def initialize(users:, time_window: 1.week, color_scheme: "neutral")
3
3
  @current_period = users.where(created_at: time_window.ago..Time.current).count
4
4
  previous_period = users.where(created_at: (2 * time_window).ago..time_window.ago).count
5
5
 
6
6
  @change_new_number = @current_period - previous_period
7
- @change_new_percent = ((@change_new_number.to_f / (previous_period == 0 ? 1 : previous_period)) * 100).truncate(2)
7
+ @change_new_percent = ((@change_new_number.to_f / ((previous_period == 0) ? 1 : previous_period)) * 100).truncate(2)
8
8
 
9
9
  @time_window = time_window
10
+
11
+ @color_scheme = color_scheme(scheme: color_scheme)
10
12
  end
11
13
  end
@@ -1,6 +1,6 @@
1
1
 
2
2
 
3
- <div class="card bg-primary text-light">
3
+ <div class="card <%= @color_scheme %>">
4
4
  <div class="card-body">
5
5
  <h5>Top Events Since <%= time_ago_in_words(@time_window.ago).titleize %> Ago (<%= @time_window.ago.strftime("%m/%d/%Y") %>)</h5>
6
6
  <div>
@@ -11,7 +11,7 @@
11
11
  <th>Count</th>
12
12
  </tr>
13
13
  </thead>
14
- <tbody class="text-light">
14
+ <tbody class="text-dark border-dark">
15
15
  <% @events.each do |action, count| %>
16
16
  <tr>
17
17
  <td><%= action %></td>
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Matey::TopEventsComponent < ApplicationComponent
4
- def initialize(events:, time_window: 1.week, limit: 5)
3
+ class Matey::TopEventsComponent < Matey::ApplicationComponent
4
+ def initialize(events:, time_window: 1.week, limit: 5, color_scheme: "neutral")
5
5
  raise ArgumentError unless events.is_a?(ActiveRecord::Relation)
6
6
  raise ArgumentError unless time_window.is_a?(Integer)
7
7
 
8
8
  @events = events.where(time: time_window.ago..Time.current).limit(limit).order("count(name) DESC").group(:name).count
9
9
  @time_window = time_window
10
+
11
+ @color_scheme = color_scheme(scheme: color_scheme)
10
12
  end
11
13
  end
@@ -1,4 +1,4 @@
1
- <div class="card bg-primary text-light">
1
+ <div class="card <%= @color_scheme %>">
2
2
  <div class="card-body">
3
3
  <h5>Top Landing Page Visits Since <%= time_ago_in_words(@time_window.ago).titleize %> Ago (<%= @time_window.ago.strftime("%m/%d/%Y") %>)</h5>
4
4
  <div>
@@ -9,7 +9,7 @@
9
9
  <th>Count</th>
10
10
  </tr>
11
11
  </thead>
12
- <tbody class="text-light">
12
+ <tbody class="text-dark border-dark">
13
13
  <% @user_count_by_event.each do |controller_name_and_action, count| %>
14
14
  <tr>
15
15
  <td><%= controller_name_and_action %></td>
@@ -1,5 +1,5 @@
1
- class Matey::TopVisitedPagesTableComponent < ApplicationComponent
2
- def initialize(events:, time_window: 1.week, limit: 10)
1
+ class Matey::TopVisitedPagesTableComponent < Matey::ApplicationComponent
2
+ def initialize(events:, time_window: 1.week, limit: 10, color_scheme: "neutral")
3
3
  # Group events by controller (:name) and action. Aggregate number of unique user actions
4
4
  @user_count_by_event = events.where(started_at: time_window.ago..).pluck(:landing_page).tally
5
5
 
@@ -7,5 +7,7 @@ class Matey::TopVisitedPagesTableComponent < ApplicationComponent
7
7
  @user_count_by_event = @user_count_by_event.sort_by { |controller_name_and_action, count| count }.last(limit).reverse
8
8
 
9
9
  @time_window = time_window
10
+
11
+ @color_scheme = color_scheme(scheme: color_scheme)
10
12
  end
11
13
  end
@@ -0,0 +1,27 @@
1
+ <div class="card <%= @color_scheme %>">
2
+ <div class="card-body">
3
+ <h5>User Activity for <i>user id: <%=@user_id%></i> since <i><%= time_ago_in_words(@time_window.ago).titleize %></i> ago </h5>
4
+ <div>
5
+ <table class="table table-hover table-borderless table-sm">
6
+ <thead class="table-dark">
7
+ <tr>
8
+ <th class="text-start">Event</th>
9
+ <th class="text-end">Count</th>
10
+ </tr>
11
+ </thead>
12
+ <tbody class="text-dark border-dark">
13
+ <% @count_by_event.each do |event, count| %>
14
+ <tr>
15
+ <td><%= event %></td>
16
+ <td class="text-end"><%= count %></td>
17
+ </tr>
18
+ <% end %>
19
+ <tr class="table-dark">
20
+ <td><strong>Total:</strong></td>
21
+ <td class="text-end"><%= @count_by_event.sum {|event, count| count} %></td>
22
+ </tr>
23
+ </tbody>
24
+ </table>
25
+ </div>
26
+ </div><!-- .card-body -->
27
+ </div><!-- .card -->
@@ -0,0 +1,12 @@
1
+ require "ahoy_matey"
2
+
3
+ class Matey::UserEngagementComponent < Matey::ApplicationComponent
4
+ def initialize(events:, user_id:, time_window: 1.week, limit: 10, color_scheme: "neutral")
5
+ @events_for_user = events.where_props(user_id: user_id).where(time: time_window.ago..Time.current).group(:name).count
6
+ @count_by_event = @events_for_user.sort_by { |event, count| count }.last(limit).reverse
7
+ @time_window = time_window
8
+ @user_id = user_id
9
+
10
+ @color_scheme = color_scheme(scheme: color_scheme)
11
+ end
12
+ end
@@ -0,0 +1,26 @@
1
+ <div class="card <%= @color_scheme %>">
2
+ <div class="card-header">
3
+ <h5>Visits By Day of Week since <%= time_ago_in_words(@time_window.ago).titleize %> Ago (<%= @time_window.ago.strftime("%m/%d/%Y") %>) </h5>
4
+ <% if @exclude_days %>
5
+ <p>Excluding <%= @exclude_days%>
6
+ <% end %>
7
+ </div>
8
+ <div class="card-body">
9
+ <table class="table table-hover table-borderless table-sm">
10
+ <thead class="table-dark">
11
+ <tr>
12
+ <th class="text-start">DayOfWeek</th>
13
+ <th class="text-end">Count</th>
14
+ </tr>
15
+ </thead>
16
+ <tbody class="text-dark border-dark">
17
+ <% @visits_by_day_of_week.each do |day_of_week, count| %>
18
+ <tr>
19
+ <td><%= day_of_week %></td>
20
+ <td class="text-end"><%= count %></td>
21
+ </tr>
22
+ <% end %>
23
+ </tbody>
24
+ </table>
25
+ </div><!-- .card-body -->
26
+ </div><!-- .card -->