@pocketprep/ui-kit 3.0.20 → 3.0.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -279,288 +279,372 @@
279
279
  <div
280
280
  v-for="(choice, index) in choices"
281
281
  :key="choice.key"
282
- ref="choices"
283
- v-dark="isDarkMode"
284
- class="uikit-question__choice-container"
285
- :class="{
286
- 'uikit-question__choice-container--hover': !showAnswers && hoverChoiceKey === choice.key,
287
- 'uikit-question__choice-container--focus': !showAnswers && focusChoiceKey === choice.key,
288
- 'uikit-question__choice-container--selected': !showAnswers
289
- && selectedChoices.includes(choice.key),
290
- 'uikit-question__choice-container--correct': !isMCR && showAnswers && !isUnanswered
291
- && answerKeys.includes(choice.key),
292
- 'uikit-question__choice-container--incorrect': !isMCR && showAnswers
293
- && selectedChoices.includes(choice.key)
294
- && distractorKeys.includes(choice.key),
295
- 'uikit-question__choice-container--big': !isMCR && !globalMetrics && (
296
- showAnswers && !isUnanswered
297
- ? answerKeys.includes(choice.key)
298
- : selectedChoices.includes(choice.key)
299
- ),
300
- }"
301
- @mousedown.prevent
302
- @mouseover="hoverChoiceKey = choice.key"
303
- @mouseleave="hoverChoiceKey = null"
304
- @focusin="focusChoiceKey = choice.key"
305
- @focusout="choiceFocusOut"
306
- @click.stop="selectChoice(choice.key)"
307
- @keydown.enter.stop="selectChoice(choice.key)"
308
- @touchstart="handleTouchStart"
309
- @touchmove="handleTouchMove"
310
- @touchend="handleTouchEnd(choice.key, $event)"
282
+ class="uikit-question__choices-container"
311
283
  >
312
284
  <div
313
- v-if="!reviewMode"
314
- v-breakpoint:questionEl="breakpoints"
285
+ ref="choices"
315
286
  v-dark="isDarkMode"
316
- class="uikit-question__choice-letter"
317
- :class="!isMCR && {
318
- 'uikit-question__choice-letter--selected': selectedChoices.includes(choice.key),
319
- 'uikit-question__choice-letter--correct': showAnswers
287
+ class="uikit-question__choice-container"
288
+ :class="{
289
+ 'uikit-question__choice-container--hover': !showAnswers && hoverChoiceKey === choice.key,
290
+ 'uikit-question__choice-container--focus': !showAnswers && focusChoiceKey === choice.key,
291
+ 'uikit-question__choice-container--selected': !showAnswers
292
+ && selectedChoices.includes(choice.key),
293
+ 'uikit-question__choice-container--correct': !isMCR && showAnswers && !isUnanswered
320
294
  && answerKeys.includes(choice.key),
321
- 'uikit-question__choice-letter--incorrect': showAnswers
295
+ 'uikit-question__choice-container--incorrect': !isMCR && showAnswers
322
296
  && selectedChoices.includes(choice.key)
323
297
  && distractorKeys.includes(choice.key),
324
- 'uikit-question__choice-letter--big': !globalMetrics && (showAnswers
325
- ? answerKeys.includes(choice.key)
326
- : selectedChoices.includes(choice.key)),
327
- }"
328
- >
329
- {{ String.fromCharCode(index + 65) }}
330
- </div>
331
- <div
332
- :ref="`choice-${choice.key}`"
333
- v-dark="isDarkMode"
334
- v-breakpoint:questionEl="breakpoints"
335
- class="uikit-question__choice"
336
- :class="{
337
- 'uikit-question__choice--strike': showAnswers
338
- ? isMCR
339
- ? distractorKeys.includes(choice.key)
340
- : choiceStrikes.includes(choice.key) && !answerKeys.includes(choice.key)
341
- : choiceStrikes.includes(choice.key),
342
- 'uikit-question__choice--big': !isMCR && !globalMetrics && (
298
+ 'uikit-question__choice-container--big': !isMCR && !globalMetrics && (
343
299
  showAnswers && !isUnanswered
344
300
  ? answerKeys.includes(choice.key)
345
301
  : selectedChoices.includes(choice.key)
346
302
  ),
347
- 'uikit-question__choice--mcr': isMCR,
348
- 'uikit-question__choice--selected': !showAnswers && selectedChoices.includes(choice.key),
349
- 'uikit-question__choice--distractor': showAnswers
350
- && distractorKeys.includes(choice.key),
351
- 'uikit-question__choice--show-stats': globalMetrics,
352
- 'uikit-question__choice--review-mode': reviewMode,
353
303
  }"
304
+ @mousedown.prevent
305
+ @mouseover="hoverChoiceKey = choice.key"
306
+ @mouseleave="hoverChoiceKey = null"
307
+ @focusin="focusChoiceKey = choice.key"
308
+ @focusout="choiceFocusOut"
309
+ @click.stop="selectChoice(choice.key)"
310
+ @keydown.enter.stop="selectChoice(choice.key)"
311
+ @touchstart="handleTouchStart"
312
+ @touchmove="handleTouchMove"
313
+ @touchend="handleTouchEnd(choice.key, $event)"
354
314
  >
355
315
  <div
356
- v-if="isMCR"
316
+ v-if="!reviewMode"
317
+ v-breakpoint:questionEl="breakpoints"
357
318
  v-dark="isDarkMode"
358
- class="uikit-question__mcr-checkbox"
359
- :class="{
360
- 'uikit-question__mcr-checkbox--selected': selectedChoices.includes(choice.key),
361
- 'uikit-question__mcr-checkbox--answer': showAnswers
319
+ class="uikit-question__choice-letter"
320
+ :class="!isMCR && {
321
+ 'uikit-question__choice-letter--selected': selectedChoices.includes(choice.key),
322
+ 'uikit-question__choice-letter--correct': showAnswers
362
323
  && answerKeys.includes(choice.key),
363
- 'uikit-question__mcr-checkbox--distractor': showAnswers
324
+ 'uikit-question__choice-letter--incorrect': showAnswers
325
+ && selectedChoices.includes(choice.key)
364
326
  && distractorKeys.includes(choice.key),
365
- 'uikit-question__mcr-checkbox--strike': !showAnswers
366
- && choiceStrikes.includes(choice.key),
327
+ 'uikit-question__choice-letter--big': !globalMetrics && (showAnswers
328
+ ? answerKeys.includes(choice.key)
329
+ : selectedChoices.includes(choice.key)),
367
330
  }"
368
331
  >
369
- <Icon
370
- v-if="selectedChoices.includes(choice.key) || (
371
- showAnswers && answerKeys.includes(choice.key)
372
- )"
373
- class="uikit-question__mcr-check"
374
- type="check"
375
- />
332
+ {{ String.fromCharCode(index + 65) }}
376
333
  </div>
377
334
  <div
378
- class="uikit-question__choice-text"
379
- :tabindex="showAnswers ? -1 : 0"
380
- :role="isMCR
381
- ? 'checkbox'
382
- : 'radio'
383
- "
384
- :aria-checked="selectedChoices.includes(choice.key) ? 'true' : 'false'"
385
- :aria-label="`${
386
- showAnswers
387
- ? answerKeys.includes(choice.key)
388
- ? 'Correct Answer, '
389
- : 'Incorrect Answer, '
390
- : ''
391
- }${ stripText(choice.text) }`"
392
- v-html="choice.text"
393
- />
394
- <PocketButton
395
- v-if="!isMCR && showAnswers && answerKeys.includes(choice.key)"
396
- v-breakpoint:questionEl="breakpoints"
397
- type="tertiary-small"
398
- class="uikit-question__toggle-explanation"
399
- :class="{ 'uikit-question__toggle-explanation--review-mode': reviewMode }"
400
- :is-dark-mode="isDarkMode"
401
- :aria-expanded="showExplanation ? 'true' : 'false'"
402
- @click.stop="toggleExplanation"
403
- @mousedown.prevent
404
- >
405
- <span
406
- ref="uikit-question__toggle-explanation-text"
407
- class="uikit-question__toggle-explanation-text"
408
- tabindex="-1"
409
- >{{ showExplanation ? 'Hide' : 'Show' }} Explanation</span>
410
- <Icon
411
- v-breakpoint:questionEl="breakpoints"
412
- class="uikit-question__toggle-explanation-icon"
413
- :class="{
414
- 'uikit-question__toggle-explanation-icon--up': showExplanation,
415
- }"
416
- type="accordionArrow"
417
- />
418
- </PocketButton>
419
- <div
420
- v-if="!isMCR && showAnswers && answerKeys.includes(choice.key) && showExplanation"
335
+ :ref="`choice-${choice.key}`"
336
+ v-dark="isDarkMode"
421
337
  v-breakpoint:questionEl="breakpoints"
422
- class="uikit-question__dropdown-explanation"
338
+ class="uikit-question__choice"
423
339
  :class="{
424
- 'uikit-question__dropdown-explanation--show-stats': globalMetrics
340
+ 'uikit-question__choice--strike': showAnswers
341
+ ? isMCR
342
+ ? distractorKeys.includes(choice.key)
343
+ : choiceStrikes.includes(choice.key) && !answerKeys.includes(choice.key)
344
+ : choiceStrikes.includes(choice.key),
345
+ 'uikit-question__choice--big': !isMCR && !globalMetrics && (
346
+ showAnswers && !isUnanswered
347
+ ? answerKeys.includes(choice.key)
348
+ : selectedChoices.includes(choice.key)
349
+ ),
350
+ 'uikit-question__choice--mcr': isMCR,
351
+ 'uikit-question__choice--selected': !showAnswers &&
352
+ selectedChoices.includes(choice.key),
353
+ 'uikit-question__choice--distractor': showAnswers
354
+ && distractorKeys.includes(choice.key),
355
+ 'uikit-question__choice--show-stats': globalMetrics,
356
+ 'uikit-question__choice--review-mode': reviewMode,
425
357
  }"
426
358
  >
427
359
  <div
360
+ v-if="isMCR"
428
361
  v-dark="isDarkMode"
429
- class="uikit-question__dropdown-explanation-text"
430
- v-html="question.explanation"
431
- />
432
- <img
433
- v-if="explanationImageUrl"
434
- v-dark="isDarkMode"
435
- class="uikit-question__dropdown-explanation-image"
436
- :src="explanationImageUrl"
437
- :alt="`${explanationImageAlt}. Extended image description below.`"
362
+ class="uikit-question__mcr-checkbox"
363
+ :class="{
364
+ 'uikit-question__mcr-checkbox--selected': selectedChoices.includes(choice.key),
365
+ 'uikit-question__mcr-checkbox--answer': showAnswers
366
+ && answerKeys.includes(choice.key),
367
+ 'uikit-question__mcr-checkbox--distractor': showAnswers
368
+ && distractorKeys.includes(choice.key),
369
+ 'uikit-question__mcr-checkbox--strike': !showAnswers
370
+ && choiceStrikes.includes(choice.key),
371
+ }"
438
372
  >
373
+ <Icon
374
+ v-if="selectedChoices.includes(choice.key) || (
375
+ showAnswers && answerKeys.includes(choice.key)
376
+ )"
377
+ class="uikit-question__mcr-check"
378
+ type="check"
379
+ />
380
+ </div>
381
+ <div
382
+ class="uikit-question__choice-text"
383
+ :tabindex="showAnswers ? -1 : 0"
384
+ :role="isMCR
385
+ ? 'checkbox'
386
+ : 'radio'
387
+ "
388
+ :aria-checked="selectedChoices.includes(choice.key) ? 'true' : 'false'"
389
+ :aria-label="`${
390
+ showAnswers
391
+ ? answerKeys.includes(choice.key)
392
+ ? 'Correct Answer, '
393
+ : 'Incorrect Answer, '
394
+ : ''
395
+ }${ stripText(choice.text) }`"
396
+ v-html="choice.text"
397
+ />
439
398
  <PocketButton
440
- v-if="explanationImageLongAlt"
399
+ v-if="!isMCR && showAnswers && answerKeys.includes(choice.key)"
441
400
  v-breakpoint:questionEl="breakpoints"
442
401
  type="tertiary-small"
443
- class="uikit-question__toggle-dropdown-explanation-img-description"
444
- :class="{
445
- 'uikit-question__toggle-dropdown-explanation-img-description--open':
446
- showExplanationImageLongAlt,
447
- 'uikit-question__toggle-dropdown-explanation-img-description--no-reference':
448
- !question.reference || hideReferences,
449
- }"
402
+ class="uikit-question__toggle-explanation"
403
+ :class="{ 'uikit-question__toggle-explanation--review-mode': reviewMode }"
450
404
  :is-dark-mode="isDarkMode"
451
405
  :aria-expanded="showExplanationImageLongAlt ? 'true' : 'false'"
452
406
  @click.stop="toggleExplanationImageLongAlt"
453
407
  @mousedown.prevent
454
408
  >
455
- <span class="uikit-question__toggle-dropdown-explanation-img-description-text">
456
- Image Description
457
- </span>
409
+ <span
410
+ ref="uikit-question__toggle-explanation-text"
411
+ class="uikit-question__toggle-explanation-text"
412
+ tabindex="-1"
413
+ >{{ showExplanation ? 'Hide' : 'Show' }} Explanation</span>
458
414
  <Icon
459
- class="uikit-question__toggle-dropdown-explanation-img-description-icon"
415
+ v-breakpoint:questionEl="breakpoints"
416
+ class="uikit-question__toggle-explanation-icon"
460
417
  :class="{
461
- 'uikit-question__toggle-dropdown-explanation-img-description-icon--up':
462
- showExplanationImageLongAlt,
418
+ 'uikit-question__toggle-explanation-icon--up': showExplanation,
463
419
  }"
464
420
  type="accordionArrow"
465
421
  />
466
422
  </PocketButton>
467
423
  <div
468
- v-if="showExplanationImageLongAlt"
469
- ref="uikit-question__dropdown-explanation-img-description"
470
- v-dark="isDarkMode"
424
+ v-if="!isMCR && showAnswers && answerKeys.includes(choice.key) && showExplanation"
471
425
  v-breakpoint:questionEl="breakpoints"
472
- class="uikit-question__dropdown-explanation-img-description"
473
- tabindex="-1"
474
- v-html="explanationImageLongAlt"
475
- />
426
+ class="uikit-question__dropdown-explanation"
427
+ :class="{
428
+ 'uikit-question__dropdown-explanation--show-stats': globalMetrics
429
+ }"
430
+ >
431
+ <div
432
+ v-dark="isDarkMode"
433
+ class="uikit-question__dropdown-explanation-text"
434
+ v-html="question.explanation"
435
+ />
436
+ <img
437
+ v-if="explanationImageUrl"
438
+ v-dark="isDarkMode"
439
+ class="uikit-question__dropdown-explanation-image"
440
+ :src="explanationImageUrl"
441
+ :alt="`${explanationImageAlt}. Extended image description below.`"
442
+ >
443
+ <PocketButton
444
+ v-if="explanationImageLongAlt"
445
+ v-breakpoint:questionEl="breakpoints"
446
+ type="tertiary-small"
447
+ class="uikit-question__toggle-dropdown-explanation-img-description"
448
+ :class="{
449
+ 'uikit-question__toggle-dropdown-explanation-img-description--open':
450
+ showExplanationImageLongAlt,
451
+ 'uikit-question__toggle-dropdown-explanation-img-description--no-reference':
452
+ !question.reference || hideReferences,
453
+ }"
454
+ :is-dark-mode="isDarkMode"
455
+ :aria-expanded="showExplanationImageLongAlt ? 'true' : 'false'"
456
+ @click.stop="toggleExplanationImageLongAlt"
457
+ @mousedown.prevent
458
+ >
459
+ <span class="uikit-question__toggle-dropdown-explanation-img-description-text">
460
+ Image Description
461
+ </span>
462
+ <Icon
463
+ class="uikit-question__toggle-dropdown-explanation-img-description-icon"
464
+ :class="{
465
+ 'uikit-question__toggle-dropdown-explanation-img-description-icon--up':
466
+ showExplanationImageLongAlt,
467
+ }"
468
+ type="accordionArrow"
469
+ />
470
+ </PocketButton>
471
+ <div
472
+ v-if="showExplanationImageLongAlt"
473
+ ref="uikit-question__dropdown-explanation-img-description"
474
+ v-dark="isDarkMode"
475
+ v-breakpoint:questionEl="breakpoints"
476
+ class="uikit-question__dropdown-explanation-img-description"
477
+ tabindex="-1"
478
+ v-html="explanationImageLongAlt"
479
+ />
480
+ <div
481
+ v-if="question.reference && !hideReferences"
482
+ v-dark="isDarkMode"
483
+ class="uikit-question__dropdown-reference"
484
+ >
485
+ <span class="uikit-question__dropdown-reference-label">Reference: </span>
486
+ <div v-html="question.reference" />
487
+ </div>
488
+ </div>
489
+ </div>
490
+ <template v-if="!globalMetrics">
476
491
  <div
477
- v-if="question.reference && !hideReferences"
492
+ v-if="!showAnswers"
493
+ v-breakpoint:questionEl="breakpoints"
478
494
  v-dark="isDarkMode"
479
- class="uikit-question__dropdown-reference"
495
+ :tabindex="showAnswers ? -1 : 0"
496
+ class="uikit-question__strikethrough"
497
+ aria-label="Strikethrough"
498
+ role="switch"
499
+ :aria-checked="choiceStrikes.includes(choice.key) ? 'true' : 'false'"
500
+ :class="{
501
+ 'uikit-question__strikethrough--visible': !showAnswers
502
+ && [ hoverChoiceKey, focusChoiceKey ].includes(choice.key),
503
+ 'uikit-question__strikethrough--active': choiceStrikes.includes(choice.key),
504
+ }"
505
+ @mousedown.prevent
506
+ @click.stop="clickChoiceStrike(choice.key)"
507
+ @keydown.enter.stop="clickChoiceStrike(choice.key)"
480
508
  >
481
- <span class="uikit-question__dropdown-reference-label">Reference: </span>
482
- <div v-html="question.reference" />
509
+ <Icon type="strike" />
483
510
  </div>
484
- </div>
485
- </div>
486
- <template v-if="!globalMetrics">
487
- <div
488
- v-if="!showAnswers"
489
- v-breakpoint:questionEl="breakpoints"
490
- v-dark="isDarkMode"
491
- :tabindex="showAnswers ? -1 : 0"
492
- class="uikit-question__strikethrough"
493
- aria-label="Strikethrough"
494
- role="switch"
495
- :aria-checked="choiceStrikes.includes(choice.key) ? 'true' : 'false'"
496
- :class="{
497
- 'uikit-question__strikethrough--visible': !showAnswers
498
- && [ hoverChoiceKey, focusChoiceKey ].includes(choice.key),
499
- 'uikit-question__strikethrough--active': choiceStrikes.includes(choice.key),
500
- }"
501
- @mousedown.prevent
502
- @click.stop="clickChoiceStrike(choice.key)"
503
- @keydown.enter.stop="clickChoiceStrike(choice.key)"
504
- >
505
- <Icon type="strike" />
506
- </div>
507
- <Icon
508
- v-if="!isMCR
509
- && showAnswers
510
- && answerKeys.includes(choice.key)
511
- && (isCorrect || isUnanswered)
512
- "
513
- v-dark="isDarkMode"
514
- type="correct"
515
- class="uikit-question__correct-icon"
516
- :class="{
517
- 'uikit-question__correct-icon--review-mode': reviewMode,
518
- }"
519
- />
520
- <Icon
521
- v-if="showAnswers && (
522
- (
523
- selectedChoices.includes(choice.key)
524
- && distractorKeys.includes(choice.key)
525
- ) || (
526
- isMCR
527
- && !selectedChoices.includes(choice.key)
511
+ <Icon
512
+ v-if="!isMCR
513
+ && showAnswers
528
514
  && answerKeys.includes(choice.key)
529
- )
530
- )"
531
- v-dark="isDarkMode"
532
- type="incorrect"
533
- class="uikit-question__incorrect-icon"
534
- :class="{
535
- 'uikit-question__incorrect-icon--mcr': isMCR,
536
- }"
537
- />
538
- </template>
539
- <template v-else>
540
- <div
541
- v-dark="isDarkMode"
542
- class="uikit-question__choice-stats-pct"
543
- >
544
- {{ choiceScores[choice.key] }} %
545
- </div>
546
- <div v-dark="isDarkMode" class="uikit-question__choice-stats-bar">
547
- <div
515
+ && (isCorrect || isUnanswered)
516
+ "
548
517
  v-dark="isDarkMode"
549
- class="uikit-question__choice-stats-bar-fill"
518
+ type="correct"
519
+ class="uikit-question__correct-icon"
550
520
  :class="{
551
- 'uikit-question__choice-stats-bar-fill--correct': showAnswers
552
- && answerKeys.includes(choice.key),
553
- 'uikit-question__choice-stats-bar-fill--incorrect': showAnswers
554
- && distractorKeys.includes(choice.key)
555
- && selectedChoices.includes(choice.key),
521
+ 'uikit-question__correct-icon--review-mode': reviewMode,
556
522
  }"
557
- :style="{
558
- 'width': `${(choiceScores[choice.key]) || 0}%`
523
+ />
524
+ <Icon
525
+ v-if="showAnswers && (
526
+ (
527
+ selectedChoices.includes(choice.key)
528
+ && distractorKeys.includes(choice.key)
529
+ ) || (
530
+ isMCR
531
+ && !selectedChoices.includes(choice.key)
532
+ && answerKeys.includes(choice.key)
533
+ )
534
+ )"
535
+ v-dark="isDarkMode"
536
+ type="incorrect"
537
+ class="uikit-question__incorrect-icon"
538
+ :class="{
539
+ 'uikit-question__incorrect-icon--mcr': isMCR,
559
540
  }"
560
541
  />
561
- </div>
562
- </template>
563
- </div>
542
+ </template>
543
+ <template v-else>
544
+ <div
545
+ v-dark="isDarkMode"
546
+ class="uikit-question__choice-stats-pct"
547
+ >
548
+ {{ choiceScores[choice.key] }} %
549
+ </div>
550
+ <div v-dark="isDarkMode" class="uikit-question__choice-stats-bar">
551
+ <div
552
+ v-dark="isDarkMode"
553
+ class="uikit-question__choice-stats-bar-fill"
554
+ :class="{
555
+ 'uikit-question__choice-stats-bar-fill--correct': showAnswers
556
+ && answerKeys.includes(choice.key),
557
+ 'uikit-question__choice-stats-bar-fill--incorrect': showAnswers
558
+ && distractorKeys.includes(choice.key)
559
+ && selectedChoices.includes(choice.key),
560
+ }"
561
+ :style="{
562
+ 'width': `${(choiceScores[choice.key]) || 0}%`
563
+ }"
564
+ />
565
+ </div>
566
+ </template>
567
+ </div>
568
+ <div
569
+ v-if="showNames && Object.entries(showNames).length > 0"
570
+ >
571
+ <Table
572
+ :key="`uikit-question__view-names-table--${choice.key}`"
573
+ class="uikit-question__view-names-table"
574
+ :show-header="false"
575
+ :rows="mappedNameRows(choice.key) || []"
576
+ :columns="showNamesColumns"
577
+ :table-column-styles="{
578
+ maxWidth: '146px',
579
+ maxHeight: '54px',
580
+ minHeight: '50px',
581
+ }"
582
+ :table-cell-styles="{
583
+ display: 'flex',
584
+ position: 'relative',
585
+ border: 'none',
586
+ }"
587
+ :table-row-styles="{
588
+ border: 'none',
589
+ padding: '0px',
590
+ }"
591
+ >
592
+ <template #tableColumnLabels>
593
+ <div />
594
+ </template>
595
+ <template #tableCellValue="{ row, column }">
596
+ <template v-if="(column.propName === 'nameOne')">
597
+ <Icon
598
+ v-if="row.isFlaggedByNameOne"
599
+ type="flagContent"
600
+ class="uikit-question__flag-icon"
601
+ />
602
+ <div
603
+ v-else
604
+ class="uikit-question__icon-space"
605
+ />
606
+ <OverflowTooltip
607
+ class="uikit-question__view-names-name"
608
+ >
609
+ {{ row.nameOne }}
610
+ </OverflowTooltip>
611
+ </template>
612
+ <template v-if="(column.propName === 'nameTwo' && row.nameTwo)">
613
+ <Icon
614
+ v-if="row.isFlaggedByNameTwo"
615
+ type="flagContent"
616
+ class="uikit-question__flag-icon"
617
+ />
618
+ <div
619
+ v-else
620
+ class="uikit-question__icon-space"
621
+ />
622
+ <OverflowTooltip>
623
+ <div class="uikit-question__view-names-name">
624
+ {{ row.nameTwo }}
625
+ </div>
626
+ </OverflowTooltip>
627
+ </template>
628
+ <template v-if="(column.propName === 'nameThree' && row.nameThree)">
629
+ <Icon
630
+ v-if="row.isFlaggedByNameThree"
631
+ type="flagContent"
632
+ class="uikit-question__flag-icon"
633
+ />
634
+ <div
635
+ v-else
636
+ class="uikit-question__icon-space"
637
+ />
638
+ <OverflowTooltip>
639
+ <div class="uikit-question__view-names-name">
640
+ {{ row.nameThree }}
641
+ </div>
642
+ </OverflowTooltip>
643
+ </template>
644
+ </template>
645
+ </Table>
646
+ </div>
647
+ </div>
564
648
  </div>
565
649
  <div
566
650
  v-if="isMCR && showAnswers && !showPaywall"
@@ -671,27 +755,29 @@
671
755
  class="uikit-question__summary-incorrect-icon"
672
756
  />
673
757
  </div>
674
- <div
675
- v-if="globalMetrics"
676
- class="uikit-question__stats-summary"
677
- >
678
- <div v-dark="isDarkMode" class="uikit-question__stats-summary-total">
679
- <div class="uikit-question__stats-summary-value">
680
- {{ choiceScores.totalAnswered }}
681
- </div>
682
- <div v-dark="isDarkMode" class="uikit-question__stats-summary-label">
683
- Studiers Answered
684
- </div>
685
- </div>
686
- <div v-dark="isDarkMode" class="uikit-question__stats-summary-correct">
687
- <div class="uikit-question__stats-summary-value">
688
- {{ Math.round((choiceScores.answeredCorrectly / choiceScores.totalAnswered) * 100) }}%
758
+ <slot name="metricsTiles">
759
+ <div
760
+ v-if="globalMetrics"
761
+ class="uikit-question__stats-summary"
762
+ >
763
+ <div v-dark="isDarkMode" class="uikit-question__stats-summary-total">
764
+ <div class="uikit-question__stats-summary-value">
765
+ {{ choiceScores.totalAnswered }}
766
+ </div>
767
+ <div v-dark="isDarkMode" class="uikit-question__stats-summary-label">
768
+ Studiers Answered
769
+ </div>
689
770
  </div>
690
- <div v-dark="isDarkMode" class="uikit-question__stats-summary-label">
691
- Answered Correctly
771
+ <div v-dark="isDarkMode" class="uikit-question__stats-summary-correct">
772
+ <div class="uikit-question__stats-summary-value">
773
+ {{ Math.round((choiceScores.answeredCorrectly / choiceScores.totalAnswered) * 100) }}%
774
+ </div>
775
+ <div v-dark="isDarkMode" class="uikit-question__stats-summary-label">
776
+ Answered Correctly
777
+ </div>
692
778
  </div>
693
779
  </div>
694
- </div>
780
+ </slot>
695
781
  <div
696
782
  v-if="!reviewMode"
697
783
  v-breakpoint:questionEl="breakpoints"
@@ -885,7 +971,7 @@
885
971
  <Icon type="close" />
886
972
  </div>
887
973
  </div>
888
- </div>
974
+ </div>
889
975
  </div>
890
976
  </template>
891
977
 
@@ -893,6 +979,9 @@
893
979
  import { Component, Vue, Prop, Watch, Emit } from 'vue-facing-decorator'
894
980
  import PocketButton from '../Buttons/Button.vue'
895
981
  import Icon from '../Icons/Icon.vue'
982
+ import type { ITableColumn, ITableSortSettings } from '../Tables/table'
983
+ import Table from '../Tables/Table.vue'
984
+ import OverflowTooltip from '../Tooltips/OverflowTooltip.vue'
896
985
  import type { Study } from '@pocketprep/types'
897
986
  import { breakpoint, dark } from '../../directives'
898
987
  import { studyModes } from '../../utils'
@@ -907,11 +996,30 @@ type TChoiceScores = Partial<Record<TChoiceKey, number>> & {
907
996
  }
908
997
  type TQuizMode = 'qotd' | 'quick10' | 'timed' | 'weakest' | 'missed' | 'custom'
909
998
  type Ref = HTMLElement | null
999
+ type TNamesRow = {
1000
+ id: string
1001
+ nameOne: string
1002
+ isFlaggedByNameOne: boolean
1003
+ nameTwo?: string
1004
+ isFlaggedByNameTwo?: boolean
1005
+ nameThree?: string
1006
+ isFlaggedByNameThree?: boolean
1007
+ }
1008
+
1009
+ type TViewNames = {
1010
+ [ key: string ]: {
1011
+ id: string
1012
+ name: string
1013
+ isFlaggedByStudent: boolean
1014
+ }[]
1015
+ }
910
1016
 
911
1017
  @Component({
912
1018
  components: {
913
1019
  PocketButton,
914
1020
  Icon,
1021
+ Table,
1022
+ OverflowTooltip,
915
1023
  },
916
1024
  directives: {
917
1025
  breakpoint,
@@ -931,6 +1039,7 @@ export default class Question extends Vue {
931
1039
  @Prop({ default: false }) reviewMode!: boolean
932
1040
  @Prop({ default: null }) previousChoices!: TChoiceKey[] | null
933
1041
  @Prop({ default: null }) globalMetrics!: Study.Class.GlobalQuestionMetricJSON | null
1042
+ @Prop({ default: null }) showNames!: TViewNames | null
934
1043
  @Prop({ default: true }) allowKeyboardShortcuts!: boolean
935
1044
  @Prop({ default: null }) containerEl!: Element | null
936
1045
  @Prop({ default: false }) isDarkMode!: boolean
@@ -957,6 +1066,21 @@ export default class Question extends Vue {
957
1066
  y: number | null
958
1067
  } = { x: null, y: null }
959
1068
 
1069
+ sortSettings: ITableSortSettings | null = null
1070
+ showNamesColumns: ITableColumn[] = [{
1071
+ name: '',
1072
+ propName: 'nameOne',
1073
+ isSortDisabled: true,
1074
+ }, {
1075
+ name: '',
1076
+ propName: 'nameTwo',
1077
+ isSortDisabled: true,
1078
+ }, {
1079
+ name: '',
1080
+ propName: 'nameThree',
1081
+ isSortDisabled: true,
1082
+ }]
1083
+
960
1084
  get paywallImages () {
961
1085
  return {
962
1086
  light: PaywallImageLight,
@@ -1120,7 +1244,8 @@ export default class Question extends Vue {
1120
1244
  const userAnswerCount = this.showAnswers && this.selectedChoices.includes(key) && !this.reviewMode ? 1 : 0
1121
1245
  const choiceAnswerCount = globalAnswerCount + userAnswerCount
1122
1246
  const answerPct = Math.round((choiceAnswerCount / totalChoicesCount) * 100)
1123
- scores[key] = answerPct
1247
+ // In case we have NaN here when nobody answered the question and nobody got it right
1248
+ scores[key] = answerPct || 0
1124
1249
  })
1125
1250
 
1126
1251
  return scores
@@ -1155,6 +1280,10 @@ export default class Question extends Vue {
1155
1280
  contextEl?.focus()
1156
1281
  }, 0)
1157
1282
  }
1283
+ this.sortSettings = {
1284
+ column: this.showNamesColumns[0] || null,
1285
+ direction: 1,
1286
+ }
1158
1287
  }
1159
1288
 
1160
1289
  beforeUnmount () {
@@ -1489,9 +1618,50 @@ export default class Question extends Vue {
1489
1618
  }
1490
1619
  }
1491
1620
 
1492
- @Emit('selectedChoices')
1493
- emitSelectedChoices (selectedChoices: Study.Cloud.IQuizAnswer) {
1494
- return selectedChoices
1621
+ mappedNameRows (choiceKey: string) {
1622
+ /*
1623
+ There is a specific order in which we have to fill the rows in the table for visible names.
1624
+ Here are the rules for filling the names in:
1625
+
1626
+ 1. The first two names go in the first column
1627
+ 2. The third and fourth names go in the second column
1628
+ 3. Any subsequent names fill out the first two rows
1629
+ 4. Any additional names after those fill out the last row
1630
+ 5. Alphabetical by col
1631
+ 6. Names truncate when they don't fit the width of the table cell
1632
+ */
1633
+ const rows: TNamesRow[] = []
1634
+ const students = this.showNames && this.showNames[choiceKey] || []
1635
+ if (students.length) {
1636
+ // Row length is dynamic depending on how many students we have
1637
+ const rowLength = students.length < 3 ? 1 :
1638
+ students.length >= 3 && students.length < 5 ? 2 :
1639
+ 3
1640
+ for (let i = 0; i < students.length; i += rowLength) {
1641
+ const row = students.slice(i, i + rowLength).reduce((acc, student) => {
1642
+ if (!acc.id) {
1643
+ // Need a unique ID for the row
1644
+ acc.id = student.id
1645
+ }
1646
+ if (!acc.nameOne && !acc.isFlaggedByNameOne) {
1647
+ // Does our row have a nameOne filled in?
1648
+ acc.nameOne = student.name
1649
+ acc.isFlaggedByNameOne = student.isFlaggedByStudent
1650
+ } else if (!acc.nameTwo && !acc.isFlaggedByNameTwo) {
1651
+ // Does our row have a nameTwo filled in?
1652
+ acc.nameTwo = student.name
1653
+ acc.isFlaggedByNameTwo = student.isFlaggedByStudent
1654
+ } else if (!acc.nameThree && !acc.isFlaggedByNameThree) {
1655
+ // Does our row have a nameThree filled in?
1656
+ acc.nameThree = student.name
1657
+ acc.isFlaggedByNameThree = student.isFlaggedByStudent
1658
+ }
1659
+ return acc
1660
+ }, {} as TNamesRow)
1661
+ rows.push(row)
1662
+ }
1663
+ }
1664
+ return rows
1495
1665
  }
1496
1666
 
1497
1667
  @Watch('reviewMode')
@@ -1508,6 +1678,11 @@ export default class Question extends Vue {
1508
1678
  this.updateSelectedChoices(choices)
1509
1679
  }
1510
1680
 
1681
+ @Emit('selectedChoices')
1682
+ emitSelectedChoices (selectedChoices: Study.Cloud.IQuizAnswer) {
1683
+ return selectedChoices
1684
+ }
1685
+
1511
1686
  @Watch('selectedChoices', { deep: true })
1512
1687
  selectedChoicesChanged () {
1513
1688
  this.emitSelectedChoices({
@@ -2371,19 +2546,23 @@ export default class Question extends Vue {
2371
2546
  }
2372
2547
  }
2373
2548
 
2549
+ &__choices-container {
2550
+ width: 100%;
2551
+
2552
+ &:not(:last-child) {
2553
+ margin-bottom: 9px;
2554
+ }
2555
+ }
2556
+
2374
2557
  &__choice-container {
2375
- position: relative;
2376
2558
  display: flex;
2377
2559
  align-items: center;
2378
2560
  width: 100%;
2379
- outline: none;
2380
- transition: 0.1s width ease;
2381
2561
  border-radius: 6px;
2382
2562
  cursor: default;
2383
-
2384
- &:not(:last-child) {
2385
- margin-bottom: 9px;
2386
- }
2563
+ position: relative;
2564
+ outline: none;
2565
+ transition: 0.1s width ease;
2387
2566
 
2388
2567
  &::after {
2389
2568
  content: '';
@@ -2500,6 +2679,33 @@ export default class Question extends Vue {
2500
2679
  }
2501
2680
  }
2502
2681
 
2682
+ &__view-names-table {
2683
+ background-color: $gray-background;
2684
+ min-height: 50px;
2685
+ padding: 15px 0 15px 14px;
2686
+ }
2687
+
2688
+ &__flag-icon {
2689
+ padding: 3px 0 0 0;
2690
+ margin: 0 4px 0 3px;
2691
+ color: $steel;
2692
+ }
2693
+
2694
+ &__icon-space {
2695
+ min-width: 17px;
2696
+ height: 0;
2697
+ }
2698
+
2699
+ &__view-names-name {
2700
+ color: $ash;
2701
+ font-size: 13px;
2702
+ line-height: 18px;
2703
+ text-overflow: ellipsis;
2704
+ overflow: hidden;
2705
+ white-space: nowrap;
2706
+ max-width: 129px;
2707
+ }
2708
+
2503
2709
  &__choice-letter {
2504
2710
  position: absolute;
2505
2711
  left: -26px;
@@ -3165,6 +3371,7 @@ export default class Question extends Vue {
3165
3371
  color: $ash;
3166
3372
  font-size: 13px;
3167
3373
  line-height: 16px;
3374
+ text-align: center;
3168
3375
 
3169
3376
  &--dark {
3170
3377
  color: $white;