analytic 0.3.0 → 0.5.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 +4 -4
- data/README.md +98 -11
- data/Rakefile +5 -0
- data/app/assets/images/analytic/icon.svg +1 -0
- data/app/controllers/analytic/dashboard_controller.rb +2 -1
- data/app/controllers/concerns/analytic/trackable.rb +2 -2
- data/app/helpers/analytic/application_helper.rb +42 -0
- data/app/jobs/analytic/track_job.rb +1 -1
- data/app/models/analytic/application_record.rb +2 -0
- data/app/models/analytic/dashboard.rb +61 -29
- data/app/models/analytic/{view.rb → event.rb} +3 -3
- data/app/models/analytic/period.rb +41 -0
- data/app/models/analytic/stat.rb +30 -0
- data/app/packs/analytic/application/components/chart.tsx +148 -0
- data/app/packs/analytic/application/components/index.tsx +21 -0
- data/app/packs/analytic/application/index.ts +1 -0
- data/app/packs/analytic/application/initializers/fontawesome.ts +7 -1
- data/app/packs/analytic/entrypoints/application.tailwind.css +39 -3
- data/app/views/analytic/dashboard/show.html.erb +61 -14
- data/app/views/layouts/analytic/application.html.erb +1 -7
- data/db/migrate/{20240805210911_create_analytic_views.rb → 20240805210911_create_analytic_events.rb} +2 -2
- data/lib/analytic/config.rb +47 -5
- data/lib/analytic/version.rb +1 -1
- metadata +13 -11
- data/app/assets/builds/analytic/application.css +0 -810
- data/app/assets/builds/analytic/application.js +0 -5779
- data/app/assets/builds/analytic/application.js.map +0 -7
@@ -3,8 +3,40 @@
|
|
3
3
|
@tailwind utilities;
|
4
4
|
|
5
5
|
@layer components {
|
6
|
+
.stat {
|
7
|
+
@apply flex gap-2 justify-between items-center;
|
8
|
+
}
|
9
|
+
|
10
|
+
.delta {
|
11
|
+
@apply font-normal flex gap-2 items-center;
|
12
|
+
}
|
13
|
+
|
14
|
+
.delta--neutral {
|
15
|
+
@apply text-slate-400;
|
16
|
+
}
|
17
|
+
|
18
|
+
.delta--positive {
|
19
|
+
@apply text-emerald-600;
|
20
|
+
}
|
21
|
+
|
22
|
+
.delta--negative {
|
23
|
+
@apply text-rose-600;
|
24
|
+
}
|
25
|
+
|
26
|
+
.pills {
|
27
|
+
@apply inline-flex gap-2 bg-slate-100 border-slate-200 rounded-full text-slate-600;
|
28
|
+
}
|
29
|
+
|
6
30
|
.pill {
|
7
|
-
@apply
|
31
|
+
@apply flex items-center justify-center gap-2 rounded-full px-6 py-2;
|
32
|
+
}
|
33
|
+
|
34
|
+
.pill--default {
|
35
|
+
@apply bg-slate-100 font-medium hover:bg-slate-200 hover:text-slate-800;
|
36
|
+
}
|
37
|
+
|
38
|
+
.pill--active {
|
39
|
+
@apply bg-white shadow font-semibold text-slate-800;
|
8
40
|
}
|
9
41
|
|
10
42
|
.card {
|
@@ -20,7 +52,7 @@
|
|
20
52
|
}
|
21
53
|
|
22
54
|
.card__content {
|
23
|
-
@apply px-5 py-4
|
55
|
+
@apply px-5 py-4;
|
24
56
|
}
|
25
57
|
|
26
58
|
.card__title {
|
@@ -28,7 +60,11 @@
|
|
28
60
|
}
|
29
61
|
|
30
62
|
.card__value {
|
31
|
-
@apply
|
63
|
+
@apply text-slate-800 font-extrabold text-lg;
|
64
|
+
}
|
65
|
+
|
66
|
+
.cards {
|
67
|
+
@apply grid gap-4 grid-cols-1 md:grid-cols-3;
|
32
68
|
}
|
33
69
|
|
34
70
|
.table {
|
@@ -1,25 +1,28 @@
|
|
1
1
|
<%- provide(:title, @dashboard.name) %>
|
2
2
|
|
3
3
|
<div class="space-y-4">
|
4
|
-
<div class="
|
5
|
-
<%= link_to '
|
6
|
-
<%= link_to '
|
7
|
-
<%= link_to '
|
8
|
-
<%= link_to '
|
9
|
-
<%= link_to '
|
4
|
+
<div class="pills">
|
5
|
+
<%= link_to 'All', analytic.dashboard_path, class: "pill #{@dashboard.period.nil? ? 'pill--active' : 'pill--default'}" %>
|
6
|
+
<%= link_to '24 hours', analytic.dashboard_path(period: '24h'), class: "pill #{@dashboard.period.eql?('24h') ? 'pill--active' : 'pill--default'}" %>
|
7
|
+
<%= link_to '7 days', analytic.dashboard_path(period: '7d'), class: "pill #{@dashboard.period.eql?('7d') ? 'pill--active' : 'pill--default'}" %>
|
8
|
+
<%= link_to '4 weeks', analytic.dashboard_path(period: '4w'), class: "pill #{@dashboard.period.eql?('4w') ? 'pill--active' : 'pill--default'}" %>
|
9
|
+
<%= link_to '12 months', analytic.dashboard_path(period: '12m'), class: "pill #{@dashboard.period.eql?('12m') ? 'pill--active' : 'pill--default'}" %>
|
10
10
|
</div>
|
11
11
|
|
12
|
-
<div class="
|
12
|
+
<div class="cards">
|
13
13
|
<div class="card">
|
14
14
|
<div class="card__header">
|
15
15
|
<div class="card__title">
|
16
|
-
<%=
|
16
|
+
<%= fa_icon_tag("fa-solid fa-users") %>
|
17
17
|
Visitors
|
18
18
|
</div>
|
19
19
|
</div>
|
20
20
|
<div class="card__content">
|
21
21
|
<div class="card__value">
|
22
|
-
|
22
|
+
<div class="stat">
|
23
|
+
<%= number_with_delimiter @dashboard.visitors.count %>
|
24
|
+
<%= delta_tag(@dashboard.visitors.delta) %>
|
25
|
+
</div>
|
23
26
|
</div>
|
24
27
|
</div>
|
25
28
|
</div>
|
@@ -27,13 +30,16 @@
|
|
27
30
|
<div class="card">
|
28
31
|
<div class="card__header">
|
29
32
|
<div class="card__title">
|
30
|
-
<%=
|
33
|
+
<%= fa_icon_tag("fa-solid fa-globe") %>
|
31
34
|
Sessions
|
32
35
|
</div>
|
33
36
|
</div>
|
34
37
|
<div class="card__content">
|
35
38
|
<div class="card__value">
|
36
|
-
|
39
|
+
<div class="stat">
|
40
|
+
<%= number_with_delimiter @dashboard.sessions.count %>
|
41
|
+
<%= delta_tag(@dashboard.sessions.delta) %>
|
42
|
+
</div>
|
37
43
|
</div>
|
38
44
|
</div>
|
39
45
|
</div>
|
@@ -41,13 +47,16 @@
|
|
41
47
|
<div class="card">
|
42
48
|
<div class="card__header">
|
43
49
|
<div class="card__title">
|
44
|
-
<%=
|
50
|
+
<%= fa_icon_tag("fa-solid fa-eye") %>
|
45
51
|
Views
|
46
52
|
</div>
|
47
53
|
</div>
|
48
54
|
<div class="card__content">
|
49
55
|
<div class="card__value">
|
50
|
-
|
56
|
+
<div class="stat">
|
57
|
+
<%= number_with_delimiter @dashboard.views.count %>
|
58
|
+
<%= delta_tag(@dashboard.views.delta) %>
|
59
|
+
</div>
|
51
60
|
</div>
|
52
61
|
</div>
|
53
62
|
</div>
|
@@ -70,7 +79,7 @@
|
|
70
79
|
</tr>
|
71
80
|
</thead>
|
72
81
|
<tbody>
|
73
|
-
<%- @dashboard.pages.each do |(host, path, views)| -%>
|
82
|
+
<%- @dashboard.current.pages.each do |(host, path, views)| -%>
|
74
83
|
<tr>
|
75
84
|
<td><%= host %></td>
|
76
85
|
<td><%= path %></td>
|
@@ -81,4 +90,42 @@
|
|
81
90
|
</table>
|
82
91
|
</div>
|
83
92
|
</div>
|
93
|
+
|
94
|
+
<div class="cards">
|
95
|
+
<div class="card">
|
96
|
+
<div class="card__header">
|
97
|
+
<div class="card__title">
|
98
|
+
<%= tag.i class: "fa-solid fa-file-code" %>
|
99
|
+
Visitors
|
100
|
+
</div>
|
101
|
+
</div>
|
102
|
+
<div class="card__content">
|
103
|
+
<%= react(component: "Chart") %>
|
104
|
+
</div>
|
105
|
+
</div>
|
106
|
+
|
107
|
+
<div class="card">
|
108
|
+
<div class="card__header">
|
109
|
+
<div class="card__title">
|
110
|
+
<%= tag.i class: "fa-solid fa-globe" %>
|
111
|
+
Sessions
|
112
|
+
</div>
|
113
|
+
</div>
|
114
|
+
<div class="card__content">
|
115
|
+
<%= react(component: "Chart") %>
|
116
|
+
</div>
|
117
|
+
</div>
|
118
|
+
|
119
|
+
<div class="card">
|
120
|
+
<div class="card__header">
|
121
|
+
<div class="card__title">
|
122
|
+
<%= tag.i class: "fa-solid fa-eye" %>
|
123
|
+
Views
|
124
|
+
</div>
|
125
|
+
</div>
|
126
|
+
<div class="card__content">
|
127
|
+
<%= react(component: "Chart") %>
|
128
|
+
</div>
|
129
|
+
</div>
|
130
|
+
</div>
|
84
131
|
</div>
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<%= csp_meta_tag %>
|
7
7
|
<%= javascript_include_tag 'analytic/application' %>
|
8
8
|
<%= stylesheet_link_tag 'analytic/application' %>
|
9
|
-
<%= %>
|
9
|
+
<%= favicon_link_tag 'analytic/icon.svg', type: 'image/svg+xml' %>
|
10
10
|
</head>
|
11
11
|
<body class="bg-slate-50">
|
12
12
|
|
@@ -32,11 +32,5 @@
|
|
32
32
|
<main class="container mx-auto px-4 py-8">
|
33
33
|
<%= yield %>
|
34
34
|
</main>
|
35
|
-
|
36
|
-
<footer class="container mx-auto px-4 text-center">
|
37
|
-
<div class="flex gap-2 justify-center">
|
38
|
-
<%= time_tag(Time.current) %>
|
39
|
-
</div>
|
40
|
-
</footer>
|
41
35
|
</body>
|
42
36
|
</html>
|
data/db/migrate/{20240805210911_create_analytic_views.rb → 20240805210911_create_analytic_events.rb}
RENAMED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class
|
3
|
+
class CreateAnalyticEvents < ActiveRecord::Migration[7.1]
|
4
4
|
def change
|
5
|
-
create_table :
|
5
|
+
create_table :analytic_events do |t|
|
6
6
|
t.uuid :visitor_id, null: false
|
7
7
|
t.uuid :session_id, null: false
|
8
8
|
t.inet :ip, null: false
|
data/lib/analytic/config.rb
CHANGED
@@ -2,19 +2,51 @@
|
|
2
2
|
|
3
3
|
module Analytic
|
4
4
|
class Config
|
5
|
-
# @
|
6
|
-
|
5
|
+
# @example
|
6
|
+
# config.time_zone = ActiveSupport::TimeZone['Tokyo']
|
7
|
+
#
|
8
|
+
# @!attribute [rw] time_zone
|
9
|
+
# @return [ActiveSupport::TimeZone]
|
10
|
+
attr_accessor :time_zone
|
7
11
|
|
8
|
-
# @
|
12
|
+
# @example
|
13
|
+
# config.ip_v4_mask = 24
|
14
|
+
#
|
15
|
+
# @!attribute [rw] ip_v4_mask
|
16
|
+
# @return [Integer]
|
9
17
|
attr_accessor :ip_v4_mask
|
10
18
|
|
11
|
-
# @
|
19
|
+
# @example
|
20
|
+
# config.ip_v6_mask = 48
|
21
|
+
#
|
22
|
+
# @!attribute [rw] ip_v6_mask
|
23
|
+
# @return [Integer]
|
12
24
|
attr_accessor :ip_v6_mask
|
13
25
|
|
26
|
+
# @example
|
27
|
+
# config.connects_to = database: { writing: :primary, reading: :replica }
|
28
|
+
#
|
29
|
+
# @!attribute [rw] connects_to
|
30
|
+
# @return [Hash, nil]
|
31
|
+
attr_accessor :connects_to
|
32
|
+
|
33
|
+
# @!attribute [rw] middleware
|
34
|
+
# @return [Array<Rack::Middleware>]
|
35
|
+
attr_accessor :middleware
|
36
|
+
|
37
|
+
# @example
|
38
|
+
# config.params = %i[utm_source utm_medium utm_campaign utm_content utm_term ref source]
|
39
|
+
#
|
40
|
+
# @!attribute [rw] params
|
41
|
+
# @return [Array<Symbol>]
|
42
|
+
attr_accessor :params
|
43
|
+
|
14
44
|
def initialize
|
15
|
-
@
|
45
|
+
@time_zone = Time.zone
|
16
46
|
@ip_v4_mask = 24 # e.g. 255.255.255.255 => '255.255.255.0/255.255.255.0'
|
17
47
|
@ip_v6_mask = 48 # e.g. 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' => 'ffff:ffff:ffff:0000:0000:0000:0000:0000'
|
48
|
+
@middleware = []
|
49
|
+
@params = %i[utm_source utm_medium utm_campaign utm_content utm_term ref source]
|
18
50
|
end
|
19
51
|
|
20
52
|
# @return [Boolean]
|
@@ -26,5 +58,15 @@ module Analytic
|
|
26
58
|
def ip_v6_mask?
|
27
59
|
@ip_v6_mask.present?
|
28
60
|
end
|
61
|
+
|
62
|
+
# @return [Boolean]
|
63
|
+
def connects_to?
|
64
|
+
@connects_to.present?
|
65
|
+
end
|
66
|
+
|
67
|
+
# @param middleware [Rack::Middleware]
|
68
|
+
def use(*args, &block)
|
69
|
+
middleware << [args, block]
|
70
|
+
end
|
29
71
|
end
|
30
72
|
end
|
data/lib/analytic/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: analytic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Sylvestre
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -34,10 +34,8 @@ files:
|
|
34
34
|
- LICENSE
|
35
35
|
- README.md
|
36
36
|
- Rakefile
|
37
|
-
- app/assets/builds/analytic/application.css
|
38
|
-
- app/assets/builds/analytic/application.js
|
39
|
-
- app/assets/builds/analytic/application.js.map
|
40
37
|
- app/assets/config/analytic_manifest.js
|
38
|
+
- app/assets/images/analytic/icon.svg
|
41
39
|
- app/controllers/analytic/application_controller.rb
|
42
40
|
- app/controllers/analytic/dashboard_controller.rb
|
43
41
|
- app/controllers/concerns/analytic/trackable.rb
|
@@ -47,7 +45,11 @@ files:
|
|
47
45
|
- app/mailers/analytic/application_mailer.rb
|
48
46
|
- app/models/analytic/application_record.rb
|
49
47
|
- app/models/analytic/dashboard.rb
|
50
|
-
- app/models/analytic/
|
48
|
+
- app/models/analytic/event.rb
|
49
|
+
- app/models/analytic/period.rb
|
50
|
+
- app/models/analytic/stat.rb
|
51
|
+
- app/packs/analytic/application/components/chart.tsx
|
52
|
+
- app/packs/analytic/application/components/index.tsx
|
51
53
|
- app/packs/analytic/application/index.ts
|
52
54
|
- app/packs/analytic/application/initializers/fontawesome.ts
|
53
55
|
- app/packs/analytic/application/initializers/index.ts
|
@@ -58,7 +60,7 @@ files:
|
|
58
60
|
- bin/dev
|
59
61
|
- bin/rails
|
60
62
|
- config/routes.rb
|
61
|
-
- db/migrate/
|
63
|
+
- db/migrate/20240805210911_create_analytic_events.rb
|
62
64
|
- lib/analytic.rb
|
63
65
|
- lib/analytic/config.rb
|
64
66
|
- lib/analytic/engine.rb
|
@@ -68,7 +70,7 @@ licenses:
|
|
68
70
|
- MIT
|
69
71
|
metadata:
|
70
72
|
rubygems_mfa_required: 'true'
|
71
|
-
post_install_message:
|
73
|
+
post_install_message:
|
72
74
|
rdoc_options: []
|
73
75
|
require_paths:
|
74
76
|
- lib
|
@@ -83,8 +85,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
85
|
- !ruby/object:Gem::Version
|
84
86
|
version: '0'
|
85
87
|
requirements: []
|
86
|
-
rubygems_version: 3.5.
|
87
|
-
signing_key:
|
88
|
+
rubygems_version: 3.5.18
|
89
|
+
signing_key:
|
88
90
|
specification_version: 4
|
89
91
|
summary: Analytic
|
90
92
|
test_files: []
|