PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.2
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.2
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 4.2.0 All 139 releases
learnpress / assets / src / js / admin / list-students-enrolled.js

list-students-enrolled.js in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.2, at assets/src/js/admin/list-students-enrolled.js

372 lines 8.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * List Students Enrolled Script
3 *
4 * Handles filter and search interactions for the enrolled students table.
5 * Pagination is handled by loadAJAX.js clickNumberPage (via .page-numbers class).
6 *
7 * @since 4.3.3
8 * @version 1.0.0
9 */
10 import * as lpUtils from 'lpAssetsJsPath/utils.js';
11
12 export class ListStudentsEnrolled {
13 constructor() {
14 this.instructorId = null;
15 this.elContainer = null;
16 this.isRequesting = false;
17 }
18
19 static selectors = {
20 elContainer: '#lp-enrolled-students',
21 elForm: '.lp-enrolled-students-form',
22 elLPTarget: '.lp-target',
23 elCourseNameInput: '.lp-enrolled-filter-course-name',
24 elCourseIdInput: '#lp-enrolled-filter-course-id',
25 elCourseList: '#lp-enrolled-course-list',
26 elSearchInput: '.lp-enrolled-search-input',
27 elStartDateInput: '.lp-enrolled-filter-start-date',
28 elEndDateInput: '.lp-enrolled-filter-end-date',
29 elBtnSearch: '.lp-enrolled-btn-search',
30 elBtnClear: '.lp-enrolled-btn-clear',
31 };
32
33 init() {
34 this.elContainer = document.querySelector(
35 ListStudentsEnrolled.selectors.elContainer
36 );
37 if ( ! this.elContainer ) {
38 return;
39 }
40
41 const elLPTarget = this.elContainer.querySelector(
42 ListStudentsEnrolled.selectors.elLPTarget
43 );
44 const ajaxHandle = this.getAjaxHandle();
45 if ( elLPTarget && ajaxHandle ) {
46 const dataSend = ajaxHandle.getDataSetCurrent( elLPTarget );
47 if ( dataSend && dataSend.args ) {
48 this.instructorId = dataSend.args.instructor_id;
49 }
50 }
51
52 this.events();
53 }
54
55 events() {
56 if ( ListStudentsEnrolled._loadedEvents ) {
57 return;
58 }
59
60 ListStudentsEnrolled._loadedEvents = this;
61
62 // Search/Clear button click.
63 lpUtils.eventHandlers( 'click', [
64 {
65 selector: ListStudentsEnrolled.selectors.elBtnSearch,
66 class: this,
67 callBack: this.searchStudents.name,
68 },
69 {
70 selector: ListStudentsEnrolled.selectors.elBtnClear,
71 class: this,
72 callBack: this.clearFilters.name,
73 },
74 ] );
75
76 // Search on Enter key.
77 lpUtils.eventHandlers( 'keydown', [
78 {
79 selector: ListStudentsEnrolled.selectors.elSearchInput,
80 class: this,
81 callBack: this.triggerBtnSearch.name,
82 checkIsEventEnter: true,
83 },
84 {
85 selector: ListStudentsEnrolled.selectors.elCourseNameInput,
86 class: this,
87 callBack: this.triggerBtnSearch.name,
88 checkIsEventEnter: true,
89 },
90 {
91 selector: ListStudentsEnrolled.selectors.elStartDateInput,
92 class: this,
93 callBack: this.triggerBtnSearch.name,
94 checkIsEventEnter: true,
95 },
96 {
97 selector: ListStudentsEnrolled.selectors.elEndDateInput,
98 class: this,
99 callBack: this.triggerBtnSearch.name,
100 checkIsEventEnter: true,
101 },
102 ] );
103
104 lpUtils.eventHandlers( 'change', [
105 {
106 selector: ListStudentsEnrolled.selectors.elStartDateInput,
107 class: this,
108 callBack: this.checkDatesRange.name,
109 },
110 {
111 selector: ListStudentsEnrolled.selectors.elEndDateInput,
112 class: this,
113 callBack: this.checkDatesRange.name,
114 },
115 ] );
116 }
117
118 // Click button search.
119 triggerBtnSearch() {
120 const buttonSearch = this.elContainer.querySelector(
121 ListStudentsEnrolled.selectors.elBtnSearch
122 );
123 if ( buttonSearch ) {
124 buttonSearch.click();
125 }
126 }
127
128 // Ensure start date is not after end date and vice versa. If invalid, adjust the other date to match.
129 checkDatesRange( args ) {
130 const { e } = args;
131 const elInput = e?.target;
132 if ( ! elInput ) {
133 return;
134 }
135
136 const elForm = elInput.closest( ListStudentsEnrolled.selectors.elForm );
137 if ( ! elForm ) {
138 return;
139 }
140
141 const startDateInput = elForm.querySelector(
142 ListStudentsEnrolled.selectors.elStartDateInput,
143 );
144 const endDateInput = elForm.querySelector(
145 ListStudentsEnrolled.selectors.elEndDateInput,
146 );
147
148 if ( elInput === startDateInput ) {
149 if ( startDateInput.value ) {
150 endDateInput.min = startDateInput.value;
151 if ( endDateInput.value && endDateInput.value < startDateInput.value ) {
152 endDateInput.value = startDateInput.value;
153 }
154 } else {
155 endDateInput.min = '';
156 }
157 } else if ( elInput === endDateInput ) {
158 if ( endDateInput.value ) {
159 startDateInput.max = endDateInput.value;
160 if ( startDateInput.value && startDateInput.value > endDateInput.value ) {
161 startDateInput.value = endDateInput.value;
162 }
163 } else {
164 startDateInput.max = '';
165 }
166 }
167 }
168
169 setButtonLoadingState( btn, isLoading ) {
170 if ( ! btn ) {
171 return;
172 }
173
174 lpUtils.lpSetLoadingEl( btn, isLoading ? 1 : 0 );
175 btn.disabled = !! isLoading;
176 }
177
178 getAjaxHandle() {
179 const ajaxHandle = window.lpAJAXG;
180 if (
181 ! ajaxHandle ||
182 typeof ajaxHandle.getDataSetCurrent !== 'function' ||
183 typeof ajaxHandle.setDataSetCurrent !== 'function' ||
184 typeof ajaxHandle.showHideLoading !== 'function' ||
185 typeof ajaxHandle.fetchAJAX !== 'function'
186 ) {
187 return null;
188 }
189
190 return ajaxHandle;
191 }
192
193 syncCourseIdFromName( elForm ) {
194 const courseIdInput = elForm?.querySelector(
195 ListStudentsEnrolled.selectors.elCourseIdInput
196 );
197 if ( ! courseIdInput ) {
198 return;
199 }
200
201 courseIdInput.value = '0';
202
203 const courseNameInput = elForm.querySelector(
204 ListStudentsEnrolled.selectors.elCourseNameInput
205 );
206 const datalist = elForm.querySelector(
207 ListStudentsEnrolled.selectors.elCourseList
208 );
209 const courseName = courseNameInput?.value.trim() || '';
210 if ( ! courseName || ! datalist ) {
211 return;
212 }
213
214 const selectedOption = Array.from( datalist.options || [] ).find(
215 ( option ) => option.value.trim() === courseName
216 );
217 if ( selectedOption ) {
218 courseIdInput.value = selectedOption.dataset.courseId || '0';
219 }
220 }
221
222 getFilterArgsFromForm( elForm, dataArgs = {} ) {
223 this.syncCourseIdFromName( elForm );
224 return lpUtils.mergeDataWithDatForm( elForm, dataArgs );
225 }
226
227 /**
228 * Search students: update args.search, re-fetch.
229 * @param args
230 */
231 searchStudents( args ) {
232 const { e } = args;
233 if ( e ) {
234 e.preventDefault();
235 }
236 const btn = args?.target?.closest(
237 ListStudentsEnrolled.selectors.elBtnSearch
238 );
239 if ( btn ) {
240 if (
241 this.isRequesting ||
242 btn.classList.contains( 'loading' ) ||
243 btn.disabled
244 ) {
245 return;
246 }
247 } else if ( this.isRequesting ) {
248 return;
249 }
250
251 const elForm = btn.closest( ListStudentsEnrolled.selectors.elForm );
252 const elLPTarget = this.elContainer.querySelector(
253 ListStudentsEnrolled.selectors.elLPTarget
254 );
255 if ( ! elLPTarget || ! elForm ) {
256 return;
257 }
258
259 const ajaxHandle = this.getAjaxHandle();
260 if ( ! ajaxHandle ) {
261 return;
262 }
263
264 this.setButtonLoadingState( btn, true );
265
266 const dataSend = ajaxHandle.getDataSetCurrent( elLPTarget );
267 dataSend.args = this.getFilterArgsFromForm(
268 elForm,
269 dataSend.args || {}
270 );
271 dataSend.args.paged = 1;
272 ajaxHandle.setDataSetCurrent( elLPTarget, dataSend );
273
274 this.reloadContent( elLPTarget, dataSend, btn );
275 }
276
277 /**
278 * Clear all filters and reload default data.
279 * @param args
280 */
281 clearFilters( args ) {
282 const { e } = args;
283 if ( e ) {
284 e.preventDefault();
285 }
286 const btn = args?.target?.closest(
287 ListStudentsEnrolled.selectors.elBtnClear
288 );
289 if ( btn ) {
290 if (
291 this.isRequesting ||
292 btn.classList.contains( 'loading' ) ||
293 btn.disabled
294 ) {
295 return;
296 }
297 } else if ( this.isRequesting ) {
298 return;
299 }
300
301 const elForm = btn.closest( ListStudentsEnrolled.selectors.elForm );
302 const elLPTarget = this.elContainer.querySelector(
303 ListStudentsEnrolled.selectors.elLPTarget
304 );
305 if ( ! elLPTarget || ! elForm ) {
306 return;
307 }
308
309 const ajaxHandle = this.getAjaxHandle();
310 if ( ! ajaxHandle ) {
311 return;
312 }
313
314 this.setButtonLoadingState( btn, true );
315
316 elForm.reset();
317 this.syncCourseIdFromName( elForm );
318
319 const dataSend = ajaxHandle.getDataSetCurrent( elLPTarget );
320 dataSend.args = lpUtils.mergeDataWithDatForm(
321 elForm,
322 dataSend.args || {}
323 );
324 dataSend.args.paged = 1;
325 ajaxHandle.setDataSetCurrent( elLPTarget, dataSend );
326
327 this.reloadContent( elLPTarget, dataSend, btn );
328 }
329
330 /**
331 * Shared reload helper: loading indicator + AJAX fetch.
332 * @param elLPTarget
333 * @param dataSend
334 * @param btn
335 */
336 reloadContent( elLPTarget, dataSend, btn = null ) {
337 const ajaxHandle = this.getAjaxHandle();
338 if ( ! ajaxHandle ) {
339 this.isRequesting = false;
340 this.setButtonLoadingState( btn, false );
341 return;
342 }
343
344 this.isRequesting = true;
345 ajaxHandle.showHideLoading( elLPTarget, 1 );
346
347 const callBack = {
348 success: ( response ) => {
349 const { status, data } = response;
350 if ( 'success' === status ) {
351 elLPTarget.innerHTML = data.content;
352 }
353 },
354 error: ( error ) => console.error( error ),
355 completed: () => {
356 this.isRequesting = false;
357 ajaxHandle.showHideLoading( elLPTarget, 0 );
358 this.setButtonLoadingState( btn, false );
359 },
360 };
361
362 ajaxHandle.fetchAJAX( dataSend, callBack );
363 }
364 }
365
366 // Auto-initialize when DOM is available (for standalone page load).
367 const listStudentsEnrolled = new ListStudentsEnrolled();
368
369 lpUtils.lpOnElementReady( ListStudentsEnrolled.selectors.elContainer, () => {
370 listStudentsEnrolled.init();
371 } );
372