@@ -41,6 +41,8 @@ import { AddonModQuizQuestionCardComponent } from '../../components/question-car
41
41
import { AddonModQuizAttemptInfoComponent } from '../../components/attempt-info/attempt-info' ;
42
42
import { CoreSharedModule } from '@/core/shared.module' ;
43
43
import { CoreQuestionComponent } from '@features/question/components/question/question' ;
44
+ import { CoreWait } from '@singletons/wait' ;
45
+ import { CoreLoadings } from '@services/overlays/loadings' ;
44
46
45
47
/**
46
48
* Page that allows reviewing a quiz attempt.
@@ -60,6 +62,8 @@ export default class AddonModQuizReviewPage implements OnInit {
60
62
61
63
@ViewChild ( IonContent ) content ?: IonContent ;
62
64
65
+ protected static readonly QUESTIONS_PER_LOAD_WHEN_SHOW_ALL = 10 ;
66
+
63
67
attempt ?: AddonModQuizAttemptWSData ; // The attempt being reviewed.
64
68
component = ADDON_MOD_QUIZ_COMPONENT_LEGACY ; // Component to link the files to.
65
69
showAll = false ; // Whether to view all questions in the same page.
@@ -78,6 +82,8 @@ export default class AddonModQuizReviewPage implements OnInit {
78
82
quiz ?: AddonModQuizQuizWSData ; // The quiz the attempt belongs to.
79
83
courseId ! : number ; // The course ID the quiz belongs to.
80
84
cmId ! : number ; // Course module id the attempt belongs to.
85
+ canLoadMore = false ;
86
+ allQuestions : CoreQuestionQuestionForView [ ] = [ ] ; // When using infinite loading, this will contain all the questions.
81
87
82
88
protected attemptId ! : number ; // The attempt being reviewed.
83
89
protected currentPage ! : number ; // The current page being reviewed.
@@ -123,12 +129,12 @@ export default class AddonModQuizReviewPage implements OnInit {
123
129
* @param slot Slot of the question to scroll to.
124
130
*/
125
131
async changePage ( page : number , slot ?: number ) : Promise < void > {
126
- if ( slot !== undefined && ( this . attempt ?. currentpage == - 1 || page == this . currentPage ) ) {
132
+ if ( slot !== undefined && ( this . attempt ?. currentpage === - 1 || page = == this . currentPage ) ) {
127
133
// Scrol to a certain question in the current page.
128
134
this . scrollToQuestion ( slot ) ;
129
135
130
136
return ;
131
- } else if ( page == this . currentPage ) {
137
+ } else if ( page === this . currentPage ) {
132
138
// If the user is navigating to the current page and no question specified, we do nothing.
133
139
return ;
134
140
}
@@ -195,9 +201,15 @@ export default class AddonModQuizReviewPage implements OnInit {
195
201
this . additionalData = data . additionaldata ;
196
202
this . currentPage = page ;
197
203
198
- this . questions = data . questions ;
199
- this . nextPage = page + 1 ;
200
- this . previousPage = page - 1 ;
204
+ if ( page === - 1 ) {
205
+ this . allQuestions = data . questions ;
206
+ this . questions = data . questions . slice ( 0 , AddonModQuizReviewPage . QUESTIONS_PER_LOAD_WHEN_SHOW_ALL ) ;
207
+ this . canLoadMore = this . allQuestions . length > this . questions . length ;
208
+ } else {
209
+ this . questions = data . questions ;
210
+ this . nextPage = page + 1 ;
211
+ this . previousPage = page - 1 ;
212
+ }
201
213
202
214
this . questions . forEach ( ( question ) => {
203
215
// Get the readable mark for each question.
@@ -208,6 +220,21 @@ export default class AddonModQuizReviewPage implements OnInit {
208
220
} ) ;
209
221
}
210
222
223
+ /**
224
+ * Show more questions (only used when showing all the questions at the same time).
225
+ *
226
+ * @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading.
227
+ */
228
+ loadMore ( infiniteComplete ?: ( ) => void ) : void {
229
+ this . questions = this . questions . concat ( this . allQuestions . slice (
230
+ this . questions . length ,
231
+ this . questions . length + AddonModQuizReviewPage . QUESTIONS_PER_LOAD_WHEN_SHOW_ALL ,
232
+ ) ) ;
233
+ this . canLoadMore = this . allQuestions . length > this . questions . length ;
234
+
235
+ infiniteComplete ?.( ) ;
236
+ }
237
+
211
238
/**
212
239
* Load data to navigate the questions using the navigation modal.
213
240
*/
@@ -253,7 +280,27 @@ export default class AddonModQuizReviewPage implements OnInit {
253
280
*
254
281
* @param slot Slot of the question to scroll to.
255
282
*/
256
- protected scrollToQuestion ( slot : number ) : void {
283
+ protected async scrollToQuestion ( slot : number ) : Promise < void > {
284
+ if ( this . showAll && this . canLoadMore ) {
285
+ // First make sure that the question is visible.
286
+ const pageIndex = this . allQuestions . findIndex ( question => question . slot === slot ) ;
287
+ if ( pageIndex > this . questions . length ) {
288
+ // Not visible, load the needed questions.
289
+ // Show a loading modal because if there are a lot of questions to load it can take a few seconds to render.
290
+ const loading = await CoreLoadings . show ( ) ;
291
+
292
+ const lastQuestionToLoad = Math . ceil ( pageIndex / AddonModQuizReviewPage . QUESTIONS_PER_LOAD_WHEN_SHOW_ALL ) *
293
+ AddonModQuizReviewPage . QUESTIONS_PER_LOAD_WHEN_SHOW_ALL ;
294
+ this . questions = this . questions . concat ( this . allQuestions . slice ( this . questions . length , lastQuestionToLoad ) ) ;
295
+ this . canLoadMore = this . allQuestions . length > this . questions . length ;
296
+
297
+ // Wait some ticks to let the questions render, otherwise the scroll might end up in a wrong position.
298
+ await CoreWait . nextTicks ( 5 ) ;
299
+ await loading . dismiss ( ) ;
300
+ await CoreWait . nextTick ( ) ; // For some reason scrolling doesn't work right after dismiss, wait a tick.
301
+ }
302
+ }
303
+
257
304
CoreDom . scrollToElement (
258
305
this . elementRef . nativeElement ,
259
306
`#addon-mod_quiz-question-${ slot } ` ,
0 commit comments