/** * Generate data with OpenAI */ import * as lpUtils from './../utils.js'; import SweetAlert from 'sweetalert2'; import * as lpToastify from 'lpAssetsJsPath/lpToastify.js'; let lp_structure_course; let popupSweetAlert = null; let lp_is_generating_course_data = false; const lp_course_ai_setting = JSON.parse( localStorage.getItem( 'lp_course_ai_setting' ) ) || {}; let isLayoutGutenberg = false; let selectGutenberg; let dispatchGutenberg; let editorGutenberg; export class GenerateWithOpenai { constructor( options = {} ) { this.options = { autoInsertButtons: true, isCourseBuilder: false, titleInputSelector: 'input[name=post_title]', courseBuilderTitleInputSelector: 'input[name=course_title]', editorIdClassic: 'content', editorIdCourseBuilder: 'course_description_editor', ...options, }; this.init(); } static selectors = { elBtnGenerateWithAi: '.lp-btn-generate-with-ai', elGenerateDataAiWrap: '.lp-generate-data-ai-wrap', }; init() { if ( ! lpData?.enable_open_ai ) { return; } if ( this.options.autoInsertButtons ) { lpUtils.lpOnElementReady( '#titlewrap', ( el ) => { el.insertAdjacentHTML( 'afterend', `` ); } ); lpUtils.lpOnElementReady( '#wp-content-media-buttons', ( el ) => { el.insertAdjacentHTML( 'beforeend', ``, ); } ); lpUtils.lpOnElementReady( '#postimagediv', ( el ) => { const elInside = el.querySelector( '.postbox-header' ); elInside.insertAdjacentHTML( 'afterend', `` ); } ); // Check is layout Gutenberg if ( wp.data && wp.data.select( 'core/editor' ) ) { isLayoutGutenberg = true; selectGutenberg = wp.data.select; dispatchGutenberg = wp.data.dispatch; editorGutenberg = selectGutenberg( 'core/editor' ); // For layout Gutenberg - button for title lpUtils.lpOnElementReady( '.editor-document-bar', ( el ) => { el.insertAdjacentHTML( 'afterend', `` ); } ); // For layout Gutenberg - button for description lpUtils.lpOnElementReady( '.editor-post-featured-image', ( el ) => { el.insertAdjacentHTML( 'beforebegin', `` ); } ); // For layout Gutenberg - button for image lpUtils.lpOnElementReady( '.editor-post-featured-image', ( el ) => { el.insertAdjacentHTML( 'afterend', `` ); } ); } } this.events(); } getTitleInputSelector() { return this.options.isCourseBuilder ? this.options.courseBuilderTitleInputSelector : this.options.titleInputSelector; } getEditorId() { return this.options.isCourseBuilder ? this.options.editorIdCourseBuilder : this.options.editorIdClassic; } setCourseBuilderPostId( form ) { if ( ! this.options.isCourseBuilder || ! form ) { return; } const postIdInput = form.querySelector( '[name="post-id"]' ); if ( ! postIdInput ) { return; } const courseEditWrap = document.querySelector( '.cb-section__course-edit[data-course-id]' ); const courseId = courseEditWrap?.dataset?.courseId || ''; if ( courseId ) { postIdInput.value = courseId; } } extractImageSourceFromHtml( html ) { if ( ! html ) { return ''; } const tempWrapper = document.createElement( 'div' ); tempWrapper.innerHTML = html; return tempWrapper.querySelector( 'img' )?.getAttribute( 'src' ) || ''; } applyCourseBuilderFeaturedImage( attachmentId, imageSrc ) { if ( ! attachmentId || ! imageSrc ) { return false; } document.dispatchEvent( new CustomEvent( 'lp-course-builder/ai-featured-image-applied', { detail: { attachmentId, imageSrc, }, } ) ); return true; } events() { lpUtils.eventHandlers( 'click', [ { selector: GenerateWithOpenai.selectors.elBtnGenerateWithAi, class: this, callBack: this.showPopup.name, }, { selector: '.lp-btn-step', class: this, callBack: this.showStep.name, }, { selector: '.lp-btn-generate-prompt', class: this, callBack: this.generatePrompt.name, }, { selector: '.lp-btn-call-open-ai', class: this, callBack: this.generateData.name, }, { selector: '.lp-btn-copy', class: this, callBack: this.copyGeneratedData.name, }, { selector: '.lp-btn-apply', class: this, callBack: this.applyGeneratedData.name, }, { selector: '.lp-btn-ai-apply-image', class: this, callBack: this.applyImageData.name, }, { selector: '.lp-btn-close-ai-popup', //class: this, callBack: ( args ) => { const { e, target } = args; const message = lpData.i18n.confirm_close_ai; if ( ! lp_is_generating_course_data ) { SweetAlert.close(); } else if ( confirm( message ) ) { SweetAlert.close(); } // Testing custom confirm box /*if ( confirm( message ) ) { SweetAlert.close(); }*/ }, }, ] ); } showPopup( args ) { const { e, target } = args; const templateId = target.dataset.template || target.closest( '.lp-btn-generate-with-ai' ).dataset.template || target.closest( '.lp-generate-data-ai-wrap' ).dataset.template || ''; const modalTemplate = document.querySelector( templateId ); if ( ! modalTemplate ) { console.error( `Template ${ templateId } not found!` ); return; } SweetAlert.fire( { html: modalTemplate.innerHTML, width: '60%', showCloseButton: false, showConfirmButton: false, allowOutsideClick: false, allowEscapeKey: false, didOpen: () => { popupSweetAlert = SweetAlert.getPopup(); // Click to show tomSelect style popupSweetAlert.click(); // Set post title and post content to hidden fields of form to AI prompt reference const elPostTitleInput = document.querySelector( this.getTitleInputSelector() ); let post_title = ''; if ( elPostTitleInput ) { post_title = elPostTitleInput.value; } else if ( isLayoutGutenberg ) { const elGutenbergTitle = document.querySelector( '.editor-post-card-panel__title-name' ); if ( elGutenbergTitle ) { post_title = elGutenbergTitle.textContent; } } let post_content = ''; if ( ! isLayoutGutenberg ) { const editorId = this.getEditorId(); if ( ! window.tinymce || ! window.tinymce.get( editorId ) ) { const editorElement = document.querySelector( `#${ editorId }` ); post_content = editorElement ? editorElement.value : ''; } else { post_content = window.tinymce.get( editorId ).getContent( { format: 'text' } ); } } else { const content = editorGutenberg.getEditedPostContent(); post_content = content.replace( /(<([^>]+)>)/gi, '' ); // Remove HTML tags } const form = popupSweetAlert.querySelector( 'form' ); this.setCourseBuilderPostId( form ); const elPostTitle = form.querySelector( '[name=post-title]' ); if ( elPostTitle ) { elPostTitle.value = post_title; if ( ! post_title ) { const elGroup = elPostTitle.closest( '.form-group' ); const elReferWarning = elGroup.querySelector( '.lp-ai-warning-refer' ); if ( elReferWarning ) { lpUtils.lpShowHideEl( elReferWarning, 1 ); } } } const elPostContent = form.querySelector( '[name=post-content]' ); if ( elPostContent ) { elPostContent.value = post_content; if ( post_content.length < 2 ) { const elGroup = elPostContent.closest( '.form-group' ); const elReferWarning = elGroup.querySelector( '.lp-ai-warning-refer' ); if ( elReferWarning ) { lpUtils.lpShowHideEl( elReferWarning, 1 ); } } } const targetAudience = popupSweetAlert.querySelector( 'select[name="target_audience"]' ); if ( targetAudience ) { if ( lp_course_ai_setting?.target_audience ) { targetAudience.tomselect.setValue( lp_course_ai_setting.target_audience ); } targetAudience.addEventListener( 'change', ( event ) => { lp_course_ai_setting.target_audience = targetAudience.tomselect.getValue(); localStorage.setItem( 'lp_course_ai_setting', JSON.stringify( lp_course_ai_setting ) ); } ); } const tone = popupSweetAlert.querySelector( 'select[name="tone"]' ); if ( tone ) { if ( lp_course_ai_setting?.tone ) { tone.tomselect.setValue( lp_course_ai_setting.tone ); } tone.addEventListener( 'change', ( event ) => { lp_course_ai_setting.tone = tone.tomselect.getValue(); localStorage.setItem( 'lp_course_ai_setting', JSON.stringify( lp_course_ai_setting ) ); } ); } const language = popupSweetAlert.querySelector( 'select[name="language"]' ); if ( language ) { if ( lp_course_ai_setting?.language ) { language.tomselect.setValue( lp_course_ai_setting.language ); } language.addEventListener( 'change', ( event ) => { const value = language.tomselect.getValue(); lp_course_ai_setting.language = value ? [ value ] : []; localStorage.setItem( 'lp_course_ai_setting', JSON.stringify( lp_course_ai_setting ) ); } ); } }, } ).then( ( result ) => { if ( result.isDismissed ) { if ( lp_is_generating_course_data ) { lp_is_generating_course_data = false; } } } ); } showStep( args ) { const { e, target } = args; e.preventDefault(); const elBtnActions = target.closest( '.button-actions' ); const elCreateCourseAIWrap = elBtnActions.closest( GenerateWithOpenai.selectors.elGenerateDataAiWrap ); let step = parseInt( elBtnActions.dataset.step ); const stepAction = target.dataset.action; if ( stepAction === 'next' ) { step++; } else if ( stepAction === 'prev' ) { step--; } elBtnActions.dataset.step = step; const elForm = target.closest( 'form' ); const elContentStep = elForm.querySelector( `.step-content[data-step="${ step }"]` ); const elItemStep = elCreateCourseAIWrap.querySelector( `.step-item[data-step="${ step }"]` ); elForm.querySelectorAll( '.step-content' ).forEach( ( el ) => el.classList.remove( 'active' ) ); elContentStep.classList.add( 'active' ); elCreateCourseAIWrap .querySelectorAll( '.step-item' ) .forEach( ( el ) => el.classList.remove( 'active' ) ); elItemStep.classList.add( 'active' ); // Get all buttons step to show/hide const form = target.closest( 'form' ); const elBtnSteps = form.querySelectorAll( 'button[data-step-show]' ); elBtnSteps.forEach( ( el ) => { const stepsShow = el.dataset.stepShow.split( ',' ).map( ( s ) => parseInt( s.trim() ) ); if ( stepsShow.includes( step ) ) { lpUtils.lpShowHideEl( el, 1 ); } else { lpUtils.lpShowHideEl( el, 0 ); } } ); } /** * Create prompt from data config * @param args */ generatePrompt( args ) { const { e, target } = args; e.preventDefault(); lpUtils.lpSetLoadingEl( target, true ); // Get dataSend const form = target.closest( 'form' ); let dataSend = JSON.parse( target.dataset.send ); dataSend = lpUtils.mergeDataWithDatForm( form, dataSend ); // Ajax to generate prompt const callBack = { success: ( response ) => { const { message, status, data } = response; lpToastify.show( message, status ); if ( status === 'success' ) { const elPromptTextarea = form.querySelector( 'textarea[name=lp-openai-prompt-generated-field]' ); elPromptTextarea.value = data; const elBtnNext = form.querySelector( '.lp-btn-step[data-action=next]' ); elBtnNext.click(); } }, error: ( error ) => { lpToastify.show( error, 'error' ); }, completed: () => { lpUtils.lpSetLoadingEl( target, false ); }, }; window.lpAJAXG.fetchAJAX( dataSend, callBack ); } /** * Submit prompt to OpenAI to generate course data * @param args */ generateData( args ) { const { e, target } = args; e.preventDefault(); lpUtils.lpSetLoadingEl( target, true ); // Get dataSend const form = target.closest( 'form' ); let dataSend = JSON.parse( target.dataset.send ); dataSend = lpUtils.mergeDataWithDatForm( form, dataSend ); const btnPrev = form.querySelector( '.lp-btn-step[data-action=prev]' ); lpUtils.lpShowHideEl( btnPrev, 0 ); // Ajax to generate prompt const callBack = { success: ( response ) => { const { message, status, data } = response; if ( lp_is_generating_course_data ) { lpToastify.show( message, status ); } if ( status === 'success' ) { // Save structure data lp_structure_course = data.lp_structure_course; // Set preview HTML const elResults = form.querySelector( '.lp-ai-generated-results' ); elResults.innerHTML = data.lp_html_preview; const elBtnNext = form.querySelector( '.lp-btn-step[data-action=next]' ); elBtnNext.click(); } }, error: ( error ) => { lpToastify.show( error, 'error' ); }, completed: () => { lpUtils.lpSetLoadingEl( target, false ); lpUtils.lpShowHideEl( btnPrev, 1 ); lp_is_generating_course_data = false; }, }; lp_is_generating_course_data = true; window.lpAJAXG.fetchAJAX( dataSend, callBack ); } applyGeneratedData( args ) { const { e, target } = args; e.preventDefault(); const dataApply = target.dataset.apply; const dataTarget = target.dataset.target; if ( dataTarget ) { if ( ! isLayoutGutenberg ) { if ( dataTarget === 'set-wp-editor-content' ) { this.setWPEditorContent( dataApply ); } else if ( dataTarget === 'set-wp-title' ) { const elTitleInput = document.querySelector( this.getTitleInputSelector() ); if ( elTitleInput ) { elTitleInput.value = dataApply; elTitleInput.dispatchEvent( new Event( 'input', { bubbles: true } ) ); } } } else if ( dataTarget === 'set-wp-editor-content' ) { dispatchGutenberg( 'core/editor' ).editPost( { content: dataApply } ); } else if ( dataTarget === 'set-wp-title' ) { dispatchGutenberg( 'core/editor' ).editPost( { title: dataApply } ); } } if ( popupSweetAlert ) { SweetAlert.close(); } } copyGeneratedData( args ) { const { e, target } = args; e.preventDefault(); const dataCopy = target.dataset.copy; if ( navigator.clipboard ) { navigator.clipboard .writeText( dataCopy ) .then( () => { lpToastify.show( 'Copied to clipboard!', 'success' ); } ) .catch( ( err ) => { lpToastify.show( 'Failed to copy text: ' + err, 'error' ); } ); } else { // Fallback when clipboard API is unavailable const textarea = document.createElement( 'textarea' ); textarea.value = dataCopy; textarea.style.position = 'fixed'; textarea.style.left = '-9999px'; document.body.appendChild( textarea ); textarea.select(); try { const successful = document.execCommand( 'copy' ); lpToastify.show( successful ? 'Copied to clipboard!' : 'Failed to copy text', successful ? 'success' : 'error' ); } catch ( err ) { lpToastify.show( 'Failed to copy text: ' + err, 'error' ); } document.body.removeChild( textarea ); } /*navigator.clipboard.writeText( dataCopy ).then( () => { lpToastify.show( 'Copied to clipboard!', 'success' ); } ).catch( ( err ) => { lpToastify.show( 'Failed to copy text: ' + err, 'error' ); } );*/ } setWPEditorContent( htmlContent ) { const editorId = this.getEditorId(); const editor = window.tinymce?.get( editorId ); if ( editor ) { editor.setContent( htmlContent ); return; } const editorElement = document.querySelector( `#${ editorId }` ); if ( editorElement ) { editorElement.value = htmlContent; editorElement.dispatchEvent( new Event( 'input', { bubbles: true } ) ); } } applyImageData( args ) { const { e, target } = args; let dataSend = JSON.parse( target.dataset.send ); dataSend = lpUtils.mergeDataWithDatForm( target.closest( 'form' ), dataSend ); //e.preventDefault(); lpUtils.lpSetLoadingEl( target, true ); // Ajax to generate prompt const callBack = { success: ( response ) => { const { message, status, data } = response; lpToastify.show( message, status ); if ( status === 'success' ) { if ( this.options.isCourseBuilder ) { const attachmentId = parseInt( data?.attachment_id || 0, 10 ); const imageSrc = this.extractImageSourceFromHtml( data?.html_image || '' ); const applied = this.applyCourseBuilderFeaturedImage( attachmentId, imageSrc ); if ( ! applied ) { lpToastify.show( 'Failed to apply image to course featured image.', 'error' ); return; } } else if ( ! isLayoutGutenberg ) { // Set image const elImagePreview = document.querySelector( '#postimagediv .inside' ); elImagePreview.outerHTML = data.html_image; } else { dispatchGutenberg( 'core/editor' ).editPost( { featured_media: data.attachment_id } ); } if ( popupSweetAlert ) { SweetAlert.close(); } } }, error: ( error ) => { lpToastify.show( error, 'error' ); }, completed: () => { lpUtils.lpSetLoadingEl( target, false ); }, }; window.lpAJAXG.fetchAJAX( dataSend, callBack ); } }