| 1 |
/** |
| 2 |
* Generate data with OpenAI |
| 3 |
*/ |
| 4 |
|
| 5 |
import * as lpUtils from 'lpAssetsJsPath/utils.js'; |
| 6 |
import * as lpToastify from 'lpAssetsJsPath/lpToastify.js'; |
| 7 |
import SweetAlert from 'sweetalert2'; |
| 8 |
import { EditSection } from './edit-section.js'; |
| 9 |
import { EditSectionItem } from './edit-section-item.js'; |
| 10 |
import { EditCourseCurriculum } from 'lpAssetsJsPath/admin/edit-course/edit-curriculum.js'; |
| 11 |
|
| 12 |
let editSection = null; |
| 13 |
let editSectionItem = null; |
| 14 |
|
| 15 |
export class EditCurriculumAi { |
| 16 |
constructor( options = {} ) { |
| 17 |
this.options = { |
| 18 |
isCourseBuilder: false, |
| 19 |
...options, |
| 20 |
}; |
| 21 |
|
| 22 |
this.init(); |
| 23 |
} |
| 24 |
|
| 25 |
static selectors = { |
| 26 |
elBtnApplyCurriculum: '.lp-btn-apply-curriculum', |
| 27 |
}; |
| 28 |
|
| 29 |
init() { |
| 30 |
if ( ! lpData?.enable_open_ai ) { |
| 31 |
return; |
| 32 |
} |
| 33 |
|
| 34 |
if ( this.options.isCourseBuilder ) { |
| 35 |
lpUtils.lpOnElementReady( EditCourseCurriculum.selectors.idElEditCurriculum, ( el ) => { |
| 36 |
const elCountSections = el.querySelector( EditSection.selectors.elCountSections ); |
| 37 |
elCountSections.insertAdjacentHTML( |
| 38 |
'beforebegin', |
| 39 |
`<button type="button" |
| 40 |
class="cb-course-edit-ai-btn lp-btn-generate-with-ai" |
| 41 |
data-template="#lp-tmpl-edit-course-curriculum-ai"> |
| 42 |
<i class="lp-ico-ai"></i> |
| 43 |
</button>` |
| 44 |
); |
| 45 |
} ); |
| 46 |
} else { |
| 47 |
lpUtils.lpOnElementReady( EditCourseCurriculum.selectors.idElEditCurriculum, ( el ) => { |
| 48 |
const elCountSections = el.querySelector( EditSection.selectors.elCountSections ); |
| 49 |
elCountSections.insertAdjacentHTML( |
| 50 |
'afterend', |
| 51 |
`<button type="button" |
| 52 |
class="lp-btn-generate-with-ai lp-btn-ai-style" |
| 53 |
data-template="#lp-tmpl-edit-course-curriculum-ai"> |
| 54 |
<i class="lp-ico-ai"></i><span>Generate with AI</span> |
| 55 |
</button>`, |
| 56 |
); |
| 57 |
} ); |
| 58 |
} |
| 59 |
|
| 60 |
this.events(); |
| 61 |
} |
| 62 |
|
| 63 |
events() { |
| 64 |
if ( EditCurriculumAi._loadedEvents ) { |
| 65 |
return; |
| 66 |
} |
| 67 |
EditCurriculumAi._loadedEvents = true; |
| 68 |
|
| 69 |
lpUtils.eventHandlers( 'click', [ |
| 70 |
{ |
| 71 |
selector: EditCurriculumAi.selectors.elBtnApplyCurriculum, |
| 72 |
class: this, |
| 73 |
callBack: this.applyData.name, |
| 74 |
}, |
| 75 |
] ); |
| 76 |
} |
| 77 |
|
| 78 |
async applyData( args ) { |
| 79 |
const { e, target } = args; |
| 80 |
let dataSend = JSON.parse( target.dataset.send ); |
| 81 |
dataSend = lpUtils.mergeDataWithDatForm( target.closest( 'form' ), dataSend ); |
| 82 |
|
| 83 |
if ( ! dataSend[ 'lp-openai-generated-data' ] ) { |
| 84 |
return; |
| 85 |
} |
| 86 |
|
| 87 |
const data = JSON.parse( dataSend[ 'lp-openai-generated-data' ] ); |
| 88 |
|
| 89 |
//console.log( 'Generated Data:', data ); |
| 90 |
|
| 91 |
const sections = data[ 0 ].sections; |
| 92 |
if ( ! sections || sections.length === 0 ) { |
| 93 |
lpToastify.show( 'No sections found in the generated data.', 'error' ); |
| 94 |
} |
| 95 |
|
| 96 |
// console.log( 'Generated Sections:', sections ); |
| 97 |
|
| 98 |
SweetAlert.close(); |
| 99 |
|
| 100 |
// Wait half second to ensure SweetAlert is closed completely |
| 101 |
await new Promise( ( resolve ) => setTimeout( resolve, 500 ) ); |
| 102 |
|
| 103 |
// New edit section instance |
| 104 |
editSection = new EditSection(); |
| 105 |
editSection.init(); |
| 106 |
|
| 107 |
// New edit section item instance |
| 108 |
editSectionItem = new EditSectionItem(); |
| 109 |
editSectionItem.init(); |
| 110 |
|
| 111 |
// Scroll to element add section |
| 112 |
const elEditCurriculum = document.querySelector( |
| 113 |
EditCourseCurriculum.selectors.idElEditCurriculum |
| 114 |
); |
| 115 |
const elDivAddNewSection = elEditCurriculum.querySelector( |
| 116 |
EditSection.selectors.elDivAddNewSection |
| 117 |
); |
| 118 |
elDivAddNewSection.scrollIntoView( { |
| 119 |
behavior: 'smooth', |
| 120 |
block: 'center', |
| 121 |
} ); |
| 122 |
|
| 123 |
// Wait 800ms to ensure scroll completely |
| 124 |
await new Promise( ( resolve ) => setTimeout( resolve, 800 ) ); |
| 125 |
|
| 126 |
for ( const sectionData of sections ) { |
| 127 |
// Set title |
| 128 |
const elSectionTitleNewInput = elEditCurriculum.querySelector( |
| 129 |
EditSection.selectors.elSectionTitleNewInput |
| 130 |
); |
| 131 |
const elBtnAddSection = elEditCurriculum.querySelector( |
| 132 |
EditSection.selectors.elBtnAddSection |
| 133 |
); |
| 134 |
elSectionTitleNewInput.value = sectionData.section_title || ''; |
| 135 |
|
| 136 |
await new Promise( ( resolve ) => { |
| 137 |
editSection.addSection( { |
| 138 |
e: new PointerEvent( 'click' ), |
| 139 |
target: elBtnAddSection, |
| 140 |
callBackNest: this.updateSectionDescription( { |
| 141 |
sectionData, |
| 142 |
elEditCurriculum, |
| 143 |
} ), |
| 144 |
resolve, |
| 145 |
} ); |
| 146 |
} ); |
| 147 |
} |
| 148 |
} |
| 149 |
|
| 150 |
/** |
| 151 |
* Update section description after create new section |
| 152 |
* @param args |
| 153 |
*/ |
| 154 |
updateSectionDescription( args ) { |
| 155 |
const { sectionData, elEditCurriculum } = args; |
| 156 |
|
| 157 |
return { |
| 158 |
success: async ( args ) => { |
| 159 |
const { elSection } = args; |
| 160 |
await new Promise( ( resolve ) => setTimeout( resolve, 1000 ) ); |
| 161 |
|
| 162 |
// Set description for the new section |
| 163 |
const elSectionDesInput = elSection.querySelector( |
| 164 |
EditSection.selectors.elSectionDesInput |
| 165 |
); |
| 166 |
elSectionDesInput.value = sectionData.section_description || ''; |
| 167 |
|
| 168 |
// Call AJAX to save description |
| 169 |
await new Promise( ( resolve ) => { |
| 170 |
editSection.updateSectionDescription( { |
| 171 |
e: new PointerEvent( 'click' ), |
| 172 |
target: elSectionDesInput, |
| 173 |
callBackNest: this.addSectionItems( { |
| 174 |
sectionData, |
| 175 |
elEditCurriculum, |
| 176 |
} ), |
| 177 |
resolve, |
| 178 |
} ); |
| 179 |
} ); |
| 180 |
|
| 181 |
setTimeout( args.resolve, 1 ); |
| 182 |
}, |
| 183 |
error: ( error ) => {}, |
| 184 |
completed: () => {}, |
| 185 |
}; |
| 186 |
} |
| 187 |
|
| 188 |
addSectionItems( args ) { |
| 189 |
const { sectionData, elEditCurriculum } = args; |
| 190 |
const lessons = sectionData.lessons || []; |
| 191 |
const quizzes = sectionData.quizzes || []; |
| 192 |
|
| 193 |
return { |
| 194 |
success: async ( args ) => { |
| 195 |
//await new Promise( ( resolve ) => setTimeout( resolve, 1000 ) ); |
| 196 |
const { elSection } = args; |
| 197 |
|
| 198 |
const elBtnSelectItemTypeLesson = elSection.querySelector( |
| 199 |
`${ EditSectionItem.selectors.elBtnSelectItemType }[data-item-type=lp_lesson]` |
| 200 |
); |
| 201 |
|
| 202 |
const elBtnSelectItemTypeQuiz = elSection.querySelector( |
| 203 |
`${ EditSectionItem.selectors.elBtnSelectItemType }[data-item-type=lp_quiz]` |
| 204 |
); |
| 205 |
|
| 206 |
for ( const itemData of lessons ) { |
| 207 |
elBtnSelectItemTypeLesson.click(); |
| 208 |
|
| 209 |
await this.addItemToSection( { |
| 210 |
itemData, |
| 211 |
elSection, |
| 212 |
elEditCurriculum, |
| 213 |
} ); |
| 214 |
} |
| 215 |
|
| 216 |
for ( const itemData of quizzes ) { |
| 217 |
elBtnSelectItemTypeQuiz.click(); |
| 218 |
|
| 219 |
await this.addItemToSection( { |
| 220 |
itemData, |
| 221 |
elSection, |
| 222 |
elEditCurriculum, |
| 223 |
} ); |
| 224 |
} |
| 225 |
|
| 226 |
setTimeout( args.resolve, 1 ); |
| 227 |
}, |
| 228 |
error: ( error ) => {}, |
| 229 |
completed: () => {}, |
| 230 |
}; |
| 231 |
} |
| 232 |
|
| 233 |
async addItemToSection( args ) { |
| 234 |
const { itemData, elSection, elEditCurriculum } = args; |
| 235 |
|
| 236 |
const elBtnAddItem = elSection.querySelector( EditSectionItem.selectors.elBtnAddItem ); |
| 237 |
const elAddItemTypeTitleInput = elSection.querySelector( |
| 238 |
EditSectionItem.selectors.elAddItemTypeTitleInput |
| 239 |
); |
| 240 |
elAddItemTypeTitleInput.value = itemData.lesson_title || itemData.quiz_title || ''; |
| 241 |
|
| 242 |
// Scroll to element add item |
| 243 |
elBtnAddItem.scrollIntoView( { behavior: 'smooth', block: 'center' } ); |
| 244 |
|
| 245 |
// Call AJAX to add item to section |
| 246 |
await new Promise( ( resolve ) => { |
| 247 |
editSectionItem.addItemToSection( { |
| 248 |
e: new PointerEvent( 'click' ), |
| 249 |
target: elBtnAddItem, |
| 250 |
resolve, |
| 251 |
callBackNest: { |
| 252 |
completed: async ( args ) => { |
| 253 |
setTimeout( resolve, 1000 ); |
| 254 |
}, |
| 255 |
}, |
| 256 |
} ); |
| 257 |
} ); |
| 258 |
|
| 259 |
setTimeout( args.resolve, 1 ); |
| 260 |
} |
| 261 |
} |
| 262 |
|