rails_local_analytics 0.2.0 → 0.2.2

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: 4ffdaa293f22790a92032f05322b5ceec16f7fa5ca6fe0d853f7ee2c22cb43a7
4
- data.tar.gz: 6d40a7a31467662aeda69cf7e2d6ad7f427c7cae14de922b70b8a0fc5003c7ce
3
+ metadata.gz: 6c1dffba4cbead6faa6192e3c1df830aa749f6f653bdc8f0eef6e9dbd3a2650b
4
+ data.tar.gz: b0b6a574e09786c7888c4e6194fff36616f9d0634d99773955e762417ee3c828
5
5
  SHA512:
6
- metadata.gz: 5a3c7cd5cda651680348f9b6feaba06ca917e6b55380fc5b9ec26713391ead71dd89830b209435eff75a3021a624c93a82e69ae5a9173c05d3a4918646d014d7
7
- data.tar.gz: e1eda84eff2b599049bd837c69de93bfcf58614d31b9f437233f6a6e0ac881b0112746ea515275d5dac98b3de0d66ee13524f1038dfed0b33c24c02a003cf018
6
+ metadata.gz: 021fcb8b029ce1d842415eb5a4a3ed39a433726851988891455f2aa1ec510a1f56acc9563bad3003b799624384a8ff74ef40183e0a81746df82bb1d3b68d2e24
7
+ data.tar.gz: 6c9d8b537f1de5f9b28b1b6e6baac6135a389a1ba65bb5dbc19a4ebdd7b73e1efaf855e6daaaa81b8b06b0a2d1913e0d0cdc97fd31635c794d545238751820c6
data/README.md CHANGED
@@ -138,6 +138,9 @@ Some examples of additional things you may want to track:
138
138
  * You may not need to store this in a new column, one example pattern could be to store this data in the existing `platform` database field
139
139
  - Country detection
140
140
  * Country detection is difficult. As such we dont try to include it by default.
141
+ * Consider using language detection instead
142
+ - Language detection
143
+ * You can gather the language from the `request.env["HTTP_ACCEPT_LANGUAGE"]` or `browser.accept_language.first.full`
141
144
  - Users or organizations
142
145
  * You may want to track your users or another model which is a core tenant to your particular application
143
146
 
@@ -2,6 +2,10 @@ body{
2
2
  padding-bottom: 20px;
3
3
  }
4
4
 
5
+ table td{
6
+ overflow-wrap: anywhere;
7
+ }
8
+
5
9
  input, select {
6
10
  border-radius: 5px;
7
11
  border: 1px solid #333;
@@ -3,6 +3,7 @@ module RailsLocalAnalytics
3
3
  PER_PAGE_LIMIT = 1000
4
4
 
5
5
  helper_method :pagination_page_number
6
+ helper_method :display_columns
6
7
 
7
8
  def index
8
9
  params[:type] ||= "page"
@@ -17,17 +18,13 @@ module RailsLocalAnalytics
17
18
  return
18
19
  end
19
20
 
20
- if params[:group_by].present? && !@klass.display_columns.include?(params[:group_by])
21
- params[:group_by] = nil
22
- end
23
-
24
21
  if params[:start_date].present?
25
22
  @start_date = Date.parse(params[:start_date])
26
23
  else
27
24
  @start_date = Date.today
28
25
  end
29
26
 
30
- if params[:end_date]
27
+ if params[:end_date].present?
31
28
  @end_date = Date.parse(params[:end_date])
32
29
  else
33
30
  @end_date = Date.today
@@ -63,20 +60,18 @@ module RailsLocalAnalytics
63
60
 
64
61
  prev_start_date, prev_end_date = get_prev_dates(start_date, end_date)
65
62
 
66
- where_conditions = params.require(:conditions).permit(*@klass.display_columns)
63
+ difference_where_conditions = params.require(:conditions).permit(*display_columns)
67
64
 
68
65
  current_total = fetch_records(
69
66
  start_date,
70
67
  end_date,
71
- where_conditions: where_conditions,
72
- pluck_columns: ["SUM(total)"],
68
+ difference_where_conditions: difference_where_conditions,
73
69
  ).first
74
70
 
75
71
  prev_total = fetch_records(
76
72
  prev_start_date,
77
73
  prev_end_date,
78
- where_conditions: where_conditions,
79
- pluck_columns: ["SUM(total)"],
74
+ difference_where_conditions: difference_where_conditions,
80
75
  ).first
81
76
 
82
77
  if prev_total
@@ -90,36 +85,69 @@ module RailsLocalAnalytics
90
85
 
91
86
  private
92
87
 
93
- def fetch_records(start_date, end_date, where_conditions: nil, pluck_columns: nil)
88
+ def fetch_records(start_date, end_date, difference_where_conditions: nil)
89
+ aggregate_sql_field = "SUM(total)"
90
+
94
91
  tracked_requests = @klass
95
92
  .where("day >= ?", start_date)
96
93
  .where("day <= ?", end_date)
97
- .order(total: :desc)
94
+ .order("#{aggregate_sql_field} DESC")
98
95
 
99
- if where_conditions.nil? && pluck_columns.nil?
96
+ if difference_where_conditions
97
+ tracked_requests = tracked_requests.where(difference_where_conditions)
98
+ else
100
99
  tracked_requests = tracked_requests
101
100
  .limit(PER_PAGE_LIMIT)
102
101
  .offset(PER_PAGE_LIMIT * (pagination_page_number-1))
103
- end
104
102
 
105
- if where_conditions
106
- tracked_requests = tracked_requests.where(where_conditions)
103
+ if params[:filter].present?
104
+ col, val = params[:filter].split("==")
105
+
106
+ if display_columns.include?(col)
107
+ tracked_requests = tracked_requests.where(col => val)
108
+ else
109
+ raise ArgumentError
110
+ end
111
+ end
107
112
  end
108
113
 
109
114
  if params[:search].present?
110
115
  tracked_requests = tracked_requests.multi_search(params[:search])
111
116
  end
112
117
 
113
- if params[:group_by].present?
114
- group_by_columns = [params[:group_by]]
115
- pluck_columns = [params[:group_by], "SUM(total)"]
118
+ if params[:group_by].blank?
119
+ pluck_columns = display_columns.dup
116
120
  else
117
- group_by_columns = @klass.display_columns
118
- pluck_columns ||= @klass.display_columns + ["SUM(total)"]
121
+ case params[:group_by]
122
+ when "url_hostname_and_path"
123
+ if display_columns.include?("url_hostname") && display_columns.include?("url_path")
124
+ pluck_columns = [:url_hostname, :url_path]
125
+ else
126
+ raise ArgumentError
127
+ end
128
+ when "referrer_hostname_and_path"
129
+ if display_columns.include?("referrer_hostname") && display_columns.include?("referrer_path")
130
+ pluck_columns = [:referrer_hostname, :referrer_path]
131
+ else
132
+ raise ArgumentError
133
+ end
134
+ when *display_columns
135
+ pluck_columns = [params[:group_by]]
136
+ else
137
+ raise ArgumentError
138
+ end
139
+ end
140
+
141
+ group_by = pluck_columns.dup
142
+
143
+ if difference_where_conditions
144
+ pluck_columns = [aggregate_sql_field]
145
+ else
146
+ pluck_columns << aggregate_sql_field
119
147
  end
120
148
 
121
149
  tracked_requests
122
- .group(*group_by_columns)
150
+ .group(*group_by)
123
151
  .pluck(*pluck_columns)
124
152
  end
125
153
 
@@ -141,5 +169,9 @@ module RailsLocalAnalytics
141
169
  return [prev_start_date, prev_end_date]
142
170
  end
143
171
 
172
+ def display_columns
173
+ @display_columns ||= @klass.display_columns
174
+ end
175
+
144
176
  end
145
177
  end
@@ -1,31 +1,76 @@
1
- <% data_columns = params[:group_by].present? ? [params[:group_by]] : @klass.display_columns %>
2
-
3
- <%= form_tag url_for(params.except(:start_date, :to).to_unsafe_hash), method: "get", class: "well well-sm", id: "search-form" do %>
4
- <div>
5
- <label style="margin-right: 10px;">Group By: <%= select_tag :group_by, options_for_select([["All", nil]] + @klass.display_columns.map{|x| [x.titleize.sub("Url ", "URL "), x]} , params[:group_by]) %></label>
6
-
7
- <label style="margin-right: 10px;">From: <%= date_field_tag :start_date, @start_date %></label>
8
- <label style="margin-right: 10px;">To: <%= date_field_tag :end_date, @end_date %></label>
1
+ <%
2
+ data_columns = params[:group_by].present? ? [params[:group_by]] : display_columns
3
+
4
+ if data_columns.first == "url_hostname_and_path"
5
+ data_columns = ["URL Hostname", "URL Path"]
6
+ elsif data_columns.first == "referrer_hostname_and_path"
7
+ data_columns = ["Referrer Hostname", "Referrer Path"]
8
+ end
9
+ %>
10
+
11
+ <%
12
+ group_by_opts = [
13
+ ["All", nil],
14
+ ]
15
+
16
+ group_by_opts += display_columns.map{|x| [x.titleize.sub("Url ", "URL "), x] }
17
+
18
+ if display_columns.include?("url_hostname") && display_columns.include?("url_path")
19
+ index = group_by_opts.index(["URL Hostname", "url_hostname"])
20
+ group_by_opts.insert(
21
+ index,
22
+ ["URL Hostname and Path", "url_hostname_and_path"],
23
+ )
24
+ end
25
+
26
+ if display_columns.include?("referrer_hostname") && display_columns.include?("referrer_path")
27
+ index = group_by_opts.index(["Referrer Hostname", "referrer_hostname"])
28
+ group_by_opts.insert(
29
+ index,
30
+ ["Referrer Hostname and Path", "referrer_hostname_and_path"],
31
+ )
32
+ end
33
+ %>
34
+
35
+ <div class="well well-sm">
36
+ <%= form_tag url_for(params.except(:start_date, :to).to_unsafe_hash), method: "get", id: "search-form" do %>
37
+ <div>
38
+ <label style="margin-right: 10px;">Group By: <%= select_tag :group_by, options_for_select(group_by_opts, params[:group_by]) %></label>
39
+
40
+ <label style="margin-right: 10px;">From: <%= date_field_tag :start_date, @start_date %></label>
41
+ <label style="margin-right: 10px;">To: <%= date_field_tag :end_date, @end_date %></label>
42
+
43
+ <label style="margin-right: 10px;">Search: <%= text_field_tag :search, params[:search] %></label>
44
+ <% end %>
9
45
 
10
- <label style="margin-right: 10px;">Search: <%= text_field_tag :search, params[:search] %></label>
11
- </div>
46
+ <% if params[:filter] %>
47
+ <div>
48
+ <label>Active Filter:</label>
49
+ <div class="badge badge-primary" style="margin-top: 5px; margin-bottom: 10px;">
50
+ <% filter_col, filter_val = params[:filter].split("==") %>
51
+ <%= filter_col.titleize.sub("Url ", "URL ") %> = "<%= filter_val %>"
52
+ </div>
53
+ <%= link_to "Remove Filter", url_for(params.to_unsafe_h.merge(filter: nil)) %>
54
+ </div>
55
+ <% end %>
12
56
 
13
57
  <div>
14
- <%= link_to "Today", url_for(params.merge(start_date: Date.today, end_date: Date.today).to_unsafe_hash) %>
58
+ <%= link_to "Today", url_for(params.merge(start_date: Date.today, end_date: Date.today).to_unsafe_hash), style: ("font-weight: bold;" if @start_date == Date.today && @end_date == Date.today) %>
15
59
  |
16
- <%= link_to "Yesterday", url_for(params.merge(start_date: (Date.today - 1.day), end_date: (Date.today - 1.day)).to_unsafe_hash) %>
60
+ <% yesterday = Date.today - 1.day %>
61
+ <%= link_to "Yesterday", url_for(params.merge(start_date: yesterday, end_date: yesterday).to_unsafe_hash), style: ("font-weight: bold;" if @start_date == yesterday && @end_date == yesterday) %>
17
62
  |
18
- <%= link_to "Last 7 days", url_for(params.merge(start_date: 7.days.ago.to_date, end_date: Date.today).to_unsafe_hash) %>
63
+ <%= link_to "Last 7 days", url_for(params.merge(start_date: 7.days.ago.to_date, end_date: Date.today).to_unsafe_hash), style: ("font-weight: bold;" if @start_date == 7.days.ago.to_date && @end_date == Date.today) %>
19
64
  |
20
- <%= link_to "Last 30 days", url_for(params.merge(start_date: 30.days.ago.to_date, end_date: Date.today).to_unsafe_hash) %>
65
+ <%= link_to "Last 30 days", url_for(params.merge(start_date: 30.days.ago.to_date, end_date: Date.today).to_unsafe_hash), style: ("font-weight: bold;" if @start_date == 30.days.ago.to_date && @end_date == Date.today) %>
21
66
  |
22
- <%= link_to "Last 3 Months", url_for(params.merge(start_date: 3.months.ago.to_date, end_date: Date.today).to_unsafe_hash) %>
67
+ <%= link_to "Last 3 Months", url_for(params.merge(start_date: 3.months.ago.to_date, end_date: Date.today).to_unsafe_hash), style: ("font-weight: bold;" if @start_date == 3.months.ago.to_date && @end_date == Date.today) %>
23
68
  |
24
- <%= link_to "Last 6 Months", url_for(params.merge(start_date: 6.months.ago.to_date, end_date: Date.today).to_unsafe_hash) %>
69
+ <%= link_to "Last 6 Months", url_for(params.merge(start_date: 6.months.ago.to_date, end_date: Date.today).to_unsafe_hash), style: ("font-weight: bold;" if @start_date == 6.months.ago.to_date && @end_date == Date.today) %>
25
70
  |
26
- <%= link_to "Last Year", url_for(params.merge(start_date: 1.year.ago.to_date, end_date: Date.today).to_unsafe_hash) %>
71
+ <%= link_to "Last Year", url_for(params.merge(start_date: 1.year.ago.to_date, end_date: Date.today).to_unsafe_hash), style: ("font-weight: bold;" if @start_date == 1.year.ago.to_date && @end_date == Date.today) %>
27
72
  </div>
28
- <% end %>
73
+ </div>
29
74
 
30
75
  <h2>Requests by <%= params[:type].titleize %></h2>
31
76
 
@@ -33,7 +78,7 @@
33
78
  <thead>
34
79
  <% data_columns.each do |header| %>
35
80
  <th>
36
- <%= header.sub("Url ", "URL ") %>
81
+ <%= header.titleize.sub("Url ", "URL ") %>
37
82
  </th>
38
83
  <% end %>
39
84
 
@@ -42,22 +87,23 @@
42
87
  </th>
43
88
 
44
89
  <th>
45
- Difference from previous period
90
+ Prev Period Difference
46
91
  </th>
47
92
  </thead>
48
93
 
49
94
  <tbody>
50
95
  <% @results.each_with_index do |row, row_index| %>
51
96
  <tr>
52
- <% row[0..-2].each do |value| %>
97
+ <% row[0..-2].each_with_index do |value, col_index| %>
53
98
  <td>
54
- <%= value %>
99
+ <% filter_param = "#{data_columns[col_index]}==#{value}" %>
100
+ <%= link_to (value || ""), url_for(params.to_unsafe_h.merge(filter: filter_param)), title: "Filter" %>
55
101
  </td>
56
102
  <% end %>
57
103
 
58
104
  <td>
59
105
  <% total = row.last %>
60
- <%= total.to_fs(:delimited) %>
106
+ <%= number_with_delimiter(total) %>
61
107
  </td>
62
108
 
63
109
  <td>
@@ -85,7 +131,7 @@
85
131
  <% prev_period_row_index = @prev_period_results.index{|prev_period_row| row[0..-2] == prev_period_row[0..-2] } %>
86
132
 
87
133
  <% if prev_period_row_index.nil? %>
88
- +<%= total.to_fs(:delimited) %>
134
+ +<%= number_with_delimiter(total) %>
89
135
  <% else %>
90
136
  <% prev_period_row = @prev_period_results.delete_at(prev_period_row_index) %>
91
137
 
@@ -93,9 +139,9 @@
93
139
  <% diff = total - prev_period_total %>
94
140
 
95
141
  <% if diff >= 0 %>
96
- +<%= diff.to_fs(:delimited) %>
142
+ +<%= number_with_delimiter(diff) %>
97
143
  <% else %>
98
- <%= diff.to_fs(:delimited) %>
144
+ <%= number_with_delimiter(diff) %>
99
145
  <% end %>
100
146
  <% end %>
101
147
  <% end %>
@@ -1,3 +1,3 @@
1
1
  module RailsLocalAnalytics
2
- VERSION = "0.2.0".freeze
2
+ VERSION = "0.2.2".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_local_analytics
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Weston Ganger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-12-04 00:00:00.000000000 Z
11
+ date: 2024-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-html-matchers
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: database_cleaner
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -97,7 +111,6 @@ files:
97
111
  - app/controllers/rails_local_analytics/dashboard_controller.rb
98
112
  - app/jobs/rails_local_analytics/application_job.rb
99
113
  - app/jobs/rails_local_analytics/record_request_job.rb
100
- - app/lib/rails_local_analytics/histogram.rb
101
114
  - app/models/rails_local_analytics/application_record.rb
102
115
  - app/models/tracked_requests_by_day_page.rb
103
116
  - app/models/tracked_requests_by_day_site.rb
@@ -1,47 +0,0 @@
1
- module RailsLocalAnalytics
2
- class Histogram
3
- attr_reader :bars, :from_date, :to_date
4
-
5
- def initialize(scope, from_date, to_date)
6
- @scope = scope
7
- @from_date, @to_date = from_date, to_date
8
- @bars = scope.map { |record| Bar.new(record.date, record.total, self) }
9
- fill_missing_days(@bars, @from_date, @to_date)
10
- end
11
-
12
- def fill_missing_days(bars, from, to)
13
- i = 0
14
- while (day = from + i) <= to
15
- if !@bars[i] || @bars[i].label != day
16
- @bars.insert(i, Bar.new(day, 0, self))
17
- end
18
- i += 1
19
- end
20
- @bars
21
- end
22
-
23
- def max_value
24
- @max_total ||= bars.map(&:value).max
25
- end
26
-
27
- def total
28
- @bars.reduce(0) { |sum, bar| sum += bar.value }
29
- end
30
-
31
- class Bar
32
- attr_reader :label, :value, :histogram
33
-
34
- def initialize(label, value, histogram)
35
- @label, @value, @histogram = label, value, histogram
36
- end
37
-
38
- def height
39
- if histogram.max_value > 0
40
- (value.to_f / histogram.max_value).round(2)
41
- else
42
- 0
43
- end
44
- end
45
- end
46
- end
47
- end