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.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 4.1.7.3.1 All 141 releases
← All changes | assets/src/js/frontend/course-builder/builder-course/builder-tab-course.js +407 -407 4.3.8 → 4.4.9 View file →
@@ -1,407 +1,407 @@
1 -import * as lpUtils from 'lpAssetsJsPath/utils.js';
2 -import SweetAlert from 'sweetalert2';
3 -import * as lpToastify from 'lpAssetsJsPath/lpToastify.js';
4 -import { SWAL_ICON_DELETE, SWAL_ICON_DUPLICATE, SWAL_ICON_TRASH_DRAFT } from '../swal-icons.js';
5 -
6 -export class BuilderTabCourse {
7 - constructor() {
8 - this.init();
9 - }
10 -
11 - static selectors = {
12 - elBtnCreateCourse: 'a.cb-btn-add-new[href]',
13 - elCourseItem: '.course-item',
14 - elCourseExpandedItems: '.course-action-expanded__items',
15 - elCourseDuplicate: '.course-action-expanded__duplicate',
16 - elCourseTrash: '.course-action-expanded__trash',
17 - elCourseDraft: '.course-action-expanded__draft',
18 - elCourseDelete: '.course-action-expanded__delete',
19 - elCourseActionExpanded: '.course-action-expanded',
20 - elCourseStatus: '.course-status',
21 - };
22 -
23 - init() {
24 - this.events();
25 - }
26 -
27 - events() {
28 - if ( BuilderTabCourse._loadedEvents ) {
29 - return;
30 - }
31 - BuilderTabCourse._loadedEvents = true;
32 -
33 - lpUtils.eventHandlers( 'click', [
34 - {
35 - selector: BuilderTabCourse.selectors.elCourseDuplicate,
36 - class: this,
37 - callBack: this.duplicateCourse.name,
38 - },
39 - {
40 - selector: BuilderTabCourse.selectors.elCourseTrash,
41 - class: this,
42 - callBack: this.trashCourse.name,
43 - },
44 - {
45 - selector: BuilderTabCourse.selectors.elCourseDraft,
46 - class: this,
47 - callBack: this.draftCourse.name,
48 - },
49 - {
50 - selector: BuilderTabCourse.selectors.elCourseDelete,
51 - class: this,
52 - callBack: this.deleteCourse.name,
53 - },
54 - {
55 - selector: BuilderTabCourse.selectors.elCourseActionExpanded,
56 - class: this,
57 - callBack: this.toggleExpandedAction.name,
58 - },
59 - {
60 - selector: BuilderTabCourse.selectors.elBtnCreateCourse,
61 - callBack: ( args ) => {
62 - const { target } = args;
63 - const elBtnCreateCourse = target.closest(
64 - BuilderTabCourse.selectors.elBtnCreateCourse
65 - );
66 -
67 - if ( ! elBtnCreateCourse ) {
68 - return;
69 - }
70 -
71 - lpUtils.lpSetLoadingEl( elBtnCreateCourse, 1 );
72 - },
73 - },
74 - ] );
75 -
76 - document.addEventListener( 'click', ( e ) => {
77 - if ( ! e.target.closest( BuilderTabCourse.selectors.elCourseActionExpanded ) ) {
78 - this.closeAllExpanded();
79 - }
80 - } );
81 - }
82 -
83 - duplicateCourse( args ) {
84 - const { target } = args;
85 - const elCourseDuplicate = target.closest( BuilderTabCourse.selectors.elCourseDuplicate );
86 - const elCourseItem = elCourseDuplicate.closest( BuilderTabCourse.selectors.elCourseItem );
87 -
88 - if ( ! elCourseItem ) {
89 - return;
90 - }
91 -
92 - const courseId = elCourseItem.dataset.courseId || '';
93 -
94 - if ( ! courseId ) {
95 - return;
96 - }
97 -
98 - SweetAlert.fire( {
99 - title: elCourseDuplicate.dataset.title || 'Duplicate Course',
100 - text: elCourseDuplicate.dataset.content || 'Are you sure you want to duplicate this course?',
101 - iconHtml: SWAL_ICON_DUPLICATE,
102 - customClass: { icon: 'lp-cb-swal-icon-html' },
103 - showCloseButton: true,
104 - showCancelButton: true,
105 - cancelButtonText: lpData.i18n.cancel,
106 - confirmButtonText: lpData.i18n.yes,
107 - reverseButtons: true,
108 - } ).then( ( result ) => {
109 - if ( result.isConfirmed ) {
110 - lpUtils.lpSetLoadingEl( elCourseDuplicate, 1 );
111 -
112 - const dataSend = {
113 - action: 'duplicate_course',
114 - args: { id_url: 'duplicate-course' },
115 - course_id: courseId,
116 - };
117 -
118 - const callBack = {
119 - success: ( response ) => {
120 - const { status, message, data } = response;
121 - lpToastify.show( message || 'Duplicated successfully!', status );
122 -
123 - if ( data?.html ) {
124 - const elCourse = elCourseDuplicate.closest( '.course' );
125 - const elCourseList = elCourse.closest( '.courses-list' ) || elCourse.parentElement;
126 -
127 - if ( elCourseList ) {
128 - elCourseList.insertAdjacentHTML( 'afterbegin', data.html );
129 - const newCourse = elCourseList.firstElementChild;
130 -
131 - if ( newCourse ) {
132 - newCourse.scrollIntoView( { behavior: 'smooth', block: 'nearest' } );
133 - newCourse.classList.add( 'highlight-new-course' );
134 - setTimeout( () => {
135 - newCourse.classList.remove( 'highlight-new-course' );
136 - }, 1500 );
137 - }
138 - }
139 - }
140 - },
141 - error: ( error ) => {
142 - lpToastify.show( error.message || error, 'error' );
143 - },
144 - completed: () => {
145 - lpUtils.lpSetLoadingEl( elCourseDuplicate, 0 );
146 - },
147 - };
148 -
149 - window.lpAJAXG.fetchAJAX( dataSend, callBack );
150 - }
151 - } );
152 - }
153 -
154 - trashCourse( args ) {
155 - const { target } = args;
156 - const elCourseTrash = target.closest( BuilderTabCourse.selectors.elCourseTrash );
157 - const elCourseItem = elCourseTrash.closest( BuilderTabCourse.selectors.elCourseItem );
158 -
159 - if ( ! elCourseItem ) {
160 - return;
161 - }
162 -
163 - const courseId = elCourseItem.dataset.courseId || '';
164 -
165 - SweetAlert.fire( {
166 - title: elCourseTrash.dataset.title || 'Trash Course',
167 - text: elCourseTrash.dataset.content || 'Are you sure you want to move this course to trash?',
168 - iconHtml: SWAL_ICON_TRASH_DRAFT,
169 - customClass: { icon: 'lp-cb-swal-icon-html' },
170 - showCloseButton: true,
171 - showCancelButton: true,
172 - cancelButtonText: lpData.i18n.cancel,
173 - confirmButtonText: lpData.i18n.yes,
174 - reverseButtons: true,
175 - } ).then( ( result ) => {
176 - if ( result.isConfirmed ) {
177 - lpUtils.lpSetLoadingEl( elCourseTrash, 1 );
178 -
179 - const dataSend = {
180 - action: 'move_trash_course',
181 - args: { id_url: 'move-trash-course' },
182 - course_id: courseId,
183 - };
184 -
185 - const callBack = {
186 - success: ( response ) => {
187 - const { status, message, data } = response;
188 - lpToastify.show( message, status );
189 -
190 - if ( data?.status ) {
191 - const elCourse = elCourseTrash.closest( '.course' );
192 - this.updateStatusUI( elCourse, data.status );
193 - }
194 - },
195 - error: ( error ) => {
196 - lpToastify.show( error.message || error, 'error' );
197 - },
198 - completed: () => {
199 - lpUtils.lpSetLoadingEl( elCourseTrash, 0 );
200 - },
201 - };
202 -
203 - window.lpAJAXG.fetchAJAX( dataSend, callBack );
204 - }
205 - } );
206 - }
207 -
208 - draftCourse( args ) {
209 - const { target } = args;
210 - const elCourseDraft = target.closest( BuilderTabCourse.selectors.elCourseDraft );
211 - const elCourseItem = elCourseDraft.closest( BuilderTabCourse.selectors.elCourseItem );
212 -
213 - if ( ! elCourseItem ) {
214 - return;
215 - }
216 -
217 - // Check if published to show confirm unpublish modal
218 - const statusEl = elCourseItem.querySelector( BuilderTabCourse.selectors.elCourseStatus );
219 - const isPublished = statusEl && statusEl.classList.contains( 'publish' );
220 - if ( isPublished ) {
221 - const confirmMsg =
222 - elCourseDraft.dataset.confirmUnpublish ||
223 - 'Saving as draft will unpublish this item. Are you sure?';
224 -
225 - SweetAlert.fire( {
226 - title: 'Draft Course',
227 - text: confirmMsg,
228 - iconHtml: SWAL_ICON_TRASH_DRAFT,
229 - customClass: { icon: 'lp-cb-swal-icon-html' },
230 - showCloseButton: true,
231 - showCancelButton: true,
232 - cancelButtonText: lpData.i18n.cancel,
233 - confirmButtonText: lpData.i18n.yes,
234 - reverseButtons: true,
235 - } ).then( ( result ) => {
236 - if ( result.isConfirmed ) {
237 - this.draftCourseExecute( elCourseDraft, elCourseItem );
238 - }
239 - } );
240 - return;
241 - }
242 -
243 - this.draftCourseExecute( elCourseDraft, elCourseItem );
244 - }
245 -
246 - draftCourseExecute( elCourseDraft, elCourseItem ) {
247 - lpUtils.lpSetLoadingEl( elCourseDraft, 1 );
248 -
249 - const courseId = elCourseItem.dataset.courseId || '';
250 -
251 - const dataSend = {
252 - action: 'move_trash_course',
253 - args: { id_url: 'move-trash-course' },
254 - course_id: courseId || 0,
255 - status: 'draft',
256 - };
257 -
258 - const callBack = {
259 - success: ( response ) => {
260 - const { status, message, data } = response;
261 - lpToastify.show( message, status );
262 -
263 - if ( data?.status ) {
264 - const elCourse = elCourseDraft.closest( '.course' );
265 - this.updateStatusUI( elCourse, data.status );
266 - }
267 - },
268 - error: ( error ) => {
269 - lpToastify.show( error.message || error, 'error' );
270 - },
271 - completed: () => {
272 - lpUtils.lpSetLoadingEl( elCourseDraft, 0 );
273 - },
274 - };
275 -
276 - window.lpAJAXG.fetchAJAX( dataSend, callBack );
277 - }
278 -
279 - deleteCourse( args ) {
280 - const { target } = args;
281 - const elCourseDelete = target.closest( BuilderTabCourse.selectors.elCourseDelete );
282 - const elCourseItem = elCourseDelete.closest( BuilderTabCourse.selectors.elCourseItem );
283 -
284 - if ( ! elCourseItem ) {
285 - return;
286 - }
287 -
288 - const courseId = elCourseItem.dataset.courseId || '';
289 -
290 - if ( ! courseId ) {
291 - return;
292 - }
293 -
294 - SweetAlert.fire( {
295 - title: elCourseDelete.dataset.title || 'Delete Course',
296 - text:
297 - elCourseDelete.dataset.content ||
298 - 'Are you sure you want to permanently delete this course?',
299 - iconHtml: SWAL_ICON_DELETE,
300 - customClass: { icon: 'lp-cb-swal-icon-html' },
301 - showCloseButton: true,
302 - showCancelButton: true,
303 - cancelButtonText: lpData.i18n.cancel,
304 - confirmButtonText: lpData.i18n.yes,
305 - reverseButtons: true,
306 - } ).then( ( result ) => {
307 - if ( result.isConfirmed ) {
308 - const dataSend = {
309 - action: 'move_trash_course',
310 - args: { id_url: 'move-trash-course' },
311 - course_id: courseId,
312 - status: 'delete',
313 - };
314 -
315 - const callBack = {
316 - success: ( response ) => {
317 - const { status, message } = response;
318 - lpToastify.show( message, status );
319 - const elCourse = elCourseDelete.closest( '.course' );
320 -
321 - elCourse.style.transition = 'opacity 0.4s ease-out, transform 0.4s ease-out';
322 - elCourse.style.opacity = '0';
323 - elCourse.style.transform = 'translateX(160px)';
324 -
325 - setTimeout( () => {
326 - elCourse.remove();
327 - }, 400 );
328 - },
329 - error: ( error ) => {
330 - lpToastify.show( error.message || error, 'error' );
331 - },
332 - };
333 -
334 - window.lpAJAXG.fetchAJAX( dataSend, callBack );
335 - }
336 - } );
337 - }
338 -
339 - toggleExpandedAction( args ) {
340 - const { target } = args;
341 - const elCourseActionExpanded = target.closest(
342 - BuilderTabCourse.selectors.elCourseActionExpanded
343 - );
344 -
345 - if ( ! elCourseActionExpanded ) {
346 - return;
347 - }
348 -
349 - const elCourseItem = elCourseActionExpanded.closest( BuilderTabCourse.selectors.elCourseItem );
350 -
351 - if ( ! elCourseItem ) {
352 - return;
353 - }
354 -
355 - const elExpandedItems = elCourseItem.querySelector(
356 - BuilderTabCourse.selectors.elCourseExpandedItems
357 - );
358 -
359 - if ( ! elExpandedItems ) {
360 - return;
361 - }
362 -
363 - // Close others
364 - this.closeAllExpanded( elExpandedItems );
365 -
366 - elExpandedItems.classList.toggle( 'active' );
367 - elCourseActionExpanded.classList.toggle( 'active' );
368 - }
369 -
370 - closeAllExpanded( excludeElement = null ) {
371 - const allExpandedItems = document.querySelectorAll(
372 - `${ BuilderTabCourse.selectors.elCourseExpandedItems }.active`
373 - );
374 -
375 - allExpandedItems.forEach( ( item ) => {
376 - if ( item === excludeElement ) {
377 - return;
378 - }
379 -
380 - item.classList.remove( 'active' );
381 -
382 - const courseItem = item.closest( BuilderTabCourse.selectors.elCourseItem );
383 -
384 - if ( ! courseItem ) {
385 - return;
386 - }
387 -
388 - const expandedBtn = courseItem.querySelector(
389 - BuilderTabCourse.selectors.elCourseActionExpanded
390 - );
391 - if ( expandedBtn ) {
392 - expandedBtn.classList.remove( 'active' );
393 - }
394 - } );
395 - }
396 -
397 - updateStatusUI( elCourse, status ) {
398 - const elStatus = elCourse.querySelector( BuilderTabCourse.selectors.elCourseStatus );
399 - const elSpanStatus = elCourse.querySelector(
400 - `${ BuilderTabCourse.selectors.elCourseStatus } span`
401 - );
402 - if ( elSpanStatus && elStatus ) {
403 - elStatus.className = 'course-status ' + status;
404 - elSpanStatus.textContent = status;
405 - }
406 - }
407 -}
1 +import * as lpUtils from 'lpAssetsJsPath/utils.js';
2 +import SweetAlert from 'sweetalert2';
3 +import * as lpToastify from 'lpAssetsJsPath/lpToastify.js';
4 +import { SWAL_ICON_DELETE, SWAL_ICON_DUPLICATE, SWAL_ICON_TRASH_DRAFT } from '../swal-icons.js';
5 +
6 +export class BuilderTabCourse {
7 + constructor() {
8 + this.init();
9 + }
10 +
11 + static selectors = {
12 + elBtnCreateCourse: 'a.cb-btn-add-new[href]',
13 + elCourseItem: '.course-item',
14 + elCourseExpandedItems: '.course-action-expanded__items',
15 + elCourseDuplicate: '.course-action-expanded__duplicate',
16 + elCourseTrash: '.course-action-expanded__trash',
17 + elCourseDraft: '.course-action-expanded__draft',
18 + elCourseDelete: '.course-action-expanded__delete',
19 + elCourseActionExpanded: '.course-action-expanded',
20 + elCourseStatus: '.course-status',
21 + };
22 +
23 + init() {
24 + this.events();
25 + }
26 +
27 + events() {
28 + if ( BuilderTabCourse._loadedEvents ) {
29 + return;
30 + }
31 + BuilderTabCourse._loadedEvents = true;
32 +
33 + lpUtils.eventHandlers( 'click', [
34 + {
35 + selector: BuilderTabCourse.selectors.elCourseDuplicate,
36 + class: this,
37 + callBack: this.duplicateCourse.name,
38 + },
39 + {
40 + selector: BuilderTabCourse.selectors.elCourseTrash,
41 + class: this,
42 + callBack: this.trashCourse.name,
43 + },
44 + {
45 + selector: BuilderTabCourse.selectors.elCourseDraft,
46 + class: this,
47 + callBack: this.draftCourse.name,
48 + },
49 + {
50 + selector: BuilderTabCourse.selectors.elCourseDelete,
51 + class: this,
52 + callBack: this.deleteCourse.name,
53 + },
54 + {
55 + selector: BuilderTabCourse.selectors.elCourseActionExpanded,
56 + class: this,
57 + callBack: this.toggleExpandedAction.name,
58 + },
59 + {
60 + selector: BuilderTabCourse.selectors.elBtnCreateCourse,
61 + callBack: ( args ) => {
62 + const { target } = args;
63 + const elBtnCreateCourse = target.closest(
64 + BuilderTabCourse.selectors.elBtnCreateCourse
65 + );
66 +
67 + if ( ! elBtnCreateCourse ) {
68 + return;
69 + }
70 +
71 + lpUtils.lpSetLoadingEl( elBtnCreateCourse, 1 );
72 + },
73 + },
74 + ] );
75 +
76 + document.addEventListener( 'click', ( e ) => {
77 + if ( ! e.target.closest( BuilderTabCourse.selectors.elCourseActionExpanded ) ) {
78 + this.closeAllExpanded();
79 + }
80 + } );
81 + }
82 +
83 + duplicateCourse( args ) {
84 + const { target } = args;
85 + const elCourseDuplicate = target.closest( BuilderTabCourse.selectors.elCourseDuplicate );
86 + const elCourseItem = elCourseDuplicate.closest( BuilderTabCourse.selectors.elCourseItem );
87 +
88 + if ( ! elCourseItem ) {
89 + return;
90 + }
91 +
92 + const courseId = elCourseItem.dataset.courseId || '';
93 +
94 + if ( ! courseId ) {
95 + return;
96 + }
97 +
98 + SweetAlert.fire( {
99 + title: elCourseDuplicate.dataset.title || 'Duplicate Course',
100 + text: elCourseDuplicate.dataset.content || 'Are you sure you want to duplicate this course?',
101 + iconHtml: SWAL_ICON_DUPLICATE,
102 + customClass: { icon: 'lp-cb-swal-icon-html' },
103 + showCloseButton: true,
104 + showCancelButton: true,
105 + cancelButtonText: lpData.i18n.cancel,
106 + confirmButtonText: lpData.i18n.yes,
107 + reverseButtons: true,
108 + } ).then( ( result ) => {
109 + if ( result.isConfirmed ) {
110 + lpUtils.lpSetLoadingEl( elCourseDuplicate, 1 );
111 +
112 + const dataSend = {
113 + action: 'duplicate_course',
114 + args: { id_url: 'duplicate-course' },
115 + course_id: courseId,
116 + };
117 +
118 + const callBack = {
119 + success: ( response ) => {
120 + const { status, message, data } = response;
121 + lpToastify.show( message || 'Duplicated successfully!', status );
122 +
123 + if ( data?.html ) {
124 + const elCourse = elCourseDuplicate.closest( '.course' );
125 + const elCourseList = elCourse.closest( '.courses-list' ) || elCourse.parentElement;
126 +
127 + if ( elCourseList ) {
128 + elCourseList.insertAdjacentHTML( 'afterbegin', data.html );
129 + const newCourse = elCourseList.firstElementChild;
130 +
131 + if ( newCourse ) {
132 + newCourse.scrollIntoView( { behavior: 'smooth', block: 'nearest' } );
133 + newCourse.classList.add( 'highlight-new-course' );
134 + setTimeout( () => {
135 + newCourse.classList.remove( 'highlight-new-course' );
136 + }, 1500 );
137 + }
138 + }
139 + }
140 + },
141 + error: ( error ) => {
142 + lpToastify.show( error.message || error, 'error' );
143 + },
144 + completed: () => {
145 + lpUtils.lpSetLoadingEl( elCourseDuplicate, 0 );
146 + },
147 + };
148 +
149 + window.lpAJAXG.fetchAJAX( dataSend, callBack );
150 + }
151 + } );
152 + }
153 +
154 + trashCourse( args ) {
155 + const { target } = args;
156 + const elCourseTrash = target.closest( BuilderTabCourse.selectors.elCourseTrash );
157 + const elCourseItem = elCourseTrash.closest( BuilderTabCourse.selectors.elCourseItem );
158 +
159 + if ( ! elCourseItem ) {
160 + return;
161 + }
162 +
163 + const courseId = elCourseItem.dataset.courseId || '';
164 +
165 + SweetAlert.fire( {
166 + title: elCourseTrash.dataset.title || 'Trash Course',
167 + text: elCourseTrash.dataset.content || 'Are you sure you want to move this course to trash?',
168 + iconHtml: SWAL_ICON_TRASH_DRAFT,
169 + customClass: { icon: 'lp-cb-swal-icon-html' },
170 + showCloseButton: true,
171 + showCancelButton: true,
172 + cancelButtonText: lpData.i18n.cancel,
173 + confirmButtonText: lpData.i18n.yes,
174 + reverseButtons: true,
175 + } ).then( ( result ) => {
176 + if ( result.isConfirmed ) {
177 + lpUtils.lpSetLoadingEl( elCourseTrash, 1 );
178 +
179 + const dataSend = {
180 + action: 'move_trash_course',
181 + args: { id_url: 'move-trash-course' },
182 + course_id: courseId,
183 + };
184 +
185 + const callBack = {
186 + success: ( response ) => {
187 + const { status, message, data } = response;
188 + lpToastify.show( message, status );
189 +
190 + if ( data?.status ) {
191 + const elCourse = elCourseTrash.closest( '.course' );
192 + this.updateStatusUI( elCourse, data.status );
193 + }
194 + },
195 + error: ( error ) => {
196 + lpToastify.show( error.message || error, 'error' );
197 + },
198 + completed: () => {
199 + lpUtils.lpSetLoadingEl( elCourseTrash, 0 );
200 + },
201 + };
202 +
203 + window.lpAJAXG.fetchAJAX( dataSend, callBack );
204 + }
205 + } );
206 + }
207 +
208 + draftCourse( args ) {
209 + const { target } = args;
210 + const elCourseDraft = target.closest( BuilderTabCourse.selectors.elCourseDraft );
211 + const elCourseItem = elCourseDraft.closest( BuilderTabCourse.selectors.elCourseItem );
212 +
213 + if ( ! elCourseItem ) {
214 + return;
215 + }
216 +
217 + // Check if published to show confirm unpublish modal
218 + const statusEl = elCourseItem.querySelector( BuilderTabCourse.selectors.elCourseStatus );
219 + const isPublished = statusEl && statusEl.classList.contains( 'publish' );
220 + if ( isPublished ) {
221 + const confirmMsg =
222 + elCourseDraft.dataset.confirmUnpublish ||
223 + 'Saving as draft will unpublish this item. Are you sure?';
224 +
225 + SweetAlert.fire( {
226 + title: 'Draft Course',
227 + text: confirmMsg,
228 + iconHtml: SWAL_ICON_TRASH_DRAFT,
229 + customClass: { icon: 'lp-cb-swal-icon-html' },
230 + showCloseButton: true,
231 + showCancelButton: true,
232 + cancelButtonText: lpData.i18n.cancel,
233 + confirmButtonText: lpData.i18n.yes,
234 + reverseButtons: true,
235 + } ).then( ( result ) => {
236 + if ( result.isConfirmed ) {
237 + this.draftCourseExecute( elCourseDraft, elCourseItem );
238 + }
239 + } );
240 + return;
241 + }
242 +
243 + this.draftCourseExecute( elCourseDraft, elCourseItem );
244 + }
245 +
246 + draftCourseExecute( elCourseDraft, elCourseItem ) {
247 + lpUtils.lpSetLoadingEl( elCourseDraft, 1 );
248 +
249 + const courseId = elCourseItem.dataset.courseId || '';
250 +
251 + const dataSend = {
252 + action: 'move_trash_course',
253 + args: { id_url: 'move-trash-course' },
254 + course_id: courseId || 0,
255 + status: 'draft',
256 + };
257 +
258 + const callBack = {
259 + success: ( response ) => {
260 + const { status, message, data } = response;
261 + lpToastify.show( message, status );
262 +
263 + if ( data?.status ) {
264 + const elCourse = elCourseDraft.closest( '.course' );
265 + this.updateStatusUI( elCourse, data.status );
266 + }
267 + },
268 + error: ( error ) => {
269 + lpToastify.show( error.message || error, 'error' );
270 + },
271 + completed: () => {
272 + lpUtils.lpSetLoadingEl( elCourseDraft, 0 );
273 + },
274 + };
275 +
276 + window.lpAJAXG.fetchAJAX( dataSend, callBack );
277 + }
278 +
279 + deleteCourse( args ) {
280 + const { target } = args;
281 + const elCourseDelete = target.closest( BuilderTabCourse.selectors.elCourseDelete );
282 + const elCourseItem = elCourseDelete.closest( BuilderTabCourse.selectors.elCourseItem );
283 +
284 + if ( ! elCourseItem ) {
285 + return;
286 + }
287 +
288 + const courseId = elCourseItem.dataset.courseId || '';
289 +
290 + if ( ! courseId ) {
291 + return;
292 + }
293 +
294 + SweetAlert.fire( {
295 + title: elCourseDelete.dataset.title || 'Delete Course',
296 + text:
297 + elCourseDelete.dataset.content ||
298 + 'Are you sure you want to permanently delete this course?',
299 + iconHtml: SWAL_ICON_DELETE,
300 + customClass: { icon: 'lp-cb-swal-icon-html' },
301 + showCloseButton: true,
302 + showCancelButton: true,
303 + cancelButtonText: lpData.i18n.cancel,
304 + confirmButtonText: lpData.i18n.yes,
305 + reverseButtons: true,
306 + } ).then( ( result ) => {
307 + if ( result.isConfirmed ) {
308 + const dataSend = {
309 + action: 'move_trash_course',
310 + args: { id_url: 'move-trash-course' },
311 + course_id: courseId,
312 + status: 'delete',
313 + };
314 +
315 + const callBack = {
316 + success: ( response ) => {
317 + const { status, message } = response;
318 + lpToastify.show( message, status );
319 + const elCourse = elCourseDelete.closest( '.course' );
320 +
321 + elCourse.style.transition = 'opacity 0.4s ease-out, transform 0.4s ease-out';
322 + elCourse.style.opacity = '0';
323 + elCourse.style.transform = 'translateX(160px)';
324 +
325 + setTimeout( () => {
326 + elCourse.remove();
327 + }, 400 );
328 + },
329 + error: ( error ) => {
330 + lpToastify.show( error.message || error, 'error' );
331 + },
332 + };
333 +
334 + window.lpAJAXG.fetchAJAX( dataSend, callBack );
335 + }
336 + } );
337 + }
338 +
339 + toggleExpandedAction( args ) {
340 + const { target } = args;
341 + const elCourseActionExpanded = target.closest(
342 + BuilderTabCourse.selectors.elCourseActionExpanded
343 + );
344 +
345 + if ( ! elCourseActionExpanded ) {
346 + return;
347 + }
348 +
349 + const elCourseItem = elCourseActionExpanded.closest( BuilderTabCourse.selectors.elCourseItem );
350 +
351 + if ( ! elCourseItem ) {
352 + return;
353 + }
354 +
355 + const elExpandedItems = elCourseItem.querySelector(
356 + BuilderTabCourse.selectors.elCourseExpandedItems
357 + );
358 +
359 + if ( ! elExpandedItems ) {
360 + return;
361 + }
362 +
363 + // Close others
364 + this.closeAllExpanded( elExpandedItems );
365 +
366 + elExpandedItems.classList.toggle( 'active' );
367 + elCourseActionExpanded.classList.toggle( 'active' );
368 + }
369 +
370 + closeAllExpanded( excludeElement = null ) {
371 + const allExpandedItems = document.querySelectorAll(
372 + `${ BuilderTabCourse.selectors.elCourseExpandedItems }.active`
373 + );
374 +
375 + allExpandedItems.forEach( ( item ) => {
376 + if ( item === excludeElement ) {
377 + return;
378 + }
379 +
380 + item.classList.remove( 'active' );
381 +
382 + const courseItem = item.closest( BuilderTabCourse.selectors.elCourseItem );
383 +
384 + if ( ! courseItem ) {
385 + return;
386 + }
387 +
388 + const expandedBtn = courseItem.querySelector(
389 + BuilderTabCourse.selectors.elCourseActionExpanded
390 + );
391 + if ( expandedBtn ) {
392 + expandedBtn.classList.remove( 'active' );
393 + }
394 + } );
395 + }
396 +
397 + updateStatusUI( elCourse, status ) {
398 + const elStatus = elCourse.querySelector( BuilderTabCourse.selectors.elCourseStatus );
399 + const elSpanStatus = elCourse.querySelector(
400 + `${ BuilderTabCourse.selectors.elCourseStatus } span`
401 + );
402 + if ( elSpanStatus && elStatus ) {
403 + elStatus.className = 'course-status ' + status;
404 + elSpanStatus.textContent = status;
405 + }
406 + }
407 +}