Compare commits
2
Commits
collaudo
...
2e67e590d6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e67e590d6 | ||
|
|
bb342ead79 |
@@ -36,6 +36,23 @@ module Admin
|
||||
max_scroll: max_scroll_by_path[path].to_i
|
||||
}
|
||||
end.sort_by { |r| [-r[:pageviews], -r[:moves], -r[:clicks], r[:page_path]] }
|
||||
|
||||
pageviews_by_day = scope.group(:day).sum(:pageview_count)
|
||||
clicks_by_day = cell_scope.group(:day).sum(:click_count)
|
||||
moves_by_day = cell_scope.group(:day).sum(:move_count)
|
||||
@trend = (@filters[:from]..@filters[:to]).map do |day|
|
||||
{
|
||||
day: day.iso8601,
|
||||
pageviews: pageviews_by_day[day].to_i,
|
||||
clicks: clicks_by_day[day].to_i,
|
||||
moves: moves_by_day[day].to_i
|
||||
}
|
||||
end
|
||||
@trend_totals = {
|
||||
pageviews: @trend.sum { |r| r[:pageviews] },
|
||||
clicks: @trend.sum { |r| r[:clicks] },
|
||||
moves: @trend.sum { |r| r[:moves] }
|
||||
}
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@@ -58,6 +58,40 @@
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if @trend.any? && (@trend_totals[:pageviews].positive? || @trend_totals[:clicks].positive? || @trend_totals[:moves].positive?) %>
|
||||
<section class="panel admin-analytics-trend">
|
||||
<h3><%= t("admin.analytics.index.trend_title") %></h3>
|
||||
<p class="muted admin-table-sub"><%= t("admin.analytics.index.trend_lead") %></p>
|
||||
<div class="kpi-grid admin-analytics-trend__kpi">
|
||||
<div class="kpi">
|
||||
<div class="kpi-label"><%= t("admin.analytics.index.table.pageviews") %></div>
|
||||
<div class="kpi-value"><%= @trend_totals[:pageviews] %></div>
|
||||
</div>
|
||||
<div class="kpi">
|
||||
<div class="kpi-label"><%= t("admin.analytics.index.table.clicks") %></div>
|
||||
<div class="kpi-value"><%= @trend_totals[:clicks] %></div>
|
||||
</div>
|
||||
<div class="kpi">
|
||||
<div class="kpi-label"><%= t("admin.analytics.index.table.moves") %></div>
|
||||
<div class="kpi-value"><%= @trend_totals[:moves] %></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chart-wrap chart-wrap--analytics">
|
||||
<canvas id="chart-analytics-trend" aria-label="<%= t("admin.analytics.index.trend_title") %>"></canvas>
|
||||
</div>
|
||||
</section>
|
||||
<script>
|
||||
window.adminAnalyticsTrend = <%= raw @trend.to_json %>;
|
||||
window.adminAnalyticsI18n = {
|
||||
pageviews: <%= raw t("admin.analytics.index.table.pageviews").to_json %>,
|
||||
clicks: <%= raw t("admin.analytics.index.table.clicks").to_json %>,
|
||||
moves: <%= raw t("admin.analytics.index.table.moves").to_json %>
|
||||
};
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js" crossorigin="anonymous"></script>
|
||||
<script src="/admin-analytics.js?v=1" defer></script>
|
||||
<% end %>
|
||||
|
||||
<div class="panel">
|
||||
<% if @pages.any? %>
|
||||
<div class="admin-table-wrap">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
<%= csrf_meta_tags %>
|
||||
<link rel="stylesheet" href="/admin.css?v=16">
|
||||
<link rel="stylesheet" href="/admin.css?v=17">
|
||||
<%= yield :head %>
|
||||
<% if content_for?(:replay_archive_styles) %>
|
||||
<link rel="stylesheet" href="/marketing.css?v=42">
|
||||
|
||||
@@ -427,6 +427,8 @@ de:
|
||||
lead: Aggregierte First-Party-Heatmaps (Bewegung/Klick) und Scrolltiefe, nur mit Statistik-Einwilligung. Keine personenbezogenen Daten.
|
||||
none: Keine Daten im gewählten Zeitraum.
|
||||
heatmap: Heatmap
|
||||
trend_title: Verlauf über die Zeit
|
||||
trend_lead: Tägliche Pageviews, Klicks und Bewegungen im gefilterten Zeitraum.
|
||||
table:
|
||||
path: Seite
|
||||
pageviews: Pageviews
|
||||
|
||||
@@ -427,6 +427,8 @@ en:
|
||||
lead: Aggregated first-party move/click heatmaps and scroll depth, only with analytics consent. No personal data.
|
||||
none: No data in the selected period.
|
||||
heatmap: Heatmap
|
||||
trend_title: Trend over time
|
||||
trend_lead: Daily pageviews, clicks and moves for the filtered period.
|
||||
table:
|
||||
path: Page
|
||||
pageviews: Pageviews
|
||||
|
||||
@@ -427,6 +427,8 @@ es:
|
||||
lead: Heatmaps de movimientos/clics y scroll agregados (first-party), solo con consentimiento estadístico. Sin datos personales.
|
||||
none: No hay datos en el periodo seleccionado.
|
||||
heatmap: Heatmap
|
||||
trend_title: Evolución en el tiempo
|
||||
trend_lead: Pageviews, clics y movimientos día a día en el periodo filtrado.
|
||||
table:
|
||||
path: Página
|
||||
pageviews: Pageviews
|
||||
|
||||
@@ -427,6 +427,8 @@ fr:
|
||||
lead: Heatmaps mouvements/clics et scroll agrégés (first-party), uniquement avec consentement statistiques. Aucune donnée personnelle.
|
||||
none: Aucune donnée sur la période sélectionnée.
|
||||
heatmap: Heatmap
|
||||
trend_title: Évolution dans le temps
|
||||
trend_lead: Pages vues, clics et mouvements par jour sur la période filtrée.
|
||||
table:
|
||||
path: Page
|
||||
pageviews: Pages vues
|
||||
|
||||
@@ -448,6 +448,8 @@ it:
|
||||
lead: Heatmap movimenti/click e scroll aggregati (first-party), solo con consenso statistico. Nessun dato personale.
|
||||
none: Nessun dato nel periodo selezionato.
|
||||
heatmap: Heatmap
|
||||
trend_title: Andamento nel tempo
|
||||
trend_lead: Pageview, click e movimenti giorno per giorno nel periodo filtrato.
|
||||
table:
|
||||
path: Pagina
|
||||
pageviews: Pageview
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
(function () {
|
||||
var trend = window.adminAnalyticsTrend || [];
|
||||
var i18n = window.adminAnalyticsI18n || {};
|
||||
var canvas = document.getElementById("chart-analytics-trend");
|
||||
if (!canvas || !trend.length || typeof Chart === "undefined") return;
|
||||
|
||||
function dayLabel(dayStr) {
|
||||
var parts = dayStr.split("-");
|
||||
if (parts.length < 3) return dayStr;
|
||||
var d = new Date(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10));
|
||||
return d.toLocaleDateString([], { day: "2-digit", month: "short" });
|
||||
}
|
||||
|
||||
var labels = trend.map(function (row) {
|
||||
return dayLabel(row.day);
|
||||
});
|
||||
|
||||
new Chart(canvas, {
|
||||
type: "line",
|
||||
data: {
|
||||
labels: labels,
|
||||
datasets: [
|
||||
{
|
||||
label: i18n.pageviews || "Pageviews",
|
||||
data: trend.map(function (r) { return r.pageviews || 0; }),
|
||||
borderColor: "rgba(229, 57, 53, 0.95)",
|
||||
backgroundColor: "rgba(229, 57, 53, 0.18)",
|
||||
fill: true,
|
||||
tension: 0.25,
|
||||
pointRadius: 3,
|
||||
pointHoverRadius: 5
|
||||
},
|
||||
{
|
||||
label: i18n.clicks || "Clicks",
|
||||
data: trend.map(function (r) { return r.clicks || 0; }),
|
||||
borderColor: "rgba(66, 165, 245, 0.95)",
|
||||
backgroundColor: "transparent",
|
||||
fill: false,
|
||||
tension: 0.25,
|
||||
pointRadius: 2,
|
||||
pointHoverRadius: 4
|
||||
},
|
||||
{
|
||||
label: i18n.moves || "Moves",
|
||||
data: trend.map(function (r) { return r.moves || 0; }),
|
||||
borderColor: "rgba(255, 193, 7, 0.85)",
|
||||
backgroundColor: "transparent",
|
||||
fill: false,
|
||||
tension: 0.25,
|
||||
pointRadius: 2,
|
||||
pointHoverRadius: 4,
|
||||
borderDash: [4, 3]
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
interaction: { mode: "index", intersect: false },
|
||||
animation: { duration: 280 },
|
||||
scales: {
|
||||
x: {
|
||||
ticks: { maxTicksLimit: 14, color: "#9a9aad", font: { size: 10 } },
|
||||
grid: { color: "rgba(255,255,255,0.06)" }
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
ticks: {
|
||||
color: "#9a9aad",
|
||||
font: { size: 10 },
|
||||
precision: 0
|
||||
},
|
||||
grid: { color: "rgba(255,255,255,0.06)" }
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: { labels: { color: "#ccc", boxWidth: 12 } }
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
@@ -173,6 +173,15 @@ body.admin-body {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.chart-wrap--analytics {
|
||||
height: 260px;
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
.admin-analytics-trend__kpi {
|
||||
margin: 0.75rem 0 0;
|
||||
}
|
||||
|
||||
.admin-panels {
|
||||
display: grid;
|
||||
grid-template-columns: 1.4fr 1fr;
|
||||
|
||||
@@ -33,6 +33,25 @@ RSpec.describe "Admin analytics", type: :request do
|
||||
expect(response.body).to include("/prezzi")
|
||||
expect(response.body).to include("12")
|
||||
expect(response.body).to include("40")
|
||||
expect(response.body).to include("chart-analytics-trend")
|
||||
expect(response.body).to include("adminAnalyticsTrend")
|
||||
end
|
||||
|
||||
it "mostra il trend anche su più giorni" do
|
||||
AnalyticsPageStat.create!(
|
||||
day: 1.day.ago.to_date,
|
||||
page_path: "/prezzi",
|
||||
device: "desktop",
|
||||
pageview_count: 5,
|
||||
scroll_samples: 0,
|
||||
scroll_sum_pct: 0,
|
||||
max_scroll_pct: 0
|
||||
)
|
||||
|
||||
get admin_analytics_path, params: { from: 2.days.ago.to_date, to: Time.zone.today }
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(response.body).to include("\"pageviews\":5")
|
||||
expect(response.body).to include("\"pageviews\":12")
|
||||
end
|
||||
|
||||
it "mostra la heatmap di una pagina con tab dispositivo" do
|
||||
|
||||
@@ -24,8 +24,8 @@ android {
|
||||
applicationId = "com.matchlivetv.match_live_tv"
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = 33
|
||||
versionName = "2.0.12-native"
|
||||
versionCode = 34
|
||||
versionName = "2.0.13-native"
|
||||
|
||||
val apiBaseUrl = project.findProperty("API_BASE_URL") as String?
|
||||
?: "https://www.matchlivetv.it"
|
||||
|
||||
Reference in New Issue
Block a user