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 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 All 140 releases
learnpress / assets / src / apps / js / frontend / quiz / components / buttons / index.js

index.js in LearnPress – WordPress LMS Plugin for Create and Sell Online Courses 4.4.9, at assets/src/apps/js/frontend/quiz/components/buttons/index.js

468 lines 10.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { Component } from '@wordpress/element';
2 import { withSelect, withDispatch, select } from '@wordpress/data';
3 import { compose } from '@wordpress/compose';
4 import { __ } from '@wordpress/i18n';
5
6 class Buttons extends Component {
7 startQuiz = ( event ) => {
8 event && event.preventDefault();
9 const btn = document.querySelector( '.lp-button.start' );
10 btn && btn.setAttribute( 'disabled', 'disabled' );
11 btn.classList.add( 'loading' );
12 const { startQuiz, status } = this.props;
13
14 if ( status === 'completed' ) {
15 const { confirm, isOpen } = select( 'learnpress/modal' );
16
17 if ( 'no' === confirm( __( 'Are you sure you want to retake the quiz?', 'learnpress' ), this.startQuiz ) ) {
18 ! isOpen() && btn && btn.removeAttribute( 'disabled' );
19 btn.classList.remove( 'loading' );
20 return;
21 }
22 }
23
24 // No require enroll
25 /*if ( lpQuizSettings.checkNorequizenroll === 1 ) {
26 // Reset data
27 window.localStorage.removeItem( 'quiz_start_' + lpQuizSettings.id );
28 window.localStorage.removeItem( 'quiz_userdata_' + lpQuizSettings.id );
29 window.localStorage.setItem( 'quiz_start_' + lpQuizSettings.id, Date.now() );
30
31 // Set retake to local.storage
32 const retakenNumber = window.localStorage.getItem( 'quiz_retake_' + lpQuizSettings.id );
33 if ( retakenNumber >= 1 ) {
34 window.localStorage.setItem( 'quiz_retake_' + lpQuizSettings.id, parseInt( retakenNumber ) + 1 );
35 } else {
36 window.localStorage.setItem( 'quiz_retake_' + lpQuizSettings.id, 1 );
37 }
38 }*/
39
40 startQuiz();
41 };
42
43 nav = ( to ) => ( event ) => {
44 let {
45 questionNav,
46 currentPage,
47 numPages,
48 setCurrentPage,
49 } = this.props;
50
51 switch ( to ) {
52 case 'prev':
53 if ( currentPage > 1 ) {
54 currentPage = currentPage - 1;
55 } else if ( questionNav === 'infinity' ) {
56 currentPage = numPages;
57 } else {
58 currentPage = 1;
59 }
60 break;
61 default:
62 if ( currentPage < numPages ) {
63 currentPage = currentPage + 1;
64 } else if ( questionNav === 'infinity' ) {
65 currentPage = 1;
66 } else {
67 currentPage = numPages;
68 }
69 }
70
71 setCurrentPage( currentPage );
72 };
73
74 moveTo = ( pageNum ) => ( event ) => {
75 event.preventDefault();
76
77 const {
78 numPages,
79 setCurrentPage,
80 } = this.props;
81
82 if ( pageNum < 1 || pageNum > numPages ) {
83 return;
84 }
85
86 setCurrentPage( pageNum );
87 };
88
89 isLast = () => {
90 const { currentPage, numPages } = this.props;
91
92 return currentPage === numPages;
93 };
94
95 isFirst = () => {
96 const { currentPage } = this.props;
97
98 return currentPage === 1;
99 };
100
101 submit = () => {
102 const { submitQuiz } = this.props;
103
104 const { confirm } = select( 'learnpress/modal' );
105
106 if ( 'no' === confirm( __( 'Are you sure to submit the quiz?', 'learnpress' ), this.submit ) ) {
107 return;
108 }
109 submitQuiz();
110 };
111
112 setQuizMode = ( mode ) => () => {
113 const { setQuizMode } = this.props;
114
115 setQuizMode( mode );
116 };
117
118 isReviewing = () => {
119 const { isReviewing } = this.props;
120
121 return isReviewing;
122 };
123
124 pageNumbers( args ) {
125 const { numPages, currentPage } = this.props;
126
127 if ( numPages < 2 ) {
128 return '';
129 }
130
131 args = {
132 numPages,
133 currentPage,
134 midSize: 1,
135 endSize: 1,
136 prevNext: true,
137 ...( args || {} ),
138 };
139
140 if ( args.endSize < 1 ) {
141 args.endSize = 1;
142 }
143
144 if ( args.midSize < 0 ) {
145 args.midSize = 1;
146 }
147
148 const numbers = [ ...Array( numPages ).keys() ];
149 let dots = false;
150
151 return (
152 <div className="nav-links">
153
154 { args.prevNext && ! this.isFirst() && (
155 <button
156 className="page-numbers prev"
157 data-type="question-navx"
158 onClick={ this.nav( 'prev' ) }
159 >
160 { __( 'Prev', 'learnpress' ) }
161 </button>
162 ) }
163
164 { numbers.map( ( number ) => {
165 number = number + 1;
166
167 if ( number === args.currentPage ) {
168 dots = true;
169
170 return (
171 <span key={ `page-number-${ number }` } className="page-numbers current">{ number }</span>
172 );
173 }
174
175 if ( number <= args.endSize || ( args.currentPage && number >= args.currentPage - args.midSize && number <= args.currentPage + args.midSize ) || number > args.numPages - args.endSize ) {
176 dots = true;
177
178 return (
179 <button
180 key={ `page-number-${ number }` }
181 className="page-numbers"
182 onClick={ this.moveTo( number ) }
183 >
184 { number }
185 </button>
186 );
187 } else if ( dots ) {
188 dots = false;
189
190 return (
191 <span key={ `page-number-${ number }` } className="page-numbers dots">&hellip;</span>
192 );
193 }
194
195 return '';
196 } ) }
197
198 { args.prevNext && ! this.isLast() && (
199 <button
200 className="page-numbers next"
201 data-type="question-navx"
202 onClick={ this.nav( 'next' ) }
203 >
204 { __( 'Next', 'learnpress' ) }
205 </button>
206 ) }
207 </div>
208 );
209 }
210
211 render() {
212 const {
213 status,
214 questionNav,
215 isReviewing,
216 showReview,
217 numPages,
218 question,
219 questionsPerPage,
220 canRetry,
221 retakeNumber,
222 requiredPassword,
223 allowRetake,
224 } = this.props;
225
226 const classNames = [ 'quiz-buttons' ];
227
228 if ( status === 'started' || isReviewing ) {
229 classNames.push( 'align-center' );
230 }
231
232 if ( questionNav === 'questionNav' ) {
233 classNames.push( 'infinity' );
234 }
235
236 if ( this.isFirst() ) {
237 classNames.push( 'is-first' );
238 }
239
240 if ( this.isLast() ) {
241 classNames.push( 'is-last' );
242 }
243
244 const popupSidebar = document.querySelector( '#popup-sidebar' );
245 const quizzApp = document.querySelector( '#learn-press-quiz-app' );
246
247 let styles = '';
248
249 if ( status === 'started' || isReviewing ) {
250 styles = { marginLeft: popupSidebar && popupSidebar.offsetWidth / 2, width: quizzApp && quizzApp.offsetWidth };
251 } else {
252 styles = null;
253 }
254 let navPositionClass = ' fixed';
255 if ( lpQuizSettings.navigationPosition == 'no' ) {
256 navPositionClass = ' nav-center';
257 }
258 return (
259 <>
260 <div className={ classNames.join( ' ' ) }>
261 <div
262 className={ `button-left` + ( ( status === 'started' || isReviewing ) ? navPositionClass : '' ) }
263 style={ styles }
264 >
265
266 { ( ( status === 'completed' && canRetry ) || -1 !== [ '', 'viewed' ].indexOf( status ) ) && ! isReviewing && ! requiredPassword && (
267 <button className="lp-button start" onClick={ this.startQuiz }>
268 { ( status === 'completed' ) ? `${ __( 'Retake', 'learnpress' ) } ${ ! allowRetake ? ` ${ retakeNumber ? ` (${ retakeNumber })` : '' }` : '' } ` : ' ' + __( 'Start', 'learnpress' ) }
269 </button>
270 ) }
271
272 { ( 'started' === status || isReviewing ) && ( numPages > 1 ) && (
273 <>
274 <div className="questions-pagination">
275 { this.pageNumbers() }
276 </div>
277 </>
278 ) }
279 </div>
280
281 <div className="button-right">
282 { ( 'started' === status ) && (
283 <>
284 { ( ( 'infinity' === questionNav || this.isLast() ) && ! isReviewing ) && (
285 <button
286 className="lp-button submit-quiz"
287 onClick={ this.submit }
288 >
289 { __( 'Finish Quiz', 'learnpress' ) }
290 </button>
291 ) }
292 </>
293 ) }
294
295 { isReviewing && showReview && (
296 <button
297 className="lp-button back-quiz"
298 onClick={ this.setQuizMode( '' ) }
299 >
300 { __( 'Result', 'learnpress' ) }
301 </button>
302 ) }
303
304 { 'completed' === status && showReview && ! isReviewing && (
305 <button
306 className="lp-button review-quiz"
307 onClick={ this.setQuizMode( 'reviewing' ) }
308 >
309 { __( 'Review', 'learnpress' ) }
310 </button>
311 ) }
312 </div>
313 </div>
314
315 { this.props.message && this.props.success !== true && (
316 <div className="learn-press-message error">
317 { this.props.message }
318 </div>
319 ) }
320 </>
321 );
322 }
323 }
324
325 /**
326 * Helper function to check a button should be show or not.
327 *
328 * Buttons [hint, check]
329 */
330 export const MaybeShowButton = compose(
331 withSelect( ( select ) => {
332 const {
333 getData,
334 } = select( 'learnpress/quiz' );
335
336 return {
337 status: getData( 'status' ),
338 showCheck: getData( 'instantCheck' ),
339 checkedQuestions: getData( 'checkedQuestions' ),
340 hintedQuestions: getData( 'hintedQuestions' ),
341 questionsPerPage: getData( 'questionsPerPage' ),
342 };
343 } )
344 )( ( props ) => {
345 const {
346 showCheck,
347 checkedQuestions,
348 hintedQuestions,
349 question,
350 status,
351 type,
352 Button,
353 } = props;
354
355 if ( status !== 'started' ) {
356 return false;
357 }
358
359 const theButton = <Button question={ question } />;
360
361 switch ( type ) {
362 case 'hint':
363
364 if ( ! hintedQuestions ) {
365 return theButton;
366 }
367
368 if ( ! question.hasHint ) {
369 return false;
370 }
371
372 return hintedQuestions.indexOf( question.id ) === -1 && theButton;
373
374 case 'check':
375
376 if ( ! showCheck ) {
377 return false;
378 }
379
380 if ( ! checkedQuestions ) {
381 return theButton;
382 }
383
384 return checkedQuestions.indexOf( question.id ) === -1 && theButton;
385 }
386 } );
387
388 export default compose( [
389 withSelect( ( select ) => {
390 const {
391 getData,
392 getCurrentQuestion,
393 } = select( 'learnpress/quiz' );
394
395 const data = {
396 id: getData( 'id' ),
397 status: getData( 'status' ),
398 questionIds: getData( 'questionIds' ),
399 questionNav: getData( 'questionNav' ),
400 isReviewing: getData( 'reviewQuestions' ) && getData( 'mode' ) === 'reviewing',
401 showReview: getData( 'reviewQuestions' ),
402 showCheck: getData( 'instantCheck' ),
403 checkedQuestions: getData( 'checkedQuestions' ),
404 hintedQuestions: getData( 'hintedQuestions' ),
405 numPages: getData( 'numPages' ),
406 pages: getData( 'pages' ),
407 currentPage: getData( 'currentPage' ),
408 questionsPerPage: getData( 'questionsPerPage' ),
409 pageNumbers: getData( 'pageNumbers' ),
410 keyPressed: getData( 'keyPressed' ),
411 canRetry: getData( 'retakeCount' ) > 0 && getData( 'retaken' ) < getData( 'retakeCount' ),
412 retakeNumber: getData( 'retakeCount' ) > 0 && getData( 'retaken' ) < getData( 'retakeCount' ) ? getData( 'retakeCount' ) - getData( 'retaken' ) : null,
413 message: getData( 'messageResponse' ) || false,
414 success: getData( 'successResponse' ) !== undefined ? getData( 'successResponse' ) : true,
415 requiredPassword: getData( 'requiredPassword' ),
416 allowRetake: getData( 'allowRetake' ),
417 };
418
419 if ( data.questionsPerPage === 1 ) {
420 data.question = getCurrentQuestion( 'object' );
421 }
422
423 if ( lpQuizSettings.checkNorequizenroll === 1 ) {
424 const retakenCurrent = window.localStorage.getItem( 'quiz_off_retaken_' + lpQuizSettings.id );
425
426 if ( getData( 'retakeCount' ) > retakenCurrent ) {
427 data.retakeNumber = getData( 'retakeCount' ) - retakenCurrent;
428 data.canRetry = true;
429 } else {
430 data.canRetry = false;
431 }
432 }
433
434 if ( data.allowRetake ) {
435 data.canRetry = true;
436 }
437
438 return data;
439 } ),
440 withDispatch( ( dispatch, { id } ) => {
441 const {
442 startQuiz,
443 setCurrentQuestion,
444 submitQuiz,
445 setQuizMode,
446 showHint,
447 checkAnswer,
448 setCurrentPage,
449 } = dispatch( 'learnpress/quiz' );
450
451 return {
452 startQuiz,
453 setCurrentQuestion,
454 setQuizMode,
455 setCurrentPage,
456 submitQuiz( id ) {
457 submitQuiz( id );
458 },
459 showHint( id ) {
460 showHint( id );
461 },
462 checkAnswer( id ) {
463 checkAnswer( id );
464 },
465 };
466 } ),
467 ] )( Buttons );
468