rails_local_analytics 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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