PluginProbe ʕ •ᴥ•ʔ
Presto Player / trunk
Presto Player vtrunk
4.3.1 4.3.0 4.2.4 4.2.3 4.2.2 4.2.0 4.2.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.12.0 1.13.0 1.14.0 1.14.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.13 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3-beta1 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.0-beta1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1.0 3.1.1 3.1.2 3.1.3 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4
presto-player / src / admin / dashboard / pages / Analytics.js
presto-player / src / admin / dashboard / pages Last commit date
learn 1 month ago settings 1 month ago Analytics.js 1 month ago AnalyticsDetail.js 1 month ago Dashboard.js 1 month ago Emails.js 1 month ago Learn.js 1 month ago MediaHub.js 3 weeks ago Onboarding.js 3 weeks ago Settings.js 1 month ago UserAnalyticsDetail.js 1 month ago
Analytics.js
169 lines
1 import React, { useEffect, useState } from "react";
2 const { __ } = wp.i18n;
3 import apiFetch from "@wordpress/api-fetch";
4 import { Container, Title, Alert } from "@bsf/force-ui";
5 import EngagementChart, { Chart } from "../components/EngagementChart";
6 import TopUsers from "../components/TopUsers";
7 import TopMedia from "../components/TopMedia";
8 import useEngagementChartData from "../hooks/useEngagementChartData";
9 import useTopPerforming from "../hooks/useTopPerforming";
10 import AnalyticsPageSkeleton from "../components/Skeletons/AnalyticsPageSkeleton";
11 import ProGateOverlay from "../components/ProGateOverlay";
12
13 const MEDIA_PER_PAGE = 5;
14 const USERS_PER_PAGE = 5;
15
16 const AnalyticsDisabledNotice = () => {
17 const dashboardUrl = window.prestoPlayer?.dashboardUrl || "";
18 const settingsHref = `${dashboardUrl}&tab=Settings&section=viewing-analytics`;
19 return (
20 <Alert
21 design="stack"
22 variant="warning"
23 title={__("Analytics collection is turned off", "presto-player")}
24 content={
25 <>
26 {__(
27 "New views and watch-time data won't be recorded until you enable analytics.",
28 "presto-player"
29 )}{" "}
30 <a
31 href={settingsHref}
32 className="text-brand-primary-600 hover:underline"
33 >
34 {__("Enable in Settings", "presto-player")}
35 </a>
36 </>
37 }
38 />
39 );
40 };
41
42 const AnalyticsContent = () => {
43 const chartContext = useEngagementChartData({});
44 const [analyticsDisabled, setAnalyticsDisabled] = useState(false);
45
46 useEffect(() => {
47 apiFetch({ path: "/wp/v2/settings" })
48 .then((settings) => {
49 if (settings?.presto_player_analytics?.enable === false) {
50 setAnalyticsDisabled(true);
51 }
52 })
53 .catch(() => {
54 // Non-fatal — fall through without the notice.
55 });
56 }, []);
57
58 // The chart shows last-30-days when no filter is set; mirror that here
59 // so the tables match what the chart is showing instead of drifting
60 // back to all-time on the unfiltered view.
61 const effectiveDates = chartContext.selectedDates?.from
62 ? chartContext.selectedDates
63 : chartContext.defaultDateRange;
64
65 const {
66 data: topData,
67 isLoading,
68 error: topPerformingError,
69 mediaPage,
70 setMediaPage,
71 mediaPagination,
72 usersPage,
73 setUsersPage,
74 usersPagination,
75 } = useTopPerforming({
76 mediaPerPage: MEDIA_PER_PAGE,
77 usersPerPage: USERS_PER_PAGE,
78 selectedDates: effectiveDates,
79 });
80
81 if (isLoading) {
82 return <AnalyticsPageSkeleton />;
83 }
84
85 return (
86 <Container className="p-8" gap="md" direction="column">
87 <Container className="w-full">
88 <Container.Item grow={1}>
89 <Title
90 description=""
91 icon={null}
92 iconPosition="right"
93 size="md"
94 tag="h3"
95 title={__("Analytics", "presto-player")}
96 />
97 </Container.Item>
98 </Container>
99
100 {analyticsDisabled && <AnalyticsDisabledNotice />}
101
102 {topPerformingError && (
103 <Alert
104 design="stack"
105 variant="error"
106 title={__(
107 "Couldn't load top media and viewers",
108 "presto-player"
109 )}
110 content={__(
111 "Try refreshing the page. If the problem persists, contact support.",
112 "presto-player"
113 )}
114 />
115 )}
116
117 {/* Analytics Overview Chart + Top Users side by side */}
118 <div className="flex flex-col md:flex-row gap-5 items-stretch">
119 <div className="flex-1 min-w-0 flex">
120 <EngagementChart contextValue={chartContext}>
121 <Chart>
122 <Container.Item className="flex items-center justify-between w-full p-1">
123 <Chart.Tabs />
124 <Chart.DateFilter />
125 </Container.Item>
126 <Chart.KPI />
127 <Chart.AreaChart />
128 </Chart>
129 </EngagementChart>
130 </div>
131 <div className="md:w-1/3 shrink-0 flex">
132 <TopUsers
133 users={topData?.topUsers || []}
134 currentPage={usersPage}
135 totalItems={usersPagination.totalItems}
136 totalPages={usersPagination.totalPages}
137 perPage={USERS_PER_PAGE}
138 onPageChange={setUsersPage}
139 />
140 </div>
141 </div>
142
143 {/* Top Media Table */}
144 <TopMedia
145 media={topData?.topMedia || []}
146 currentPage={mediaPage}
147 totalItems={mediaPagination.totalItems}
148 totalPages={mediaPagination.totalPages}
149 perPage={MEDIA_PER_PAGE}
150 onPageChange={setMediaPage}
151 />
152 </Container>
153 );
154 };
155
156 const Analytics = () => {
157 if (!window.prestoPlayer?.isPremium) {
158 return (
159 <ProGateOverlay>
160 <AnalyticsPageSkeleton />
161 </ProGateOverlay>
162 );
163 }
164
165 return <AnalyticsContent />;
166 };
167
168 export default Analytics;
169