Semplifica il grafico analytics: solo pageview e toggle nascondi.
Chiarisce che il totale è su tutte le pagine (filtri Da/A/Device), distinto dal dettaglio per path. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -58,42 +58,48 @@
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if @trend.any? && (@trend_totals[:pageviews].positive? || @trend_totals[:clicks].positive? || @trend_totals[:moves].positive?) %>
|
||||
<section class="panel admin-analytics-trend">
|
||||
<% if @trend.any? && @trend_totals[:pageviews].positive? %>
|
||||
<section class="panel admin-analytics-trend" id="admin-analytics-trend">
|
||||
<div class="admin-analytics-trend__head">
|
||||
<div>
|
||||
<h3><%= t("admin.analytics.index.trend_title") %></h3>
|
||||
<p class="muted admin-table-sub"><%= t("admin.analytics.index.trend_lead") %></p>
|
||||
</div>
|
||||
<button type="button"
|
||||
id="admin-analytics-trend-toggle"
|
||||
class="admin-btn admin-btn--outline admin-btn--sm"
|
||||
aria-controls="admin-analytics-trend-body"
|
||||
aria-expanded="true"><%= t("admin.analytics.index.hide_chart") %></button>
|
||||
</div>
|
||||
<div id="admin-analytics-trend-body">
|
||||
<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-label"><%= t("admin.analytics.index.trend_total_label") %></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 class="kpi-sub muted"><%= t("admin.analytics.index.trend_total_hint", from: l(@filters[:from]), to: l(@filters[:to])) %></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>
|
||||
</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 %>
|
||||
hideChart: <%= raw t("admin.analytics.index.hide_chart").to_json %>,
|
||||
showChart: <%= raw t("admin.analytics.index.show_chart").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>
|
||||
<script src="/admin-analytics.js?v=2" defer></script>
|
||||
<% end %>
|
||||
|
||||
<div class="panel">
|
||||
<% if @pages.any? %>
|
||||
<h3 class="admin-analytics-pages-title"><%= t("admin.analytics.index.pages_title") %></h3>
|
||||
<p class="muted admin-table-sub"><%= t("admin.analytics.index.pages_lead") %></p>
|
||||
<div class="admin-table-wrap">
|
||||
<table class="admin-table">
|
||||
<thead>
|
||||
|
||||
@@ -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=17">
|
||||
<link rel="stylesheet" href="/admin.css?v=18">
|
||||
<%= yield :head %>
|
||||
<% if content_for?(:replay_archive_styles) %>
|
||||
<link rel="stylesheet" href="/marketing.css?v=42">
|
||||
|
||||
@@ -427,8 +427,14 @@ 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.
|
||||
trend_title: Pageview-Verlauf
|
||||
trend_lead: Gesamte Pageviews aller Seiten, Tag für Tag. Dieselben Filter Von / Bis / Gerät. Nicht mit einer Tabellenzeile vergleichbar (die nach Pfad trennt).
|
||||
trend_total_label: Pageviews gesamt (alle Seiten)
|
||||
trend_total_hint: "%{from} → %{to}"
|
||||
hide_chart: Diagramm ausblenden
|
||||
show_chart: Diagramm anzeigen
|
||||
pages_title: Aufschlüsselung nach Seite
|
||||
pages_lead: Pageviews und Engagement im gefilterten Zeitraum, nach Pfad. Die Summe der Pageview-Zeilen entspricht dem Diagramm-Total.
|
||||
table:
|
||||
path: Seite
|
||||
pageviews: Pageviews
|
||||
|
||||
@@ -427,8 +427,14 @@ 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.
|
||||
trend_title: Pageview trend
|
||||
trend_lead: Total pageviews across all pages, day by day. Uses the same From / To / Device filters. Not comparable to a single table row (which splits by path).
|
||||
trend_total_label: Total pageviews (all pages)
|
||||
trend_total_hint: "%{from} → %{to}"
|
||||
hide_chart: Hide chart
|
||||
show_chart: Show chart
|
||||
pages_title: Breakdown by page
|
||||
pages_lead: Pageviews and engagement for the filtered period, split by path. The sum of pageview rows matches the chart total.
|
||||
table:
|
||||
path: Page
|
||||
pageviews: Pageviews
|
||||
|
||||
@@ -427,8 +427,14 @@ 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.
|
||||
trend_title: Evolución de pageviews
|
||||
trend_lead: Total de pageviews de todas las páginas, día a día. Usa los mismos filtros Desde / Hasta / Device. No es comparable con una fila de la tabla (que parte por path).
|
||||
trend_total_label: Pageviews totales (todas las páginas)
|
||||
trend_total_hint: "%{from} → %{to}"
|
||||
hide_chart: Ocultar gráfico
|
||||
show_chart: Mostrar gráfico
|
||||
pages_title: Detalle por página
|
||||
pages_lead: Pageviews y engagement en el periodo filtrado, por path. La suma de las filas coincide con el total del gráfico.
|
||||
table:
|
||||
path: Página
|
||||
pageviews: Pageviews
|
||||
|
||||
@@ -427,8 +427,14 @@ 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.
|
||||
trend_title: Évolution des pages vues
|
||||
trend_lead: Total des pages vues sur toutes les pages, jour par jour. Mêmes filtres De / À / Appareil. Non comparable à une ligne du tableau (découpée par chemin).
|
||||
trend_total_label: Pages vues totales (toutes les pages)
|
||||
trend_total_hint: "%{from} → %{to}"
|
||||
hide_chart: Masquer le graphique
|
||||
show_chart: Afficher le graphique
|
||||
pages_title: Détail par page
|
||||
pages_lead: Pages vues et engagement sur la période filtrée, par chemin. La somme des lignes égale le total du graphique.
|
||||
table:
|
||||
path: Page
|
||||
pageviews: Pages vues
|
||||
|
||||
@@ -448,8 +448,14 @@ 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.
|
||||
trend_title: Andamento pageview
|
||||
trend_lead: Totale pageview di tutte le pagine, giorno per giorno. Usa gli stessi filtri Da / A / Device. Non è confrontabile con una singola riga della tabella (che spezza per path).
|
||||
trend_total_label: Pageview totali (tutte le pagine)
|
||||
trend_total_hint: "%{from} → %{to}"
|
||||
hide_chart: Nascondi grafico
|
||||
show_chart: Mostra grafico
|
||||
pages_title: Dettaglio per pagina
|
||||
pages_lead: Pageview e engagement nel periodo filtrato, spezzati per path. La somma delle pageview delle righe coincide col totale del grafico.
|
||||
table:
|
||||
path: Pagina
|
||||
pageviews: Pageview
|
||||
|
||||
@@ -1,7 +1,40 @@
|
||||
(function () {
|
||||
var STORAGE_KEY = "mltv_admin_analytics_chart_hidden";
|
||||
var trend = window.adminAnalyticsTrend || [];
|
||||
var i18n = window.adminAnalyticsI18n || {};
|
||||
var panel = document.getElementById("admin-analytics-trend");
|
||||
var canvas = document.getElementById("chart-analytics-trend");
|
||||
var toggle = document.getElementById("admin-analytics-trend-toggle");
|
||||
var body = document.getElementById("admin-analytics-trend-body");
|
||||
|
||||
function setHidden(hidden) {
|
||||
if (!panel || !body || !toggle) return;
|
||||
body.hidden = hidden;
|
||||
panel.classList.toggle("is-collapsed", hidden);
|
||||
toggle.setAttribute("aria-expanded", hidden ? "false" : "true");
|
||||
toggle.textContent = hidden
|
||||
? (i18n.showChart || "Mostra grafico")
|
||||
: (i18n.hideChart || "Nascondi grafico");
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY, hidden ? "1" : "0");
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
function initiallyHidden() {
|
||||
try {
|
||||
return localStorage.getItem(STORAGE_KEY) === "1";
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (toggle && body) {
|
||||
setHidden(initiallyHidden());
|
||||
toggle.addEventListener("click", function () {
|
||||
setHidden(!body.hidden);
|
||||
});
|
||||
}
|
||||
|
||||
if (!canvas || !trend.length || typeof Chart === "undefined") return;
|
||||
|
||||
function dayLabel(dayStr) {
|
||||
@@ -11,14 +44,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,
|
||||
labels: trend.map(function (row) { return dayLabel(row.day); }),
|
||||
datasets: [
|
||||
{
|
||||
label: i18n.pageviews || "Pageviews",
|
||||
@@ -29,27 +58,6 @@
|
||||
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]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -74,7 +82,7 @@
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: { labels: { color: "#ccc", boxWidth: 12 } }
|
||||
legend: { display: false }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -178,10 +178,31 @@ body.admin-body {
|
||||
margin-top: 0.75rem;
|
||||
}
|
||||
|
||||
.admin-analytics-trend__head {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.admin-analytics-trend__head h3 {
|
||||
margin: 0 0 0.35rem;
|
||||
}
|
||||
|
||||
.admin-analytics-trend__kpi {
|
||||
margin: 0.75rem 0 0;
|
||||
}
|
||||
|
||||
.admin-analytics-trend.is-collapsed .admin-analytics-trend__head {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.admin-analytics-pages-title {
|
||||
margin: 0 0 0.35rem;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.admin-panels {
|
||||
display: grid;
|
||||
grid-template-columns: 1.4fr 1fr;
|
||||
|
||||
@@ -7,6 +7,8 @@ RSpec.describe "Admin analytics", type: :request do
|
||||
|
||||
before do
|
||||
post admin_login_path, params: { username: admin.username, password: "Password123" }
|
||||
AnalyticsPageStat.delete_all
|
||||
AnalyticsPageCell.delete_all
|
||||
AnalyticsPageStat.create!(
|
||||
day: Time.zone.today,
|
||||
page_path: "/prezzi",
|
||||
@@ -35,9 +37,12 @@ RSpec.describe "Admin analytics", type: :request do
|
||||
expect(response.body).to include("40")
|
||||
expect(response.body).to include("chart-analytics-trend")
|
||||
expect(response.body).to include("adminAnalyticsTrend")
|
||||
expect(response.body).to include(I18n.t("admin.analytics.index.hide_chart"))
|
||||
expect(response.body).to include("hideChart")
|
||||
expect(response.body).not_to include("clicks:")
|
||||
end
|
||||
|
||||
it "mostra il trend anche su più giorni" do
|
||||
it "il grafico rispetta i filtri data e aggrega pageview di tutte le pagine" do
|
||||
AnalyticsPageStat.create!(
|
||||
day: 1.day.ago.to_date,
|
||||
page_path: "/prezzi",
|
||||
@@ -47,13 +52,25 @@ RSpec.describe "Admin analytics", type: :request do
|
||||
scroll_sum_pct: 0,
|
||||
max_scroll_pct: 0
|
||||
)
|
||||
AnalyticsPageStat.create!(
|
||||
day: Time.zone.today,
|
||||
page_path: "/altro",
|
||||
device: "desktop",
|
||||
pageview_count: 7,
|
||||
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(I18n.t("admin.analytics.index.trend_total_label"))
|
||||
expect(response.body).to include(">24<")
|
||||
expect(response.body).to include("\"pageviews\":5")
|
||||
expect(response.body).to include("\"pageviews\":12")
|
||||
expect(response.body).to include("\"pageviews\":19")
|
||||
end
|
||||
|
||||
|
||||
it "mostra la heatmap di una pagina con tab dispositivo" do
|
||||
get admin_analytics_page_path, params: { page_path: "/prezzi" }
|
||||
expect(response).to have_http_status(:ok)
|
||||
|
||||
Reference in New Issue
Block a user