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 / courses / generate-with-ai.js

generate-with-ai.js in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.2, at assets/src/js/admin/courses/generate-with-ai.js

389 lines 10.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Create course with AI
3 */
4
5 import * as lpUtils from 'lpAssetsJsPath/utils.js';
6 import SweetAlert from 'sweetalert2';
7 import * as lpToastify from 'lpAssetsJsPath/lpToastify.js';
8 let lp_structure_course;
9 let lp_is_generating_course_data = false;
10 const lp_course_ai_setting = JSON.parse( localStorage.getItem( 'lp_course_ai_setting' ) ) || {};
11
12 export class CreateCourseViaAI {
13 constructor( options = {} ) {
14 this.options = {
15 autoInsertButton: true,
16 isCourseBuilder: false,
17 redirectDelayMs: 2000,
18 ...options,
19 };
20
21 this.init();
22 }
23
24 static selectors = {
25 elGenerateDataAiWrap: '.lp-generate-data-ai-wrap',
26 };
27
28 init() {
29 if ( this.options.autoInsertButton ) {
30 if ( ! lpData?.enable_open_ai ) {
31 lpUtils.lpOnElementReady( '.page-title-action', ( el ) => {
32 el.insertAdjacentHTML(
33 'afterend',
34 `<button type="button" class="lp-btn-warning-enable-ai lp-btn-ai-style">
35 <i class="lp-ico-ai"></i>
36 <span>${ lpData.i18n.generate_with_ai }</span>
37 </button>`
38 );
39 } );
40 } else {
41 lpUtils.lpOnElementReady( '.page-title-action', ( el ) => {
42 el.insertAdjacentHTML(
43 'afterend',
44 `<button type="button" class="lp-btn-generate-course-with-ai lp-btn-ai-style">
45 <i class="lp-ico-ai"></i>
46 <span>${ lpData.i18n.generate_with_ai }</span>
47 </button>`
48 );
49 } );
50 }
51 }
52
53 this.events();
54 }
55
56 events() {
57 if ( CreateCourseViaAI._loadedEvents ) {
58 return;
59 }
60 CreateCourseViaAI._loadedEvents = true;
61
62 lpUtils.eventHandlers( 'click', [
63 {
64 selector: '.lp-btn-warning-enable-ai',
65 class: this,
66 callBack: this.showPopupEnableAI.name,
67 },
68 {
69 selector: '.lp-btn-generate-course-with-ai',
70 class: this,
71 callBack: this.showPopupCreateFullCourse.name,
72 },
73 {
74 selector: '.lp-btn-step',
75 class: this,
76 callBack: this.showStep.name,
77 },
78 {
79 selector: '.lp-btn-generate-prompt',
80 class: this,
81 callBack: this.generatePrompt.name,
82 },
83 {
84 selector: '.lp-btn-call-open-ai',
85 class: this,
86 callBack: this.generateDataCourse.name,
87 },
88 {
89 selector: '.lp-btn-create-course',
90 class: this,
91 callBack: this.createCourse.name,
92 },
93 {
94 selector: '.lp-btn-close-ai-popup',
95 //class: this,
96 callBack: ( args ) => {
97 const { e, target } = args;
98
99 const message = lpData?.i18n?.confirm_close_ai || 'Are you sure you want to close? Generate data will stop.';
100
101 if ( ! lp_is_generating_course_data ) {
102 SweetAlert.close();
103 } else if ( confirm( message ) ) {
104 SweetAlert.close();
105 }
106
107 // Testing custom confirm box
108 /*if ( confirm( message ) ) {
109 SweetAlert.close();
110 }*/
111 },
112 },
113 ] );
114 }
115
116 // Show popup warning enable AI before using.
117 showPopupEnableAI() {
118 const modalTemplate = document.querySelector( '#lp-tmpl-must-enable-ai' );
119
120 if ( ! modalTemplate ) {
121 console.error( 'Enable OpenAI Modal Template not found!' );
122 return;
123 }
124
125 SweetAlert.fire( {
126 html: modalTemplate.innerHTML,
127 width: '420px',
128 showCloseButton: false,
129 showConfirmButton: false,
130 } );
131 }
132
133 showPopupCreateFullCourse() {
134 const modalTemplate = document.querySelector(
135 '#lp-tmpl-create-course-ai'
136 );
137
138 if ( ! modalTemplate ) {
139 console.error( 'AI Create Full Course Modal Template not found!' );
140 return;
141 }
142
143 SweetAlert.fire( {
144 html: modalTemplate.innerHTML,
145 width: '60%',
146 showCloseButton: false,
147 showConfirmButton: false,
148 allowOutsideClick: false,
149 allowEscapeKey: false,
150 didOpen: () => {
151 const popup = SweetAlert.getPopup();
152 popup.click();
153
154 const targetAudience = popup.querySelector( 'select[name="target_audience"]' );
155 if ( targetAudience && lp_course_ai_setting?.target_audience ) {
156 targetAudience.tomselect.setValue( lp_course_ai_setting.target_audience );
157 }
158 const tone = popup.querySelector( 'select[name="tone"]' );
159 if ( tone && lp_course_ai_setting?.tone ) {
160 tone.tomselect.setValue( lp_course_ai_setting.tone );
161 }
162 const language = popup.querySelector( 'select[name="language"]' );
163 if ( language && lp_course_ai_setting?.language ) {
164 language.tomselect.setValue( lp_course_ai_setting.language );
165 }
166
167 targetAudience.addEventListener( 'change', ( event ) => {
168 lp_course_ai_setting.target_audience = targetAudience.tomselect.getValue();
169 localStorage.setItem( 'lp_course_ai_setting', JSON.stringify( lp_course_ai_setting ) );
170 } );
171
172 tone.addEventListener( 'change', ( event ) => {
173 lp_course_ai_setting.tone = tone.tomselect.getValue();
174 localStorage.setItem( 'lp_course_ai_setting', JSON.stringify( lp_course_ai_setting ) );
175 } );
176
177 language.addEventListener( 'change', ( event ) => {
178 const value = language.tomselect.getValue();
179 lp_course_ai_setting.language = value ? [ value ] : [];
180 localStorage.setItem( 'lp_course_ai_setting', JSON.stringify( lp_course_ai_setting ) );
181 } );
182 },
183 } ).then( ( result ) => {
184 if ( result.isDismissed ) {
185 if ( lp_is_generating_course_data ) {
186 lp_is_generating_course_data = false;
187 }
188 }
189 } );
190 }
191
192 showStep( args ) {
193 const { e, target } = args;
194 e.preventDefault();
195
196 const elBtnActions = target.closest( '.button-actions' );
197 const elCreateCourseAIWrap = elBtnActions.closest( CreateCourseViaAI.selectors.elGenerateDataAiWrap );
198 let step = parseInt( elBtnActions.dataset.step );
199
200 const stepAction = target.dataset.action;
201 if ( stepAction === 'next' ) {
202 step++;
203 } else if ( stepAction === 'prev' ) {
204 step--;
205 }
206
207 elBtnActions.dataset.step = step;
208 const elForm = target.closest( 'form' );
209 const elContentStep = elForm.querySelector( `.step-content[data-step="${ step }"]` );
210 const elItemStep = elCreateCourseAIWrap.querySelector( `.step-item[data-step="${ step }"]` );
211 elForm.querySelectorAll( '.step-content' ).forEach( ( el ) => el.classList.remove( 'active' ) );
212 elContentStep.classList.add( 'active' );
213 elCreateCourseAIWrap.querySelectorAll( '.step-item' ).forEach( ( el ) => el.classList.remove( 'active' ) );
214 elItemStep.classList.add( 'active' );
215
216 // Get all buttons step to show/hide
217 const form = target.closest( 'form' );
218 const elBtnSteps = form.querySelectorAll( 'button[data-step-show]' );
219 elBtnSteps.forEach( ( el ) => {
220 const stepsShow = el.dataset.stepShow.split( ',' ).map( ( s ) => parseInt( s.trim() ) );
221 if ( stepsShow.includes( step ) ) {
222 lpUtils.lpShowHideEl( el, 1 );
223 } else {
224 lpUtils.lpShowHideEl( el, 0 );
225 }
226 } );
227 }
228
229 /**
230 * Create prompt from data config
231 * @param args
232 */
233 generatePrompt( args ) {
234 const { e, target } = args;
235 e.preventDefault();
236 lpUtils.lpSetLoadingEl( target, true );
237
238 // Get dataSend
239 const form = target.closest( 'form' );
240 let dataSend = JSON.parse( target.dataset.send );
241 dataSend = lpUtils.mergeDataWithDatForm( form, dataSend );
242
243 // Ajax to generate prompt
244 const callBack = {
245 success: ( response ) => {
246 const { message, status, data } = response;
247
248 lpToastify.show( message, status );
249
250 if ( status === 'success' ) {
251 const elBtnNext = form.querySelector( '.lp-btn-step[data-action=next]' );
252 elBtnNext.click();
253
254 const elPromptTextarea = form.querySelector( 'textarea[name=lp-openai-prompt-generated-field]' );
255 elPromptTextarea.value = data;
256 }
257 },
258 error: ( error ) => {
259 lpToastify.show( error, 'error' );
260 },
261 completed: () => {
262 lpUtils.lpSetLoadingEl( target, false );
263 },
264 };
265
266 window.lpAJAXG.fetchAJAX( dataSend, callBack );
267 }
268
269 /**
270 * Submit prompt to OpenAI to generate course data
271 * @param args
272 */
273 generateDataCourse( args ) {
274 const { e, target } = args;
275 e.preventDefault();
276 lpUtils.lpSetLoadingEl( target, true );
277
278 // Get dataSend
279 const form = target.closest( 'form' );
280 let dataSend = JSON.parse( target.dataset.send );
281 dataSend = lpUtils.mergeDataWithDatForm( form, dataSend );
282
283 const btnPrev = form.querySelector( '.lp-btn-step[data-action=prev]' );
284 lpUtils.lpShowHideEl( btnPrev, 0 );
285
286 // Ajax to generate prompt
287 const callBack = {
288 success: ( response ) => {
289 const { message, status, data } = response;
290
291 if ( lp_is_generating_course_data ) {
292 lpToastify.show( message, status );
293 }
294
295 if ( status === 'success' ) {
296 // Save structure data
297 lp_structure_course = data.lp_structure_course;
298
299 // Set preview HTML
300 const elResults = form.querySelector( '.lp-ai-generated-results' );
301 elResults.innerHTML = data.lp_html_preview;
302
303 const elBtnNext = form.querySelector( '.lp-btn-step[data-action=next]' );
304 elBtnNext.click();
305 }
306 },
307 error: ( error ) => {
308 lpToastify.show( error, 'error' );
309 },
310 completed: () => {
311 lpUtils.lpSetLoadingEl( target, false );
312 lpUtils.lpShowHideEl( btnPrev, 1 );
313 lp_is_generating_course_data = false;
314 },
315 };
316
317 lp_is_generating_course_data = true;
318 window.lpAJAXG.fetchAJAX( dataSend, callBack );
319 }
320
321 /**
322 * Create course with data of OpenAI
323 * @param args
324 */
325 createCourse( args ) {
326 const { e, target } = args;
327 e.preventDefault();
328 lpUtils.lpSetLoadingEl( target, true );
329
330 // Get dataSend
331 const dataSend = JSON.parse( target.dataset.send );
332 dataSend.lp_structure_course = lp_structure_course;
333 if ( this.options.isCourseBuilder ) {
334 dataSend.is_course_builder = 1;
335 }
336
337 const form = target.closest( 'form' );
338 const elBtnPrev = form.querySelector( '.lp-btn-step[data-action=prev]' );
339 lpUtils.lpShowHideEl( elBtnPrev, 0 );
340
341 const windowWidth = window.outerWidth;
342 let alertWidth;
343 if ( windowWidth < 768 ) {
344 alertWidth = '90%';
345 } else {
346 alertWidth = '30%';
347 }
348
349 const creatingCourseAiModal = document.querySelector( '#lp-tmpl-creating-course-ai' );
350 SweetAlert.fire( {
351 html: creatingCourseAiModal.innerHTML,
352 showCloseButton: false,
353 showConfirmButton: false,
354 allowOutsideClick: false,
355 width: alertWidth,
356 } );
357
358 // Ajax to generate prompt
359 const callBack = {
360 success: ( response ) => {
361 const { message, status, data } = response;
362
363 SweetAlert.close();
364 lpToastify.show( message, status );
365
366 if ( status === 'success' ) {
367 setTimeout(
368 () => {
369 window.location.href = data.edit_course_url;
370 },
371 this.options.redirectDelayMs
372 );
373 } else {
374 lpUtils.lpShowHideEl( elBtnPrev, 1 );
375 }
376 },
377 error: ( error ) => {
378 lpToastify.show( error, 'error' );
379 lpUtils.lpShowHideEl( elBtnPrev, 1 );
380 },
381 completed: () => {
382 lpUtils.lpSetLoadingEl( target, false );
383 },
384 };
385
386 window.lpAJAXG.fetchAJAX( dataSend, callBack );
387 }
388 }
389