PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.9
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.9
4.4.9 4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 All 140 releases
← All changes | assets/src/js/frontend/course-builder/builder-dashboard.js +180 -180 4.3.8 → 4.4.9 View file →
@@ -1,180 +1,180 @@
1 -/**
2 - * Dashboard charts and interactions for Course Builder.
3 - *
4 - * @since 4.3.0
5 - * @version 1.0.0
6 - */
7 -
8 -import Chart from 'chart.js/auto';
9 -
10 -export class BuilderDashboard {
11 - constructor() {
12 - this.charts = {};
13 - this.init();
14 - }
15 -
16 - init() {
17 - const dataEl = document.getElementById( 'lp-cb-dashboard-chart-data' );
18 - if ( ! dataEl ) {
19 - return;
20 - }
21 -
22 - try {
23 - this.chartData = JSON.parse( dataEl.textContent );
24 - } catch ( e ) {
25 - console.warn( 'Dashboard: Failed to parse chart data', e );
26 - return;
27 - }
28 -
29 - this.initSalesChart();
30 - this.initStudentsChart();
31 - this.bindFilterEvents();
32 - }
33 -
34 - createGradient( ctx, color ) {
35 - const gradient = ctx.createLinearGradient( 0, 0, 0, ctx.canvas.height );
36 - gradient.addColorStop( 0, color + '40' );
37 - gradient.addColorStop( 1, color + '05' );
38 - return gradient;
39 - }
40 -
41 - getChartConfig( labels, data, color, prefix = '', isInteger = false ) {
42 - return {
43 - type: 'line',
44 - data: {
45 - labels,
46 - datasets: [ {
47 - data,
48 - borderColor: color,
49 - borderWidth: 2.5,
50 - backgroundColor: ( context ) => {
51 - const { ctx } = context.chart;
52 - return this.createGradient( ctx, color );
53 - },
54 - fill: true,
55 - tension: 0.4,
56 - pointBackgroundColor: color,
57 - pointBorderColor: '#fff',
58 - pointBorderWidth: 2,
59 - pointRadius: 0,
60 - pointHoverRadius: 6,
61 - pointHoverBorderWidth: 2,
62 - } ],
63 - },
64 - options: {
65 - responsive: true,
66 - maintainAspectRatio: false,
67 - plugins: {
68 - legend: { display: false },
69 - tooltip: {
70 - backgroundColor: '#1e1e1e',
71 - titleColor: '#fff',
72 - bodyColor: '#fff',
73 - borderColor: 'rgba(255,255,255,0.1)',
74 - borderWidth: 1,
75 - cornerRadius: 8,
76 - padding: 12,
77 - displayColors: false,
78 - callbacks: {
79 - label: ( context ) => {
80 - const val = context.parsed.y || 0;
81 - return prefix + val.toLocaleString();
82 - },
83 - },
84 - },
85 - },
86 - scales: {
87 - x: {
88 - grid: { display: false },
89 - ticks: {
90 - color: '#9ca3af',
91 - font: { size: 11 },
92 - maxRotation: 0,
93 - },
94 - border: { display: false },
95 - },
96 - y: {
97 - grid: {
98 - color: 'rgba(0,0,0,0.04)',
99 - drawBorder: false,
100 - },
101 - ticks: {
102 - stepSize: isInteger ? 1 : undefined,
103 - color: '#9ca3af',
104 - font: { size: 11 },
105 - callback: ( value ) => prefix + value.toLocaleString(),
106 - },
107 - border: { display: false },
108 - beginAtZero: true,
109 - },
110 - },
111 - interaction: {
112 - intersect: false,
113 - mode: 'index',
114 - },
115 - },
116 - };
117 - }
118 -
119 - initSalesChart() {
120 - const canvas = document.getElementById( 'lp-cb-chart-sales' );
121 - if ( ! canvas ) {
122 - return;
123 - }
124 -
125 - const { labels = [], data = [] } = this.chartData.sales || {};
126 - const config = this.getChartConfig( labels, data, '#10b981', '$' );
127 - this.charts.sales = new Chart( canvas, config );
128 - }
129 -
130 - initStudentsChart() {
131 - const canvas = document.getElementById( 'lp-cb-chart-students' );
132 - if ( ! canvas ) {
133 - return;
134 - }
135 -
136 - const { labels = [], data = [] } = this.chartData.students || {};
137 - const config = this.getChartConfig( labels, data, '#f59e0b', '', true );
138 - this.charts.students = new Chart( canvas, config );
139 - }
140 -
141 - bindFilterEvents() {
142 - const filters = document.querySelectorAll( '.chart-card__filter' );
143 - filters.forEach( ( select ) => {
144 - select.addEventListener( 'change', ( e ) => {
145 - const chartType = e.target.dataset.chart;
146 - const period = e.target.value;
147 - this.fetchChartData( chartType, period );
148 - } );
149 - } );
150 - }
151 -
152 - async fetchChartData( chartType, period ) {
153 - const chart = this.charts[ chartType ];
154 - if ( ! chart ) {
155 - return;
156 - }
157 -
158 - const formData = new FormData();
159 - formData.append( 'action', 'lp_cb_dashboard_chart_data' );
160 - formData.append( 'chart_type', chartType );
161 - formData.append( 'period', period );
162 - formData.append( 'nonce', this.chartData.nonce );
163 -
164 - try {
165 - const response = await fetch( this.chartData.ajaxUrl, {
166 - method: 'POST',
167 - body: formData,
168 - } );
169 -
170 - const result = await response.json();
171 - if ( result.success && result.data ) {
172 - chart.data.labels = result.data.labels || [];
173 - chart.data.datasets[ 0 ].data = result.data.data || [];
174 - chart.update( 'none' );
175 - }
176 - } catch ( e ) {
177 - console.warn( 'Dashboard: Failed to fetch chart data', e );
178 - }
179 - }
180 -}
1 +/**
2 + * Dashboard charts and interactions for Course Builder.
3 + *
4 + * @since 4.3.0
5 + * @version 1.0.0
6 + */
7 +
8 +import Chart from 'chart.js/auto';
9 +
10 +export class BuilderDashboard {
11 + constructor() {
12 + this.charts = {};
13 + this.init();
14 + }
15 +
16 + init() {
17 + const dataEl = document.getElementById( 'lp-cb-dashboard-chart-data' );
18 + if ( ! dataEl ) {
19 + return;
20 + }
21 +
22 + try {
23 + this.chartData = JSON.parse( dataEl.textContent );
24 + } catch ( e ) {
25 + console.warn( 'Dashboard: Failed to parse chart data', e );
26 + return;
27 + }
28 +
29 + this.initSalesChart();
30 + this.initStudentsChart();
31 + this.bindFilterEvents();
32 + }
33 +
34 + createGradient( ctx, color ) {
35 + const gradient = ctx.createLinearGradient( 0, 0, 0, ctx.canvas.height );
36 + gradient.addColorStop( 0, color + '40' );
37 + gradient.addColorStop( 1, color + '05' );
38 + return gradient;
39 + }
40 +
41 + getChartConfig( labels, data, color, prefix = '', isInteger = false ) {
42 + return {
43 + type: 'line',
44 + data: {
45 + labels,
46 + datasets: [ {
47 + data,
48 + borderColor: color,
49 + borderWidth: 2.5,
50 + backgroundColor: ( context ) => {
51 + const { ctx } = context.chart;
52 + return this.createGradient( ctx, color );
53 + },
54 + fill: true,
55 + tension: 0.4,
56 + pointBackgroundColor: color,
57 + pointBorderColor: '#fff',
58 + pointBorderWidth: 2,
59 + pointRadius: 0,
60 + pointHoverRadius: 6,
61 + pointHoverBorderWidth: 2,
62 + } ],
63 + },
64 + options: {
65 + responsive: true,
66 + maintainAspectRatio: false,
67 + plugins: {
68 + legend: { display: false },
69 + tooltip: {
70 + backgroundColor: '#1e1e1e',
71 + titleColor: '#fff',
72 + bodyColor: '#fff',
73 + borderColor: 'rgba(255,255,255,0.1)',
74 + borderWidth: 1,
75 + cornerRadius: 8,
76 + padding: 12,
77 + displayColors: false,
78 + callbacks: {
79 + label: ( context ) => {
80 + const val = context.parsed.y || 0;
81 + return prefix + val.toLocaleString();
82 + },
83 + },
84 + },
85 + },
86 + scales: {
87 + x: {
88 + grid: { display: false },
89 + ticks: {
90 + color: '#9ca3af',
91 + font: { size: 11 },
92 + maxRotation: 0,
93 + },
94 + border: { display: false },
95 + },
96 + y: {
97 + grid: {
98 + color: 'rgba(0,0,0,0.04)',
99 + drawBorder: false,
100 + },
101 + ticks: {
102 + stepSize: isInteger ? 1 : undefined,
103 + color: '#9ca3af',
104 + font: { size: 11 },
105 + callback: ( value ) => prefix + value.toLocaleString(),
106 + },
107 + border: { display: false },
108 + beginAtZero: true,
109 + },
110 + },
111 + interaction: {
112 + intersect: false,
113 + mode: 'index',
114 + },
115 + },
116 + };
117 + }
118 +
119 + initSalesChart() {
120 + const canvas = document.getElementById( 'lp-cb-chart-sales' );
121 + if ( ! canvas ) {
122 + return;
123 + }
124 +
125 + const { labels = [], data = [] } = this.chartData.sales || {};
126 + const config = this.getChartConfig( labels, data, '#10b981', '$' );
127 + this.charts.sales = new Chart( canvas, config );
128 + }
129 +
130 + initStudentsChart() {
131 + const canvas = document.getElementById( 'lp-cb-chart-students' );
132 + if ( ! canvas ) {
133 + return;
134 + }
135 +
136 + const { labels = [], data = [] } = this.chartData.students || {};
137 + const config = this.getChartConfig( labels, data, '#f59e0b', '', true );
138 + this.charts.students = new Chart( canvas, config );
139 + }
140 +
141 + bindFilterEvents() {
142 + const filters = document.querySelectorAll( '.chart-card__filter' );
143 + filters.forEach( ( select ) => {
144 + select.addEventListener( 'change', ( e ) => {
145 + const chartType = e.target.dataset.chart;
146 + const period = e.target.value;
147 + this.fetchChartData( chartType, period );
148 + } );
149 + } );
150 + }
151 +
152 + async fetchChartData( chartType, period ) {
153 + const chart = this.charts[ chartType ];
154 + if ( ! chart ) {
155 + return;
156 + }
157 +
158 + const formData = new FormData();
159 + formData.append( 'action', 'lp_cb_dashboard_chart_data' );
160 + formData.append( 'chart_type', chartType );
161 + formData.append( 'period', period );
162 + formData.append( 'nonce', this.chartData.nonce );
163 +
164 + try {
165 + const response = await fetch( this.chartData.ajaxUrl, {
166 + method: 'POST',
167 + body: formData,
168 + } );
169 +
170 + const result = await response.json();
171 + if ( result.success && result.data ) {
172 + chart.data.labels = result.data.labels || [];
173 + chart.data.datasets[ 0 ].data = result.data.data || [];
174 + chart.update( 'none' );
175 + }
176 + } catch ( e ) {
177 + console.warn( 'Dashboard: Failed to fetch chart data', e );
178 + }
179 + }
180 +}