@pocketprep/ui-kit 3.4.90 → 3.5.1
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.
- package/README.md +2 -2
- package/dist/@pocketprep/ui-kit.css +1 -0
- package/dist/@pocketprep/ui-kit.js +16490 -18228
- package/dist/@pocketprep/ui-kit.js.map +1 -1
- package/dist/@pocketprep/ui-kit.umd.cjs +11 -11
- package/dist/@pocketprep/ui-kit.umd.cjs.map +1 -1
- package/eslint.config.ts +111 -0
- package/lib/components/Banners/Banner.vue +2 -2
- package/lib/components/Bundles/BundleList.vue +1 -1
- package/lib/components/Bundles/BundleSearch.vue +43 -12
- package/lib/components/Bundles/PremiumPill.vue +2 -2
- package/lib/components/Buttons/Button.vue +19 -18
- package/lib/components/Buttons/Link.vue +9 -8
- package/lib/components/Buttons/Tab.vue +4 -3
- package/lib/components/Calendar/Calendar.vue +14 -2
- package/lib/components/Charts/Bar.vue +3 -3
- package/lib/components/Charts/Pie.vue +4 -4
- package/lib/components/Controls/SegmentControl.vue +8 -7
- package/lib/components/Controls/Slider.vue +2 -3
- package/lib/components/Controls/ToggleSwitch.vue +3 -2
- package/lib/components/EmptyStates/EmptyState.vue +3 -2
- package/lib/components/Exams/ExamCard.vue +3 -3
- package/lib/components/Exams/ExamMenuCard.vue +2 -2
- package/lib/components/Filters/FilterDropdown.vue +2 -2
- package/lib/components/Filters/FilterOptions.vue +2 -2
- package/lib/components/Forms/Checkbox.vue +2 -2
- package/lib/components/Forms/CheckboxOption.vue +2 -2
- package/lib/components/Forms/Errors.vue +2 -2
- package/lib/components/Forms/Input.vue +2 -2
- package/lib/components/Forms/Radio.vue +37 -39
- package/lib/components/Forms/RadioButton.vue +1 -1
- package/lib/components/Forms/Select.vue +7 -6
- package/lib/components/Forms/Textarea.vue +2 -2
- package/lib/components/Icons/Icon.vue +1 -0
- package/lib/components/Icons/IconEdit.vue +4 -2
- package/lib/components/Icons/IconFullViewActive.vue +1 -1
- package/lib/components/Icons/IconLoading2.vue +1 -3
- package/lib/components/Loaders/SkeletonLoader.vue +2 -2
- package/lib/components/Messaging/InfoMessage.vue +2 -2
- package/lib/components/Modal/Modal.vue +2 -2
- package/lib/components/Modal/ModalContainer.vue +2 -2
- package/lib/components/Onboarding/EmailAuth.vue +5 -5
- package/lib/components/Onboarding/MagicCodeEntry.vue +3 -4
- package/lib/components/Pagination/QuestionReviewPagination.vue +23 -21
- package/lib/components/Pagination/TablePagination.vue +2 -2
- package/lib/components/Quiz/FlagToggle.vue +2 -2
- package/lib/components/Quiz/GlobalMetricsToggle.vue +3 -2
- package/lib/components/Quiz/KeyboardShortcutsButton.vue +1 -1
- package/lib/components/Quiz/KeyboardShortcutsModal.vue +1 -1
- package/lib/components/Quiz/Question/ChoicesContainer.vue +99 -132
- package/lib/components/Quiz/Question/DropdownExplanation.vue +41 -55
- package/lib/components/Quiz/Question/Explanation.vue +49 -59
- package/lib/components/Quiz/Question/MatrixChoicesContainer.vue +208 -226
- package/lib/components/Quiz/Question/MatrixRadioGroup.vue +7 -6
- package/lib/components/Quiz/Question/MobileMatrixChoicesContainer.vue +315 -320
- package/lib/components/Quiz/Question/MobileMatrixRadioGroup.vue +14 -11
- package/lib/components/Quiz/Question/PassageAndImage.vue +34 -45
- package/lib/components/Quiz/Question/PassageAndImageDropdown.vue +39 -49
- package/lib/components/Quiz/Question/Paywall.vue +30 -41
- package/lib/components/Quiz/Question/QuestionContext.vue +24 -33
- package/lib/components/Quiz/Question/StatsSummary.vue +12 -22
- package/lib/components/Quiz/Question/Summary.vue +56 -66
- package/lib/components/Quiz/Question/composables.ts +71 -0
- package/lib/components/Quiz/Question/injectionSymbols.ts +69 -0
- package/lib/components/Quiz/Question.vue +810 -1009
- package/lib/components/Quiz/QuizContainer.vue +63 -67
- package/lib/components/Quiz/QuizProgress.vue +73 -77
- package/lib/components/Quiz/QuizProgressBar.vue +3 -2
- package/lib/components/Quiz/question.d.ts +4 -4
- package/lib/components/Search/Pill.vue +2 -2
- package/lib/components/Search/Search.vue +2 -2
- package/lib/components/SidePanels/SidePanel.vue +8 -3
- package/lib/components/Tables/Table.vue +4 -3
- package/lib/components/Tables/TableActions.vue +3 -3
- package/lib/components/Tags/Tag.vue +2 -2
- package/lib/components/Toasts/Toast.vue +5 -3
- package/lib/components/Tooltips/OverflowTooltip.vue +2 -2
- package/lib/components/Tooltips/Tooltip.vue +2 -2
- package/lib/directives.ts +28 -23
- package/lib/pocketprep-export.module.scss +3 -2
- package/lib/pocketprep.scss +2 -2
- package/lib/styles/_breakpoints.scss +12 -24
- package/lib/styles/_colors.scss +0 -1
- package/package.json +38 -29
- package/stylelint.config.js +38 -0
- package/.eslintrc.cjs +0 -74
- package/dist/style.css +0 -1
- package/stylelint.config.cjs +0 -22
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
|
|
14
14
|
}"
|
|
15
15
|
v-dark="isDarkMode"
|
|
16
|
-
v-breakpoint
|
|
16
|
+
v-breakpoint="breakpointsWithEl"
|
|
17
17
|
>
|
|
18
18
|
<div
|
|
19
19
|
class="uikit-question-mobile-matrix-choices-container__row-container"
|
|
20
20
|
v-for="(rowLabel, rowIndex) in matrixRowLabels"
|
|
21
21
|
:key="rowIndex"
|
|
22
22
|
v-dark="isDarkMode"
|
|
23
|
-
v-breakpoint
|
|
23
|
+
v-breakpoint="breakpointsWithEl"
|
|
24
24
|
>
|
|
25
25
|
<div
|
|
26
26
|
class="uikit-question-mobile-matrix-choices-container__row"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
expandedRowNumbers.includes(rowIndex),
|
|
30
30
|
}"
|
|
31
31
|
v-dark="isDarkMode"
|
|
32
|
-
v-breakpoint
|
|
32
|
+
v-breakpoint="breakpointsWithEl"
|
|
33
33
|
@click.stop="toggleChoiceDropdown(rowIndex)"
|
|
34
34
|
>
|
|
35
35
|
<Icon
|
|
@@ -71,20 +71,13 @@
|
|
|
71
71
|
v-for="(colHeader, colHeaderIndex) in selectedColumnHeaders"
|
|
72
72
|
:key="colHeaderIndex"
|
|
73
73
|
>
|
|
74
|
-
<template v-if="
|
|
75
|
-
selectedColumnHeaders &&
|
|
76
|
-
selectedColumnHeaders[rowIndex] &&
|
|
77
|
-
selectedColumnHeaders[rowIndex][colHeaderIndex]">
|
|
74
|
+
<template v-if="doesSelectedColumnHeaderExist(rowIndex, colHeaderIndex)">
|
|
78
75
|
<div
|
|
79
76
|
class="uikit-question-mobile-matrix-choices-container__selected-choice-labels"
|
|
80
77
|
v-dark="isDarkMode"
|
|
81
|
-
v-breakpoint
|
|
78
|
+
v-breakpoint="breakpointsWithEl"
|
|
82
79
|
>
|
|
83
|
-
{{
|
|
84
|
-
selectedColumnHeaders[rowIndex][selectedColumnHeaders[rowIndex].length - 1] ?
|
|
85
|
-
stripHtmlTags(selectedColumnHeaders[rowIndex][colHeaderIndex]) :
|
|
86
|
-
`${stripHtmlTags(selectedColumnHeaders[rowIndex][colHeaderIndex])},`
|
|
87
|
-
}}
|
|
80
|
+
{{ getSelectedChoiceLabels(rowIndex, colHeaderIndex) }}
|
|
88
81
|
</div>
|
|
89
82
|
</template>
|
|
90
83
|
</div>
|
|
@@ -117,7 +110,7 @@
|
|
|
117
110
|
/>
|
|
118
111
|
<Checkbox
|
|
119
112
|
v-else
|
|
120
|
-
:model-value="matrixCheckboxGrid[rowIndex][columnIndex]"
|
|
113
|
+
:model-value="matrixCheckboxGrid[rowIndex]?.[columnIndex]"
|
|
121
114
|
:is-dark-mode="isDarkMode"
|
|
122
115
|
:disabled="showMatrixAnswers || reviewMode"
|
|
123
116
|
:checkbox-styles="checkboxContainerStyling(rowIndex, columnIndex)"
|
|
@@ -128,8 +121,8 @@
|
|
|
128
121
|
:class="{
|
|
129
122
|
'uikit-question-mobile-matrix-choices-container__checkbox-label--distractor':
|
|
130
123
|
(showMatrixAnswers || reviewMode) &&
|
|
131
|
-
matrixChoiceLayout[rowIndex] &&
|
|
132
|
-
matrixChoiceLayout[rowIndex][columnIndex]?.startsWith('d'),
|
|
124
|
+
matrixChoiceLayout?.[rowIndex] &&
|
|
125
|
+
matrixChoiceLayout?.[rowIndex]?.[columnIndex]?.startsWith('d'),
|
|
133
126
|
}"
|
|
134
127
|
>
|
|
135
128
|
{{ stripHtmlTags(column) }}
|
|
@@ -151,7 +144,6 @@
|
|
|
151
144
|
:matrix-answer-keys="matrixAnswerKeys"
|
|
152
145
|
:is-dark-mode="isDarkMode"
|
|
153
146
|
:question-el="questionEl"
|
|
154
|
-
:breakpoints="breakpoints"
|
|
155
147
|
:disabled="false"
|
|
156
148
|
@update:modelValue="updateRadioRowSelection(rowIndex, $event)"
|
|
157
149
|
/>
|
|
@@ -161,394 +153,397 @@
|
|
|
161
153
|
</div>
|
|
162
154
|
</template>
|
|
163
155
|
|
|
164
|
-
<script lang="ts">
|
|
165
|
-
import { Component, Vue, Prop, Emit, Watch } from 'vue-facing-decorator'
|
|
156
|
+
<script setup lang="ts">
|
|
166
157
|
import Icon from '../../Icons/Icon.vue'
|
|
167
|
-
import PocketButton from '../../Buttons/Button.vue'
|
|
168
158
|
import Checkbox from '../../Forms/Checkbox.vue'
|
|
169
159
|
import MobileMatrixRadioGroup from './MobileMatrixRadioGroup.vue'
|
|
170
|
-
import { dark, breakpoint } from '../../../directives'
|
|
171
|
-
import
|
|
172
|
-
import type {
|
|
160
|
+
import { dark as vDark, breakpoint as vBreakpoint } from '../../../directives'
|
|
161
|
+
import { useQuestionContext } from './composables'
|
|
162
|
+
import type { IRadioOptions, TMatrixChoiceKey } from './../question'
|
|
173
163
|
import BrandColors from '../../../pocketprep-export.module.scss'
|
|
164
|
+
import { computed, onMounted, ref, watch } from 'vue'
|
|
165
|
+
|
|
166
|
+
const emit = defineEmits<{
|
|
167
|
+
'emitSelectedMatrixChoice': [matrixChoiceKeys: TMatrixChoiceKey[]]
|
|
168
|
+
}>()
|
|
169
|
+
|
|
170
|
+
const {
|
|
171
|
+
// questionEl is used by the breakpoint directive
|
|
172
|
+
questionEl,
|
|
173
|
+
question,
|
|
174
|
+
isMatrixQuestionCorrect,
|
|
175
|
+
reviewMode,
|
|
176
|
+
isDarkMode,
|
|
177
|
+
breakpointsWithEl,
|
|
178
|
+
showMatrixAnswers,
|
|
179
|
+
matrixAnswerKeys,
|
|
180
|
+
selectedMatrixChoices,
|
|
181
|
+
} = useQuestionContext()
|
|
182
|
+
|
|
183
|
+
const matrixCheckboxGrid = ref<boolean[][] | undefined>(undefined)
|
|
184
|
+
const matrixRadioGrid = ref<IRadioOptions[] | undefined>(undefined)
|
|
185
|
+
const expandedRowNumbers = ref<number[]>([])
|
|
186
|
+
const selectedColumnHeaders = ref<string[][]>([])
|
|
187
|
+
const brandColors = BrandColors
|
|
188
|
+
|
|
189
|
+
const stripHtmlTags = (string?: string) => {
|
|
190
|
+
if (string) {
|
|
191
|
+
const div = document.createElement('div')
|
|
192
|
+
div.innerHTML = string
|
|
193
|
+
return div.textContent || ''
|
|
194
|
+
}
|
|
195
|
+
return ''
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const matrixChoiceLayout = computed(() => {
|
|
199
|
+
return question.value.matrixChoiceLayout
|
|
200
|
+
})
|
|
174
201
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
MobileMatrixRadioGroup,
|
|
181
|
-
},
|
|
182
|
-
directives: {
|
|
183
|
-
dark,
|
|
184
|
-
breakpoint,
|
|
185
|
-
},
|
|
202
|
+
const defaultCheckboxGrid = computed(() => {
|
|
203
|
+
return matrixChoiceLayout.value?.map(row => {
|
|
204
|
+
const choiceRow = row.map(() => false)
|
|
205
|
+
return choiceRow
|
|
206
|
+
})
|
|
186
207
|
})
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
'tablet-portrait': 1023,
|
|
194
|
-
'tablet-landscape': 1439,
|
|
195
|
-
} }) breakpoints!: TBreakPointsObject
|
|
196
|
-
@Prop() question!: Study.Class.QuestionJSON
|
|
197
|
-
@Prop() matrixChoiceLayout!: string[][]
|
|
198
|
-
@Prop({ default: false }) showMatrixAnswers!: boolean
|
|
199
|
-
@Prop({ default: false }) isUnanswered!: boolean
|
|
200
|
-
@Prop({ default: false }) isMatrixQuestionCorrect!: boolean
|
|
201
|
-
@Prop() matrixAnswerKeys!: TMatrixChoiceKey[]
|
|
202
|
-
@Prop() matrixDistractorKeys!: TMatrixChoiceKey[]
|
|
203
|
-
@Prop() selectedMatrixChoices!: TMatrixChoiceKey[]
|
|
204
|
-
@Prop() matrixChoices!: TMatrixChoiceKey[]
|
|
205
|
-
|
|
206
|
-
matrixCheckboxGrid: boolean[][] | undefined = undefined
|
|
207
|
-
matrixRadioGrid: IRadioOptions[] | undefined = undefined
|
|
208
|
-
expandedRowNumbers: number[] = []
|
|
209
|
-
selectedColumnHeaders: string[][] = []
|
|
210
|
-
brandColors = BrandColors
|
|
211
|
-
|
|
212
|
-
stripHtmlTags (string?: string) {
|
|
213
|
-
if (string) {
|
|
214
|
-
const div = document.createElement('div')
|
|
215
|
-
div.innerHTML = string
|
|
216
|
-
return div.textContent || ''
|
|
208
|
+
|
|
209
|
+
const defaultRadioButtonGrid = computed(() => {
|
|
210
|
+
return matrixChoiceLayout.value?.map(row => {
|
|
211
|
+
return {
|
|
212
|
+
choices: row as TMatrixChoiceKey[],
|
|
213
|
+
value: null as TMatrixChoiceKey | null,
|
|
217
214
|
}
|
|
218
|
-
|
|
219
|
-
|
|
215
|
+
})
|
|
216
|
+
})
|
|
220
217
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
return choiceRow
|
|
225
|
-
})
|
|
226
|
-
}
|
|
218
|
+
const matrixRowLabels = computed(() => {
|
|
219
|
+
return question.value.matrixLabels?.rows
|
|
220
|
+
})
|
|
227
221
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
choices: row as TMatrixChoiceKey[],
|
|
232
|
-
value: null as TMatrixChoiceKey | null,
|
|
233
|
-
}
|
|
234
|
-
})
|
|
235
|
-
}
|
|
222
|
+
const matrixColumnLabels = computed(() => {
|
|
223
|
+
return question.value.matrixLabels?.columns
|
|
224
|
+
})
|
|
236
225
|
|
|
237
|
-
|
|
238
|
-
|
|
226
|
+
onMounted(() => {
|
|
227
|
+
if (question.value.type === 'Matrix Checkbox') {
|
|
228
|
+
matrixCheckboxGrid.value = convertSelectedMatrixChoiceToCheckboxGrid()
|
|
239
229
|
}
|
|
240
230
|
|
|
241
|
-
|
|
242
|
-
|
|
231
|
+
if (question.value.type === 'Matrix Radio Button') {
|
|
232
|
+
matrixRadioGrid.value = convertSelectedMatrixChoiceToRadioBtnGrid()
|
|
243
233
|
}
|
|
244
234
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
235
|
+
question.value.matrixChoiceLayout?.forEach(() => {
|
|
236
|
+
selectedColumnHeaders.value.push([])
|
|
237
|
+
})
|
|
238
|
+
})
|
|
249
239
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
240
|
+
const toggleChoiceDropdown = (rowIndex: number) => {
|
|
241
|
+
const includedRowNumberIndex = expandedRowNumbers.value.findIndex(row => row === rowIndex)
|
|
242
|
+
if (includedRowNumberIndex === -1) {
|
|
243
|
+
expandedRowNumbers.value.push(rowIndex)
|
|
244
|
+
} else {
|
|
245
|
+
expandedRowNumbers.value.splice(includedRowNumberIndex, 1)
|
|
246
|
+
}
|
|
247
|
+
}
|
|
253
248
|
|
|
254
|
-
|
|
255
|
-
|
|
249
|
+
const selectedChoiceKey = (rowIndex: number, columnIndex: number) => {
|
|
250
|
+
const row = rowIndex += 1
|
|
251
|
+
const column = columnIndex += 1
|
|
252
|
+
if (selectedMatrixChoices.value.length && matrixAnswerKeys.value.length) {
|
|
253
|
+
const matrixSelectedChoiceKey = selectedMatrixChoices.value.find((choice) => {
|
|
254
|
+
const substring = choice.substring(1)
|
|
255
|
+
return substring === `${row}_${column}`
|
|
256
256
|
})
|
|
257
|
-
}
|
|
258
257
|
|
|
259
|
-
|
|
260
|
-
const includedRowNumberIndex = this.expandedRowNumbers.findIndex(row => row === rowIndex)
|
|
261
|
-
if (includedRowNumberIndex === -1) {
|
|
262
|
-
this.expandedRowNumbers.push(rowIndex)
|
|
263
|
-
} else {
|
|
264
|
-
this.expandedRowNumbers.splice(includedRowNumberIndex, 1)
|
|
265
|
-
}
|
|
258
|
+
return matrixSelectedChoiceKey
|
|
266
259
|
}
|
|
260
|
+
return undefined
|
|
261
|
+
}
|
|
267
262
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
if (this.selectedMatrixChoices.length && this.matrixAnswerKeys.length) {
|
|
272
|
-
const matrixSelectedChoiceKey = this.selectedMatrixChoices.find((choice) => {
|
|
273
|
-
const substring = choice.substring(1)
|
|
274
|
-
return substring === `${row}_${column}`
|
|
275
|
-
})
|
|
276
|
-
|
|
277
|
-
return matrixSelectedChoiceKey
|
|
278
|
-
}
|
|
279
|
-
return undefined
|
|
280
|
-
}
|
|
263
|
+
const getRadioRowSelection = (rowIndex: number) => {
|
|
264
|
+
return matrixRadioGrid.value?.[rowIndex]?.value
|
|
265
|
+
}
|
|
281
266
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
267
|
+
const getRadioRowChoices = (rowIndex: number) => {
|
|
268
|
+
const choices = matrixRadioGrid.value?.[rowIndex]?.choices
|
|
269
|
+
return choices
|
|
270
|
+
}
|
|
285
271
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
272
|
+
const updateRadioRowSelection = (rowIndex: number, choiceKey: TMatrixChoiceKey | null) => {
|
|
273
|
+
const row = matrixRadioGrid.value?.[rowIndex]
|
|
274
|
+
if (row) {
|
|
275
|
+
row.value = choiceKey
|
|
290
276
|
|
|
291
|
-
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
const choiceKeyIndex = row.choices.findIndex(choice => choice === choiceKey)
|
|
298
|
-
const rowHeader = this.question.matrixLabels?.columns[choiceKeyIndex]
|
|
299
|
-
if (rowHeader) {
|
|
300
|
-
this.selectedColumnHeaders[rowIndex]?.pop()
|
|
301
|
-
this.selectedColumnHeaders[rowIndex]?.push(rowHeader)
|
|
302
|
-
}
|
|
277
|
+
// update row header label
|
|
278
|
+
const choiceKeyIndex = row.choices.findIndex(choice => choice === choiceKey)
|
|
279
|
+
const rowHeader = question.value.matrixLabels?.columns[choiceKeyIndex]
|
|
280
|
+
if (rowHeader) {
|
|
281
|
+
selectedColumnHeaders.value[rowIndex]?.pop()
|
|
282
|
+
selectedColumnHeaders.value[rowIndex]?.push(rowHeader)
|
|
303
283
|
}
|
|
304
284
|
}
|
|
285
|
+
}
|
|
305
286
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
}
|
|
287
|
+
const correctlySelectedChoice = (rowIndex: number, columnIndex: number) => {
|
|
288
|
+
if (selectedMatrixChoices.value && matrixAnswerKeys.value) {
|
|
289
|
+
const selectedChoice = selectedChoiceKey(rowIndex, columnIndex)
|
|
290
|
+
if (selectedChoice && selectedChoice.startsWith('a') && matrixAnswerKeys.value.includes(selectedChoice)) {
|
|
291
|
+
return true
|
|
312
292
|
}
|
|
313
|
-
return false
|
|
314
293
|
}
|
|
294
|
+
return false
|
|
295
|
+
}
|
|
315
296
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
297
|
+
const incorrectlySelectedChoice = (rowIndex: number, columnIndex: number) => {
|
|
298
|
+
if (selectedMatrixChoices.value && matrixAnswerKeys.value) {
|
|
299
|
+
const selectedChoice = selectedChoiceKey(rowIndex, columnIndex)
|
|
300
|
+
if (selectedChoice?.startsWith('d')) {
|
|
301
|
+
return true
|
|
322
302
|
}
|
|
323
|
-
return false
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
correctAnswerButNotSelected (rowIndex: number, columnIndex: number) {
|
|
327
|
-
const selectedChoice = this.selectedChoiceKey(rowIndex, columnIndex)
|
|
328
|
-
const answerKey = this.matrixAnswerKeys.find(choice => choice === `a${rowIndex + 1}_${columnIndex + 1}`)
|
|
329
|
-
return answerKey && !selectedChoice
|
|
330
303
|
}
|
|
304
|
+
return false
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const correctAnswerButNotSelected = (rowIndex: number, columnIndex: number) => {
|
|
308
|
+
const selectedChoice = selectedChoiceKey(rowIndex, columnIndex)
|
|
309
|
+
const answerKey = matrixAnswerKeys.value.find(choice => choice === `a${rowIndex + 1}_${columnIndex + 1}`)
|
|
310
|
+
return answerKey && !selectedChoice
|
|
311
|
+
}
|
|
331
312
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const incorrectlySelectedChoice = this.incorrectlySelectedChoice(rowIndex, columnIndex)
|
|
313
|
+
const checkboxContainerStyling = (rowIndex: number, columnIndex: number) => {
|
|
314
|
+
const isReviewMode = showMatrixAnswers.value || reviewMode.value
|
|
335
315
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
}
|
|
316
|
+
// check box is correctlySelected
|
|
317
|
+
if (isReviewMode && correctlySelectedChoice(rowIndex, columnIndex)) {
|
|
318
|
+
const borderColor = isDarkMode.value ? brandColors.jungleGreen : brandColors.cadaverous
|
|
319
|
+
return {
|
|
320
|
+
borderColor: `${borderColor} !important`,
|
|
321
|
+
background: `${borderColor} !important`,
|
|
343
322
|
}
|
|
323
|
+
}
|
|
344
324
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
}
|
|
325
|
+
if (isReviewMode && incorrectlySelectedChoice(rowIndex, columnIndex)) {
|
|
326
|
+
return {
|
|
327
|
+
background: `${brandColors.steel} !important`,
|
|
328
|
+
border: `1px solid ${brandColors.steel} !important`,
|
|
350
329
|
}
|
|
330
|
+
}
|
|
351
331
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
}
|
|
332
|
+
if (isReviewMode && correctAnswerButNotSelected(rowIndex, columnIndex)) {
|
|
333
|
+
return {
|
|
334
|
+
background: 'transparent !important',
|
|
335
|
+
border: `1px solid ${brandColors.slate} !important`,
|
|
357
336
|
}
|
|
358
337
|
}
|
|
338
|
+
}
|
|
359
339
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
}
|
|
340
|
+
const checkboxCheckStyling = (rowIndex: number, columnIndex: number) => {
|
|
341
|
+
const isReviewMode = showMatrixAnswers.value || reviewMode.value
|
|
342
|
+
if (isReviewMode && correctAnswerButNotSelected(rowIndex, columnIndex)) {
|
|
343
|
+
const color = isDarkMode.value ? brandColors.jungleGreen : brandColors.cadaverous
|
|
344
|
+
return {
|
|
345
|
+
color: `${color} !important`,
|
|
367
346
|
}
|
|
368
347
|
}
|
|
348
|
+
}
|
|
369
349
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
}
|
|
350
|
+
const correctRow = (rowIndex: number) => {
|
|
351
|
+
if (matrixChoiceLayout.value?.[rowIndex]) {
|
|
352
|
+
if (
|
|
353
|
+
question?.value.type === 'Matrix Checkbox' &&
|
|
354
|
+
matrixCheckboxGrid.value?.[rowIndex]
|
|
355
|
+
) {
|
|
356
|
+
const correctAnswerKeys = matrixChoiceLayout.value[rowIndex]?.filter(choice =>
|
|
357
|
+
choice.startsWith('a')
|
|
358
|
+
)
|
|
359
|
+
const selectedAnswerKeys = matrixCheckboxGrid.value[rowIndex]?.map((choice, choiceIndex) => {
|
|
360
|
+
return selectedChoiceKey(rowIndex, choiceIndex)
|
|
361
|
+
})
|
|
362
|
+
const correctSelectedKeys = matrixCheckboxGrid.value[rowIndex]?.filter((choice, choiceIndex) => {
|
|
363
|
+
const selectedChoice = selectedChoiceKey(rowIndex, choiceIndex)
|
|
364
|
+
return selectedChoice?.startsWith('a')
|
|
365
|
+
})
|
|
366
|
+
return !selectedAnswerKeys?.some(choice => choice?.startsWith('d')) &&
|
|
367
|
+
(correctAnswerKeys?.length === correctSelectedKeys?.length)
|
|
368
|
+
}
|
|
390
369
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
return rowVal.startsWith('a')
|
|
399
|
-
}
|
|
400
|
-
return false
|
|
370
|
+
if (
|
|
371
|
+
question?.value.type === 'Matrix Radio Button' &&
|
|
372
|
+
matrixRadioGrid.value?.[rowIndex]
|
|
373
|
+
) {
|
|
374
|
+
const rowVal = matrixRadioGrid.value[rowIndex]?.value
|
|
375
|
+
if (rowVal) {
|
|
376
|
+
return rowVal.startsWith('a')
|
|
401
377
|
}
|
|
378
|
+
return false
|
|
402
379
|
}
|
|
403
|
-
return false
|
|
404
380
|
}
|
|
381
|
+
return false
|
|
382
|
+
}
|
|
405
383
|
|
|
406
|
-
|
|
407
|
-
|
|
384
|
+
const convertSelectedMatrixChoiceToCheckboxGrid = () => {
|
|
385
|
+
const checkboxGrid = defaultCheckboxGrid.value
|
|
408
386
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
387
|
+
// Reset selectedColumnHeaders string[][] in case in headers are still in the arrays
|
|
388
|
+
// Let selectedMatrixChoices set those columns
|
|
389
|
+
const columnMatrixLabels = question.value.matrixLabels?.rows
|
|
390
|
+
const defaultSelectedColumnLabels: string[][] = []
|
|
391
|
+
if (columnMatrixLabels) {
|
|
392
|
+
columnMatrixLabels.forEach(() => {
|
|
393
|
+
defaultSelectedColumnLabels.push([])
|
|
394
|
+
})
|
|
417
395
|
|
|
418
|
-
|
|
419
|
-
|
|
396
|
+
selectedColumnHeaders.value = defaultSelectedColumnLabels
|
|
397
|
+
}
|
|
420
398
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
399
|
+
selectedMatrixChoices.value.forEach(choice => {
|
|
400
|
+
const rowIndex = Number(choice.substring(1, choice.indexOf('_'))) - 1
|
|
401
|
+
const columnIndex = Number(choice.split('_').pop()) - 1
|
|
402
|
+
const row = checkboxGrid?.[rowIndex]
|
|
403
|
+
if (row) {
|
|
404
|
+
row[columnIndex] = true
|
|
405
|
+
if (selectedColumnHeaders.value[rowIndex] && question.value.matrixLabels?.columns[columnIndex]) {
|
|
406
|
+
const columnHeader = question.value.matrixLabels?.columns[columnIndex]
|
|
407
|
+
if (columnHeader) {
|
|
408
|
+
selectedColumnHeaders.value[rowIndex]?.push(columnHeader)
|
|
429
409
|
}
|
|
430
410
|
}
|
|
431
|
-
})
|
|
432
|
-
return checkboxGrid
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
convertSelectedMatrixChoiceToRadioBtnGrid () {
|
|
436
|
-
const radioBtnGrid = this.defaultRadioButtonGrid
|
|
437
|
-
|
|
438
|
-
const columnMatrixLabels = this.question.matrixLabels?.rows
|
|
439
|
-
const defaultSelectedColumnLabels: string[][] = []
|
|
440
|
-
if (columnMatrixLabels) {
|
|
441
|
-
columnMatrixLabels.forEach(() => {
|
|
442
|
-
defaultSelectedColumnLabels.push([])
|
|
443
|
-
})
|
|
444
|
-
|
|
445
|
-
this.selectedColumnHeaders = defaultSelectedColumnLabels
|
|
446
411
|
}
|
|
412
|
+
})
|
|
413
|
+
return checkboxGrid
|
|
414
|
+
}
|
|
447
415
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
this.selectedColumnHeaders[rowIndex].push(columnHeader)
|
|
457
|
-
}
|
|
458
|
-
if (radioBtnGrid && radioBtnGrid[rowIndex]) {
|
|
459
|
-
radioBtnGrid[rowIndex].value = choice
|
|
460
|
-
}
|
|
416
|
+
const convertSelectedMatrixChoiceToRadioBtnGrid = () => {
|
|
417
|
+
const radioBtnGrid = defaultRadioButtonGrid.value
|
|
418
|
+
|
|
419
|
+
const columnMatrixLabels = question.value.matrixLabels?.rows
|
|
420
|
+
const defaultSelectedColumnLabels: string[][] = []
|
|
421
|
+
if (columnMatrixLabels) {
|
|
422
|
+
columnMatrixLabels.forEach(() => {
|
|
423
|
+
defaultSelectedColumnLabels.push([])
|
|
461
424
|
})
|
|
462
|
-
|
|
425
|
+
|
|
426
|
+
selectedColumnHeaders.value = defaultSelectedColumnLabels
|
|
463
427
|
}
|
|
464
428
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
429
|
+
selectedMatrixChoices.value.forEach(choice => {
|
|
430
|
+
const rowIndex = Number(choice.substring(1, choice.indexOf('_'))) - 1
|
|
431
|
+
const columnIndex = Number(choice.split('_').pop()) - 1
|
|
432
|
+
if (selectedColumnHeaders.value[rowIndex] && question.value.matrixLabels?.columns[columnIndex]) {
|
|
433
|
+
const columnHeader = question.value.matrixLabels?.columns[columnIndex]
|
|
434
|
+
// In case a column header is still in selectedColumnHeaders, remove it first and let
|
|
435
|
+
// selectedMatrixChoices add selected column header based on selected choices
|
|
436
|
+
if (columnHeader) {
|
|
437
|
+
selectedColumnHeaders.value[rowIndex]?.pop()
|
|
438
|
+
selectedColumnHeaders.value[rowIndex]?.push(columnHeader)
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
const radioBtnGridRow = radioBtnGrid?.[rowIndex]
|
|
442
|
+
if (radioBtnGridRow) {
|
|
443
|
+
radioBtnGridRow.value = choice
|
|
444
|
+
}
|
|
445
|
+
})
|
|
446
|
+
return radioBtnGrid
|
|
447
|
+
}
|
|
469
448
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
449
|
+
const checkboxRowClicked = (rowIndex: number, columnIndex: number) => {
|
|
450
|
+
const matrixCheckboxGridRow = matrixCheckboxGrid.value?.[rowIndex]
|
|
451
|
+
if (matrixCheckboxGridRow) {
|
|
452
|
+
matrixCheckboxGridRow[columnIndex] = !matrixCheckboxGridRow[columnIndex]
|
|
453
|
+
const columnHeader = question.value.matrixLabels?.columns[columnIndex]
|
|
454
|
+
|
|
455
|
+
if (selectedColumnHeaders.value?.[rowIndex] && columnHeader) {
|
|
456
|
+
if (selectedColumnHeaders.value[rowIndex]?.includes(columnHeader)) {
|
|
457
|
+
const columnHeaderIndex = selectedColumnHeaders.value[rowIndex]?.indexOf(columnHeader)
|
|
458
|
+
if (columnHeaderIndex !== undefined && columnHeaderIndex !== -1) {
|
|
459
|
+
selectedColumnHeaders.value[rowIndex]?.splice(columnHeaderIndex, 1)
|
|
478
460
|
}
|
|
461
|
+
} else {
|
|
462
|
+
selectedColumnHeaders.value[rowIndex]?.push(columnHeader)
|
|
479
463
|
}
|
|
480
464
|
}
|
|
481
465
|
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const doesSelectedColumnHeaderExist = (rowIndex: number, columnIndex: number) => {
|
|
469
|
+
return selectedColumnHeaders.value?.[rowIndex]?.[columnIndex] || false
|
|
470
|
+
}
|
|
482
471
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
472
|
+
const getSelectedChoiceLabels = (rowIndex: number, columnIndex: number) => {
|
|
473
|
+
const columnHeadersInRow = selectedColumnHeaders.value?.[rowIndex]
|
|
474
|
+
if (!columnHeadersInRow) {
|
|
475
|
+
return
|
|
486
476
|
}
|
|
477
|
+
const selectedColumnHeader = columnHeadersInRow[columnIndex]
|
|
478
|
+
const lastColumnHeader = columnHeadersInRow[columnHeadersInRow.length - 1]
|
|
479
|
+
if (!selectedColumnHeader) {
|
|
480
|
+
return ''
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
return selectedColumnHeader === lastColumnHeader
|
|
484
|
+
? stripHtmlTags(selectedColumnHeader)
|
|
485
|
+
: `${stripHtmlTags(selectedColumnHeader)},`
|
|
486
|
+
}
|
|
487
487
|
|
|
488
|
+
const emitSelectedMatrixChoice = (matrixChoiceKeys: TMatrixChoiceKey[]) => {
|
|
489
|
+
emit('emitSelectedMatrixChoice', matrixChoiceKeys)
|
|
490
|
+
}
|
|
488
491
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
const selectedCheckboxChoices: TMatrixChoiceKey[] = []
|
|
492
|
+
watch(matrixCheckboxGrid, () => {
|
|
493
|
+
if (matrixChoiceLayout.value && matrixCheckboxGrid.value && (!reviewMode.value || !showMatrixAnswers.value)) {
|
|
494
|
+
const selectedCheckboxChoices: TMatrixChoiceKey[] = []
|
|
493
495
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
this.matrixChoiceLayout[rowIndex][choiceIndex]
|
|
500
|
-
) {
|
|
501
|
-
const choiceKey = this.matrixChoiceLayout[rowIndex][choiceIndex] as TMatrixChoiceKey
|
|
496
|
+
matrixCheckboxGrid.value.forEach((row, rowIndex) => {
|
|
497
|
+
row.forEach((choice, choiceIndex) => {
|
|
498
|
+
if (choice && matrixChoiceLayout?.value?.[rowIndex]?.[choiceIndex]) {
|
|
499
|
+
const choiceKey = matrixChoiceLayout.value?.[rowIndex]?.[choiceIndex] as TMatrixChoiceKey
|
|
500
|
+
if (choiceKey) {
|
|
502
501
|
selectedCheckboxChoices.push(choiceKey)
|
|
503
502
|
}
|
|
504
|
-
}
|
|
503
|
+
}
|
|
505
504
|
})
|
|
505
|
+
})
|
|
506
506
|
|
|
507
|
-
|
|
508
|
-
}
|
|
507
|
+
emitSelectedMatrixChoice(selectedCheckboxChoices)
|
|
509
508
|
}
|
|
509
|
+
}, { deep: true })
|
|
510
510
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
const selectedRadioButtonChoices: TMatrixChoiceKey[] = []
|
|
511
|
+
watch(matrixRadioGrid, () => {
|
|
512
|
+
if (matrixChoiceLayout.value && matrixRadioGrid.value && (!reviewMode.value || !showMatrixAnswers.value)) {
|
|
513
|
+
const selectedRadioButtonChoices: TMatrixChoiceKey[] = []
|
|
515
514
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
515
|
+
matrixRadioGrid.value.forEach((row) => {
|
|
516
|
+
if (row.value) {
|
|
517
|
+
selectedRadioButtonChoices.push(row.value)
|
|
518
|
+
}
|
|
519
|
+
})
|
|
521
520
|
|
|
522
|
-
|
|
523
|
-
}
|
|
521
|
+
emitSelectedMatrixChoice(selectedRadioButtonChoices)
|
|
524
522
|
}
|
|
523
|
+
}, { deep: true })
|
|
525
524
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
this.expandedRowNumbers = []
|
|
530
|
-
}
|
|
525
|
+
watch(showMatrixAnswers, () => {
|
|
526
|
+
if (showMatrixAnswers) {
|
|
527
|
+
expandedRowNumbers.value = []
|
|
531
528
|
}
|
|
529
|
+
})
|
|
532
530
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
this.matrixCheckboxGrid = selectedCheckboxGrid ? selectedCheckboxGrid : this.defaultCheckboxGrid
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
if ((this.reviewMode || this.showMatrixAnswers) && this.question.type === 'Matrix Radio Button') {
|
|
541
|
-
const selectedRadioBtnGrid = this.convertSelectedMatrixChoiceToRadioBtnGrid()
|
|
542
|
-
this.matrixRadioGrid = selectedRadioBtnGrid
|
|
543
|
-
}
|
|
531
|
+
watch(selectedMatrixChoices, () => {
|
|
532
|
+
if ((reviewMode.value || showMatrixAnswers.value) && question.value.type === 'Matrix Checkbox') {
|
|
533
|
+
const selectedCheckboxGrid = convertSelectedMatrixChoiceToCheckboxGrid()
|
|
534
|
+
matrixCheckboxGrid.value = selectedCheckboxGrid ? selectedCheckboxGrid : defaultCheckboxGrid.value
|
|
544
535
|
}
|
|
545
|
-
}
|
|
546
536
|
|
|
537
|
+
if ((reviewMode.value || showMatrixAnswers.value) && question.value.type === 'Matrix Radio Button') {
|
|
538
|
+
const selectedRadioBtnGrid = convertSelectedMatrixChoiceToRadioBtnGrid()
|
|
539
|
+
matrixRadioGrid.value = selectedRadioBtnGrid
|
|
540
|
+
}
|
|
541
|
+
})
|
|
547
542
|
</script>
|
|
548
543
|
|
|
549
544
|
<style lang="scss">
|
|
550
|
-
@
|
|
551
|
-
@
|
|
545
|
+
@use '@/styles/breakpoints' as *;
|
|
546
|
+
@use '@/styles/colors' as *;
|
|
552
547
|
|
|
553
548
|
.uikit-question-mobile-matrix-choices-container {
|
|
554
549
|
width: 100%;
|