trackguard 0.21.0 → 0.22.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/app/assets/stylesheets/trackguard/admin.css +2 -2
- data/app/helpers/trackguard/application_helper.rb +20 -0
- data/app/views/layouts/trackguard/admin.html.erb +1 -6
- data/app/views/trackguard/admin/_nav.html.erb +7 -0
- data/app/views/trackguard/admin/_stats_panel.html.erb +27 -0
- data/app/views/trackguard/admin/_visit_row.html.erb +15 -9
- data/app/views/trackguard/admin/dashboards/_body.html.erb +38 -0
- data/app/views/trackguard/admin/dashboards/show.html.erb +1 -106
- data/app/views/trackguard/admin/visits/_body.html.erb +15 -0
- data/app/views/trackguard/admin/visits/_pagination.html.erb +6 -5
- data/app/views/trackguard/admin/visits/index.html.erb +1 -16
- data/lib/trackguard/version.rb +1 -1
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d17d909f51f058510417e8624ab06dbab2c6aaef25335d4e1b5aee1611452cf6
|
|
4
|
+
data.tar.gz: d39ced082e7e2a16ddf4f08d0681cafe34517cf04811777bc9e99b93623b8f0a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5e942af4746f0198a375fdef13011e65afd2e07b80a4663e1b4a1cb0b6f8c87857818b0f4d3f4e960386221aeb06a889d0c67c89f647ce640473191eb676560c
|
|
7
|
+
data.tar.gz: 3bb04dd3cdeee9f5a304e0160a5ab4a7aa16f1a5b8889f0f4bbb671b4d428d1e8fa10667f3693b943fb807ae4401fe949ed01acd2c0d7f33d075146660adf20f
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
|
|
16
16
|
/* ── Layout ────────────────────────────────────────────────────────── */
|
|
17
17
|
.tg-container {
|
|
18
|
-
max-width: 1100px;
|
|
18
|
+
max-width: var(--tg-container-max-width, 1100px);
|
|
19
19
|
margin: 0 auto;
|
|
20
|
-
padding: 0 1.5rem;
|
|
20
|
+
padding: 0 var(--tg-container-padding, 1.5rem);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/* ── Header ────────────────────────────────────────────────────────── */
|
|
@@ -6,5 +6,25 @@ module Trackguard
|
|
|
6
6
|
tag.meta(name: "trace-id", content: @trace_id)
|
|
7
7
|
], "\n")
|
|
8
8
|
end
|
|
9
|
+
|
|
10
|
+
def trackguard_nav_links
|
|
11
|
+
[
|
|
12
|
+
{ label: "Dashboard", url: dashboard_path, active: request.path == dashboard_path },
|
|
13
|
+
{ label: "All Visits", url: visits_path, active: request.path.start_with?(visits_path) }
|
|
14
|
+
]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def trackguard_visits_page_url
|
|
18
|
+
->(n) { visits_path(page: n) }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def trackguard_visit_row_actions(visitor)
|
|
22
|
+
{
|
|
23
|
+
flag: { url: flag_visitor_path, method: :patch, params: { id: visitor.id } },
|
|
24
|
+
unflag: { url: unflag_visitor_path, method: :patch, params: { id: visitor.id } },
|
|
25
|
+
whitelist: { url: whitelist_visitor_path, method: :patch, params: { id: visitor.id } },
|
|
26
|
+
unwhitelist: { url: unwhitelist_visitor_path, method: :patch, params: { id: visitor.id } }
|
|
27
|
+
}
|
|
28
|
+
end
|
|
9
29
|
end
|
|
10
30
|
end
|
|
@@ -25,12 +25,7 @@
|
|
|
25
25
|
</div>
|
|
26
26
|
</div>
|
|
27
27
|
</header>
|
|
28
|
-
|
|
29
|
-
<div class="tg-container">
|
|
30
|
-
<a href="<%= dashboard_path %>" class="tg-nav__link<%= ' tg-nav__link--active' if request.path == dashboard_path %>">Dashboard</a>
|
|
31
|
-
<a href="<%= visits_path %>" class="tg-nav__link<%= ' tg-nav__link--active' if request.path.start_with?(visits_path) %>">All Visits</a>
|
|
32
|
-
</div>
|
|
33
|
-
</nav>
|
|
28
|
+
<%= render "trackguard/admin/nav" %>
|
|
34
29
|
<main class="tg-main">
|
|
35
30
|
<div class="tg-container">
|
|
36
31
|
<%= yield %>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<div class="tg-panel">
|
|
2
|
+
<h2 class="tg-panel__heading">
|
|
3
|
+
<%= title %><% if local_assigns[:subtitle] %> <span class="tg-panel__sub"><%= subtitle %></span><% end %>
|
|
4
|
+
</h2>
|
|
5
|
+
<% if rows.any? %>
|
|
6
|
+
<table class="tg-table">
|
|
7
|
+
<% if local_assigns[:row_label] %>
|
|
8
|
+
<thead>
|
|
9
|
+
<tr>
|
|
10
|
+
<th class="tg-th"><%= row_label %></th>
|
|
11
|
+
<th class="tg-th tg-th--right">Views</th>
|
|
12
|
+
</tr>
|
|
13
|
+
</thead>
|
|
14
|
+
<% end %>
|
|
15
|
+
<tbody>
|
|
16
|
+
<% rows.each do |label, count| %>
|
|
17
|
+
<tr>
|
|
18
|
+
<td class="tg-td"><%= label %></td>
|
|
19
|
+
<td class="tg-td tg-td--num"><%= count %></td>
|
|
20
|
+
</tr>
|
|
21
|
+
<% end %>
|
|
22
|
+
</tbody>
|
|
23
|
+
</table>
|
|
24
|
+
<% else %>
|
|
25
|
+
<p class="tg-empty"><%= local_assigns.fetch(:empty_message, "No data yet.") %></p>
|
|
26
|
+
<% end %>
|
|
27
|
+
</div>
|
|
@@ -31,25 +31,31 @@
|
|
|
31
31
|
</summary>
|
|
32
32
|
<div class="tg-detail">
|
|
33
33
|
<% if visitor %>
|
|
34
|
+
<% _actions = trackguard_visit_row_actions(visitor) %>
|
|
34
35
|
<div class="tg-detail__actions">
|
|
35
36
|
<% if whitelisted %>
|
|
36
|
-
<%= button_to "Remove from whitelist",
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
<%= button_to "Remove from whitelist", _actions[:unwhitelist][:url],
|
|
38
|
+
method: _actions[:unwhitelist][:method],
|
|
39
|
+
params: _actions[:unwhitelist][:params],
|
|
39
40
|
class: "tg-btn tg-btn--ghost",
|
|
40
41
|
data: { confirm: "Remove whitelist entry for #{visitor.ip}?" } %>
|
|
41
42
|
<% else %>
|
|
42
|
-
<%= button_to "Whitelist",
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
<%= button_to "Whitelist", _actions[:whitelist][:url],
|
|
44
|
+
method: _actions[:whitelist][:method],
|
|
45
|
+
params: _actions[:whitelist][:params],
|
|
45
46
|
class: "tg-btn tg-btn--whitelist",
|
|
46
47
|
data: { confirm: "Whitelist #{visitor.ip} for 7 days?" } %>
|
|
47
48
|
<% end %>
|
|
48
49
|
<% if flagged %>
|
|
49
|
-
<%= button_to "Unflag",
|
|
50
|
+
<%= button_to "Unflag", _actions[:unflag][:url],
|
|
51
|
+
method: _actions[:unflag][:method],
|
|
52
|
+
params: _actions[:unflag][:params],
|
|
53
|
+
class: "tg-btn tg-btn--ghost" %>
|
|
50
54
|
<% else %>
|
|
51
|
-
<%= form_with url:
|
|
52
|
-
|
|
55
|
+
<%= form_with url: _actions[:flag][:url], method: _actions[:flag][:method], class: "tg-flag-form" do |f| %>
|
|
56
|
+
<% (_actions[:flag][:params] || {}).each do |k, v| %>
|
|
57
|
+
<%= hidden_field_tag k, v %>
|
|
58
|
+
<% end %>
|
|
53
59
|
<%= f.submit "Flag", class: "tg-btn tg-btn--danger" %>
|
|
54
60
|
<%= f.text_field :flag_reason, placeholder: "Flag reason (optional)", class: "tg-input", autocomplete: "off" %>
|
|
55
61
|
<%= f.text_field :name, placeholder: "Name (optional, auto-detected if blank)", class: "tg-input", autocomplete: "off" %>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<%# Summary cards %>
|
|
2
|
+
<div class="tg-stats">
|
|
3
|
+
<div class="tg-stat">
|
|
4
|
+
<p class="tg-stat__label">Today</p>
|
|
5
|
+
<p class="tg-stat__value"><%= @total_today %></p>
|
|
6
|
+
</div>
|
|
7
|
+
<div class="tg-stat">
|
|
8
|
+
<p class="tg-stat__label">This Week</p>
|
|
9
|
+
<p class="tg-stat__value"><%= @total_week %></p>
|
|
10
|
+
</div>
|
|
11
|
+
<div class="tg-stat">
|
|
12
|
+
<p class="tg-stat__label">This Month</p>
|
|
13
|
+
<p class="tg-stat__value"><%= @total_month %></p>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<%# Top pages / referrers / sources grid %>
|
|
18
|
+
<div class="tg-panels">
|
|
19
|
+
<%= render "trackguard/admin/stats_panel", title: "Top Pages", subtitle: "last 30 days", rows: @top_pages, row_label: "Path" %>
|
|
20
|
+
<%= render "trackguard/admin/stats_panel", title: "Top Referrers", subtitle: "last 30 days", rows: @top_referrers, row_label: "Referrer" %>
|
|
21
|
+
<%= render "trackguard/admin/stats_panel", title: "Top Sources", subtitle: "last 30 days", rows: @top_sources, row_label: "Source" %>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<%# Recent visits %>
|
|
25
|
+
<div class="tg-panel">
|
|
26
|
+
<h2 class="tg-panel__heading">Recent Visits</h2>
|
|
27
|
+
<% if @recent.any? %>
|
|
28
|
+
<table class="tg-table">
|
|
29
|
+
<tbody>
|
|
30
|
+
<% @recent.each do |pv| %>
|
|
31
|
+
<%= render "trackguard/admin/visit_row", pv: pv %>
|
|
32
|
+
<% end %>
|
|
33
|
+
</tbody>
|
|
34
|
+
</table>
|
|
35
|
+
<% else %>
|
|
36
|
+
<p class="tg-empty">No visits recorded yet.</p>
|
|
37
|
+
<% end %>
|
|
38
|
+
</div>
|
|
@@ -1,108 +1,3 @@
|
|
|
1
1
|
<% content_for :title, "Trackguard" %>
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
<div class="tg-stats">
|
|
5
|
-
<div class="tg-stat">
|
|
6
|
-
<p class="tg-stat__label">Today</p>
|
|
7
|
-
<p class="tg-stat__value"><%= @total_today %></p>
|
|
8
|
-
</div>
|
|
9
|
-
<div class="tg-stat">
|
|
10
|
-
<p class="tg-stat__label">This Week</p>
|
|
11
|
-
<p class="tg-stat__value"><%= @total_week %></p>
|
|
12
|
-
</div>
|
|
13
|
-
<div class="tg-stat">
|
|
14
|
-
<p class="tg-stat__label">This Month</p>
|
|
15
|
-
<p class="tg-stat__value"><%= @total_month %></p>
|
|
16
|
-
</div>
|
|
17
|
-
</div>
|
|
18
|
-
|
|
19
|
-
<%# Top pages / referrers / sources grid %>
|
|
20
|
-
<div class="tg-panels">
|
|
21
|
-
<div class="tg-panel">
|
|
22
|
-
<h2 class="tg-panel__heading">Top Pages <span class="tg-panel__sub">last 30 days</span></h2>
|
|
23
|
-
<% if @top_pages.any? %>
|
|
24
|
-
<table class="tg-table">
|
|
25
|
-
<thead>
|
|
26
|
-
<tr>
|
|
27
|
-
<th class="tg-th">Path</th>
|
|
28
|
-
<th class="tg-th tg-th--right">Views</th>
|
|
29
|
-
</tr>
|
|
30
|
-
</thead>
|
|
31
|
-
<tbody>
|
|
32
|
-
<% @top_pages.each do |path, count| %>
|
|
33
|
-
<tr>
|
|
34
|
-
<td class="tg-td"><%= path %></td>
|
|
35
|
-
<td class="tg-td tg-td--num"><%= count %></td>
|
|
36
|
-
</tr>
|
|
37
|
-
<% end %>
|
|
38
|
-
</tbody>
|
|
39
|
-
</table>
|
|
40
|
-
<% else %>
|
|
41
|
-
<p class="tg-empty">No data yet.</p>
|
|
42
|
-
<% end %>
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
<div class="tg-panel">
|
|
46
|
-
<h2 class="tg-panel__heading">Top Referrers <span class="tg-panel__sub">last 30 days</span></h2>
|
|
47
|
-
<% if @top_referrers.any? %>
|
|
48
|
-
<table class="tg-table">
|
|
49
|
-
<thead>
|
|
50
|
-
<tr>
|
|
51
|
-
<th class="tg-th">Referrer</th>
|
|
52
|
-
<th class="tg-th tg-th--right">Views</th>
|
|
53
|
-
</tr>
|
|
54
|
-
</thead>
|
|
55
|
-
<tbody>
|
|
56
|
-
<% @top_referrers.each do |referer, count| %>
|
|
57
|
-
<tr>
|
|
58
|
-
<td class="tg-td tg-td--break"><%= referer %></td>
|
|
59
|
-
<td class="tg-td tg-td--num"><%= count %></td>
|
|
60
|
-
</tr>
|
|
61
|
-
<% end %>
|
|
62
|
-
</tbody>
|
|
63
|
-
</table>
|
|
64
|
-
<% else %>
|
|
65
|
-
<p class="tg-empty">No referrer data yet.</p>
|
|
66
|
-
<% end %>
|
|
67
|
-
</div>
|
|
68
|
-
|
|
69
|
-
<div class="tg-panel">
|
|
70
|
-
<h2 class="tg-panel__heading">Top Sources <span class="tg-panel__sub">last 30 days</span></h2>
|
|
71
|
-
<% if @top_sources.any? %>
|
|
72
|
-
<table class="tg-table">
|
|
73
|
-
<thead>
|
|
74
|
-
<tr>
|
|
75
|
-
<th class="tg-th">Source</th>
|
|
76
|
-
<th class="tg-th tg-th--right">Views</th>
|
|
77
|
-
</tr>
|
|
78
|
-
</thead>
|
|
79
|
-
<tbody>
|
|
80
|
-
<% @top_sources.each do |source, count| %>
|
|
81
|
-
<tr>
|
|
82
|
-
<td class="tg-td"><%= source %></td>
|
|
83
|
-
<td class="tg-td tg-td--num"><%= count %></td>
|
|
84
|
-
</tr>
|
|
85
|
-
<% end %>
|
|
86
|
-
</tbody>
|
|
87
|
-
</table>
|
|
88
|
-
<% else %>
|
|
89
|
-
<p class="tg-empty">No source data yet.</p>
|
|
90
|
-
<% end %>
|
|
91
|
-
</div>
|
|
92
|
-
</div>
|
|
93
|
-
|
|
94
|
-
<%# Recent visits %>
|
|
95
|
-
<div class="tg-panel">
|
|
96
|
-
<h2 class="tg-panel__heading">Recent Visits</h2>
|
|
97
|
-
<% if @recent.any? %>
|
|
98
|
-
<table class="tg-table">
|
|
99
|
-
<tbody>
|
|
100
|
-
<% @recent.each do |pv| %>
|
|
101
|
-
<%= render "trackguard/admin/visit_row", pv: pv %>
|
|
102
|
-
<% end %>
|
|
103
|
-
</tbody>
|
|
104
|
-
</table>
|
|
105
|
-
<% else %>
|
|
106
|
-
<p class="tg-empty">No visits recorded yet.</p>
|
|
107
|
-
<% end %>
|
|
108
|
-
</div>
|
|
3
|
+
<%= render "trackguard/admin/dashboards/body" %>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<div class="tg-panel">
|
|
2
|
+
<% if @visits.any? %>
|
|
3
|
+
<%= render "trackguard/admin/visits/pagination", page_url: trackguard_visits_page_url %>
|
|
4
|
+
<table class="tg-table">
|
|
5
|
+
<tbody>
|
|
6
|
+
<% @visits.each do |pv| %>
|
|
7
|
+
<%= render "trackguard/admin/visit_row", pv: pv %>
|
|
8
|
+
<% end %>
|
|
9
|
+
</tbody>
|
|
10
|
+
</table>
|
|
11
|
+
<%= render "trackguard/admin/visits/pagination", page_url: trackguard_visits_page_url %>
|
|
12
|
+
<% else %>
|
|
13
|
+
<p class="tg-empty">No visits recorded yet.</p>
|
|
14
|
+
<% end %>
|
|
15
|
+
</div>
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
<% page_url = local_assigns.fetch(:page_url) { ->(n) { visits_path(page: n) } } %>
|
|
1
2
|
<% if @pages > 1 %>
|
|
2
3
|
<% window_start = [ @page - 1, 2 ].max %>
|
|
3
4
|
<% window_end = [ @page + 1, @pages - 1 ].min %>
|
|
4
5
|
<nav class="tg-pagination" aria-label="Pagination">
|
|
5
6
|
<% if @page > 1 %>
|
|
6
|
-
<a href="<%=
|
|
7
|
+
<a href="<%= page_url.call(@page - 1) %>" class="tg-pagination__link">← Prev</a>
|
|
7
8
|
<% else %>
|
|
8
9
|
<span class="tg-pagination__link tg-pagination__link--disabled">← Prev</span>
|
|
9
10
|
<% end %>
|
|
@@ -12,7 +13,7 @@
|
|
|
12
13
|
<% if @page == 1 %>
|
|
13
14
|
<span class="tg-pagination__link tg-pagination__link--active">1</span>
|
|
14
15
|
<% else %>
|
|
15
|
-
<a href="<%=
|
|
16
|
+
<a href="<%= page_url.call(1) %>" class="tg-pagination__link">1</a>
|
|
16
17
|
<% end %>
|
|
17
18
|
|
|
18
19
|
<% if window_start > 2 %>
|
|
@@ -24,7 +25,7 @@
|
|
|
24
25
|
<% if n == @page %>
|
|
25
26
|
<span class="tg-pagination__link tg-pagination__link--active"><%= n %></span>
|
|
26
27
|
<% else %>
|
|
27
|
-
<a href="<%=
|
|
28
|
+
<a href="<%= page_url.call(n) %>" class="tg-pagination__link"><%= n %></a>
|
|
28
29
|
<% end %>
|
|
29
30
|
<% end %>
|
|
30
31
|
|
|
@@ -36,11 +37,11 @@
|
|
|
36
37
|
<% if @page == @pages %>
|
|
37
38
|
<span class="tg-pagination__link tg-pagination__link--active"><%= @pages %></span>
|
|
38
39
|
<% else %>
|
|
39
|
-
<a href="<%=
|
|
40
|
+
<a href="<%= page_url.call(@pages) %>" class="tg-pagination__link"><%= @pages %></a>
|
|
40
41
|
<% end %>
|
|
41
42
|
|
|
42
43
|
<% if @page < @pages %>
|
|
43
|
-
<a href="<%=
|
|
44
|
+
<a href="<%= page_url.call(@page + 1) %>" class="tg-pagination__link">Next →</a>
|
|
44
45
|
<% else %>
|
|
45
46
|
<span class="tg-pagination__link tg-pagination__link--disabled">Next →</span>
|
|
46
47
|
<% end %>
|
|
@@ -4,19 +4,4 @@
|
|
|
4
4
|
<h1 class="tg-page-title">All Visits <span class="tg-page-title__count"><%= @total %></span></h1>
|
|
5
5
|
</div>
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
<% if @visits.any? %>
|
|
9
|
-
<%= render "pagination" %>
|
|
10
|
-
<table class="tg-table">
|
|
11
|
-
<tbody>
|
|
12
|
-
<% @visits.each do |pv| %>
|
|
13
|
-
<%= render "trackguard/admin/visit_row", pv: pv %>
|
|
14
|
-
<% end %>
|
|
15
|
-
</tbody>
|
|
16
|
-
</table>
|
|
17
|
-
|
|
18
|
-
<%= render "pagination" %>
|
|
19
|
-
<% else %>
|
|
20
|
-
<p class="tg-empty">No visits recorded yet.</p>
|
|
21
|
-
<% end %>
|
|
22
|
-
</div>
|
|
7
|
+
<%= render "trackguard/admin/visits/body" %>
|
data/lib/trackguard/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: trackguard
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.22.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Krzysztof Rygielski
|
|
@@ -70,8 +70,12 @@ files:
|
|
|
70
70
|
- app/services/trackguard/application_service.rb
|
|
71
71
|
- app/services/trackguard/page_view_recorder.rb
|
|
72
72
|
- app/views/layouts/trackguard/admin.html.erb
|
|
73
|
+
- app/views/trackguard/admin/_nav.html.erb
|
|
74
|
+
- app/views/trackguard/admin/_stats_panel.html.erb
|
|
73
75
|
- app/views/trackguard/admin/_visit_row.html.erb
|
|
76
|
+
- app/views/trackguard/admin/dashboards/_body.html.erb
|
|
74
77
|
- app/views/trackguard/admin/dashboards/show.html.erb
|
|
78
|
+
- app/views/trackguard/admin/visits/_body.html.erb
|
|
75
79
|
- app/views/trackguard/admin/visits/_pagination.html.erb
|
|
76
80
|
- app/views/trackguard/admin/visits/index.html.erb
|
|
77
81
|
- config/importmap.rb
|