PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.10
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.10
4.4.10 4.4.9.1 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 All 142 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.10, at assets/src/js/admin/list-students-enrolled.js

359 lines 8.5 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 }
17
18 static selectors = {
19 elContainer: '.lp-enrolled-students',
20 elLayout: '.lp-students-enrolled-layout',
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 callBack: this.searchStudents.bind( this ),
67 },
68 {
69 selector: ListStudentsEnrolled.selectors.elBtnClear,
70 callBack: this.clearFilters.bind( this ),
71 },
72 ] );
73
74 // Search on Enter key.
75 lpUtils.eventHandlers( 'keydown', [
76 {
77 selector: ListStudentsEnrolled.selectors.elSearchInput,
78 callBack: this.triggerBtnSearch.bind( this ),
79 checkIsEventEnter: true,
80 },
81 {
82 selector: ListStudentsEnrolled.selectors.elCourseNameInput,
83 callBack: this.triggerBtnSearch.bind( this ),
84 checkIsEventEnter: true,
85 },
86 {
87 selector: ListStudentsEnrolled.selectors.elStartDateInput,
88 callBack: this.triggerBtnSearch.bind( this ),
89 checkIsEventEnter: true,
90 },
91 {
92 selector: ListStudentsEnrolled.selectors.elEndDateInput,
93 callBack: this.triggerBtnSearch.bind( this ),
94 checkIsEventEnter: true,
95 },
96 ] );
97
98 lpUtils.eventHandlers( 'change', [
99 {
100 selector: ListStudentsEnrolled.selectors.elStartDateInput,
101 callBack: this.checkDatesRange.bind( this ),
102 },
103 {
104 selector: ListStudentsEnrolled.selectors.elEndDateInput,
105 callBack: this.checkDatesRange.bind( this ),
106 },
107 ] );
108 }
109
110 // Click button search.
111 triggerBtnSearch() {
112 const buttonSearch = this.elContainer.querySelector(
113 ListStudentsEnrolled.selectors.elBtnSearch
114 );
115 if ( buttonSearch ) {
116 buttonSearch.click();
117 }
118 }
119
120 // Ensure start date is not after end date and vice versa. If invalid, adjust the other date to match.
121 checkDatesRange( args ) {
122 const { e } = args;
123 const elInput = e?.target;
124 if ( ! elInput ) {
125 return;
126 }
127
128 const elForm = elInput.closest( ListStudentsEnrolled.selectors.elForm );
129 if ( ! elForm ) {
130 return;
131 }
132
133 const startDateInput = elForm.querySelector(
134 ListStudentsEnrolled.selectors.elStartDateInput
135 );
136 const endDateInput = elForm.querySelector(
137 ListStudentsEnrolled.selectors.elEndDateInput
138 );
139
140 if ( elInput === startDateInput ) {
141 if ( startDateInput.value ) {
142 endDateInput.min = startDateInput.value;
143 if (
144 endDateInput.value &&
145 endDateInput.value < startDateInput.value
146 ) {
147 endDateInput.value = startDateInput.value;
148 }
149 } else {
150 endDateInput.min = '';
151 }
152 } else if ( elInput === endDateInput ) {
153 if ( endDateInput.value ) {
154 startDateInput.max = endDateInput.value;
155 if (
156 startDateInput.value &&
157 startDateInput.value > endDateInput.value
158 ) {
159 startDateInput.value = endDateInput.value;
160 }
161 } else {
162 startDateInput.max = '';
163 }
164 }
165 }
166
167 setButtonLoadingState( btn, isLoading ) {
168 if ( ! btn ) {
169 return;
170 }
171
172 lpUtils.lpSetLoadingEl( btn, isLoading ? 1 : 0 );
173 //btn.disabled = !! isLoading;
174 }
175
176 getAjaxHandle() {
177 const ajaxHandle = window.lpAJAXG;
178 if (
179 ! ajaxHandle ||
180 typeof ajaxHandle.getDataSetCurrent !== 'function' ||
181 typeof ajaxHandle.setDataSetCurrent !== 'function' ||
182 typeof ajaxHandle.showHideLoading !== 'function' ||
183 typeof ajaxHandle.fetchAJAX !== 'function'
184 ) {
185 return null;
186 }
187
188 return ajaxHandle;
189 }
190
191 syncCourseIdFromName( elForm ) {
192 const courseIdInput = elForm?.querySelector(
193 ListStudentsEnrolled.selectors.elCourseIdInput
194 );
195 if ( ! courseIdInput ) {
196 return;
197 }
198
199 courseIdInput.value = '0';
200
201 const courseNameInput = elForm.querySelector(
202 ListStudentsEnrolled.selectors.elCourseNameInput
203 );
204 const datalist = elForm.querySelector(
205 ListStudentsEnrolled.selectors.elCourseList
206 );
207 const courseName = courseNameInput?.value.trim() || '';
208 if ( ! courseName || ! datalist ) {
209 return;
210 }
211
212 const selectedOption = Array.from( datalist.options || [] ).find(
213 ( option ) => option.value.trim() === courseName
214 );
215 if ( selectedOption ) {
216 courseIdInput.value = selectedOption.dataset.courseId || '0';
217 }
218 }
219
220 getFilterArgsFromForm( elForm, dataArgs = {} ) {
221 this.syncCourseIdFromName( elForm );
222 return lpUtils.mergeDataWithDatForm( elForm, dataArgs );
223 }
224
225 /**
226 * Search students: update args.search, re-fetch.
227 * @param args
228 */
229 searchStudents( args ) {
230 const { e } = args;
231 if ( e ) {
232 e.preventDefault();
233 }
234 const btn = args?.target?.closest(
235 ListStudentsEnrolled.selectors.elBtnSearch
236 );
237
238 if ( ! btn ) {
239 return;
240 }
241
242 const elForm = btn.closest( ListStudentsEnrolled.selectors.elForm );
243 const elLayout = elForm.closest(
244 ListStudentsEnrolled.selectors.elLayout
245 );
246 const elLPTarget = elLayout.querySelector(
247 ListStudentsEnrolled.selectors.elLPTarget
248 );
249 if ( ! elLPTarget || ! elForm ) {
250 return;
251 }
252
253 const ajaxHandle = this.getAjaxHandle();
254 if ( ! ajaxHandle ) {
255 return;
256 }
257
258 this.setButtonLoadingState( btn, true );
259
260 const dataSend = ajaxHandle.getDataSetCurrent( elLPTarget );
261 dataSend.args = this.getFilterArgsFromForm(
262 elForm,
263 dataSend.args || {}
264 );
265 dataSend.args.paged = 1;
266 ajaxHandle.setDataSetCurrent( elLPTarget, dataSend );
267
268 this.reloadContent( elLPTarget, dataSend, btn );
269 }
270
271 /**
272 * Clear all filters and reload default data.
273 * @param args
274 */
275 clearFilters( args ) {
276 const { e } = args;
277 if ( e ) {
278 e.preventDefault();
279 }
280 const btn = args?.target?.closest(
281 ListStudentsEnrolled.selectors.elBtnClear
282 );
283
284 if ( ! btn ) {
285 return;
286 }
287
288 const elForm = btn.closest( ListStudentsEnrolled.selectors.elForm );
289 const elLayout = elForm.closest(
290 ListStudentsEnrolled.selectors.elLayout
291 );
292 const elLPTarget = elLayout.querySelector(
293 ListStudentsEnrolled.selectors.elLPTarget
294 );
295 if ( ! elLPTarget || ! elForm ) {
296 return;
297 }
298
299 const ajaxHandle = this.getAjaxHandle();
300 if ( ! ajaxHandle ) {
301 return;
302 }
303
304 this.setButtonLoadingState( btn, true );
305
306 elForm.reset();
307 this.syncCourseIdFromName( elForm );
308
309 const dataSend = ajaxHandle.getDataSetCurrent( elLPTarget );
310 dataSend.args = lpUtils.mergeDataWithDatForm(
311 elForm,
312 dataSend.args || {}
313 );
314 dataSend.args.paged = 1;
315 ajaxHandle.setDataSetCurrent( elLPTarget, dataSend );
316
317 this.reloadContent( elLPTarget, dataSend, btn );
318 }
319
320 /**
321 * Shared reload helper: loading indicator + AJAX fetch.
322 * @param elLPTarget
323 * @param dataSend
324 * @param btn
325 */
326 reloadContent( elLPTarget, dataSend, btn = null ) {
327 const ajaxHandle = this.getAjaxHandle();
328 if ( ! ajaxHandle ) {
329 this.setButtonLoadingState( btn, false );
330 return;
331 }
332
333 ajaxHandle.showHideLoading( elLPTarget, 1 );
334
335 const callBack = {
336 success: ( response ) => {
337 const { status, data } = response;
338 if ( 'success' === status ) {
339 elLPTarget.innerHTML = data.content;
340 }
341 },
342 error: ( error ) => console.error( error ),
343 completed: () => {
344 ajaxHandle.showHideLoading( elLPTarget, 0 );
345 this.setButtonLoadingState( btn, false );
346 },
347 };
348
349 ajaxHandle.fetchAJAX( dataSend, callBack );
350 }
351 }
352
353 // Auto-initialize when DOM is available (for standalone page load).
354 const listStudentsEnrolled = new ListStudentsEnrolled();
355
356 lpUtils.lpOnElementReady( ListStudentsEnrolled.selectors.elContainer, () => {
357 listStudentsEnrolled.init();
358 } );
359