PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
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.8, at assets/src/js/admin/list-students-enrolled.js

370 lines 8.7 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 ) {
244 return;
245 }
246 } else if ( this.isRequesting ) {
247 return;
248 }
249
250 const elForm = btn.closest( ListStudentsEnrolled.selectors.elForm );
251 const elLPTarget = this.elContainer.querySelector(
252 ListStudentsEnrolled.selectors.elLPTarget
253 );
254 if ( ! elLPTarget || ! elForm ) {
255 return;
256 }
257
258 const ajaxHandle = this.getAjaxHandle();
259 if ( ! ajaxHandle ) {
260 return;
261 }
262
263 this.setButtonLoadingState( btn, true );
264
265 const dataSend = ajaxHandle.getDataSetCurrent( elLPTarget );
266 dataSend.args = this.getFilterArgsFromForm(
267 elForm,
268 dataSend.args || {}
269 );
270 dataSend.args.paged = 1;
271 ajaxHandle.setDataSetCurrent( elLPTarget, dataSend );
272
273 this.reloadContent( elLPTarget, dataSend, btn );
274 }
275
276 /**
277 * Clear all filters and reload default data.
278 * @param args
279 */
280 clearFilters( args ) {
281 const { e } = args;
282 if ( e ) {
283 e.preventDefault();
284 }
285 const btn = args?.target?.closest(
286 ListStudentsEnrolled.selectors.elBtnClear
287 );
288 if ( btn ) {
289 if (
290 this.isRequesting ||
291 btn.classList.contains( 'loading' )
292 ) {
293 return;
294 }
295 } else if ( this.isRequesting ) {
296 return;
297 }
298
299 const elForm = btn.closest( ListStudentsEnrolled.selectors.elForm );
300 const elLPTarget = this.elContainer.querySelector(
301 ListStudentsEnrolled.selectors.elLPTarget
302 );
303 if ( ! elLPTarget || ! elForm ) {
304 return;
305 }
306
307 const ajaxHandle = this.getAjaxHandle();
308 if ( ! ajaxHandle ) {
309 return;
310 }
311
312 this.setButtonLoadingState( btn, true );
313
314 elForm.reset();
315 this.syncCourseIdFromName( elForm );
316
317 const dataSend = ajaxHandle.getDataSetCurrent( elLPTarget );
318 dataSend.args = lpUtils.mergeDataWithDatForm(
319 elForm,
320 dataSend.args || {}
321 );
322 dataSend.args.paged = 1;
323 ajaxHandle.setDataSetCurrent( elLPTarget, dataSend );
324
325 this.reloadContent( elLPTarget, dataSend, btn );
326 }
327
328 /**
329 * Shared reload helper: loading indicator + AJAX fetch.
330 * @param elLPTarget
331 * @param dataSend
332 * @param btn
333 */
334 reloadContent( elLPTarget, dataSend, btn = null ) {
335 const ajaxHandle = this.getAjaxHandle();
336 if ( ! ajaxHandle ) {
337 this.isRequesting = false;
338 this.setButtonLoadingState( btn, false );
339 return;
340 }
341
342 this.isRequesting = true;
343 ajaxHandle.showHideLoading( elLPTarget, 1 );
344
345 const callBack = {
346 success: ( response ) => {
347 const { status, data } = response;
348 if ( 'success' === status ) {
349 elLPTarget.innerHTML = data.content;
350 }
351 },
352 error: ( error ) => console.error( error ),
353 completed: () => {
354 this.isRequesting = false;
355 ajaxHandle.showHideLoading( elLPTarget, 0 );
356 this.setButtonLoadingState( btn, false );
357 },
358 };
359
360 ajaxHandle.fetchAJAX( dataSend, callBack );
361 }
362 }
363
364 // Auto-initialize when DOM is available (for standalone page load).
365 const listStudentsEnrolled = new ListStudentsEnrolled();
366
367 lpUtils.lpOnElementReady( ListStudentsEnrolled.selectors.elContainer, () => {
368 listStudentsEnrolled.init();
369 } );
370