Skip to content

Commit

Permalink
Fix questions shopping cart and add empty questions notice
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexVelezLl committed Feb 19, 2025
1 parent 42fe344 commit 95ae8d6
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
>
<AccordionItem
:title="displayQuestionTitle(question, getQuestionContent(question).title)"
:aria-selected="selectedQuestions.includes(question.item)"
:aria-selected="questionIsChecked(question)"
:headerAppearanceOverrides="{
userSelect: dragActive ? 'none !important' : 'text',
}"
Expand All @@ -79,7 +79,7 @@
<KCheckbox
v-if="isSelectable"
class="accordion-item-checkbox"
:checked="selectedQuestions.includes(question.item)"
:checked="questionIsChecked(question)"
:disabled="questionCheckboxDisabled(question)"
@change="
(value, $event) => handleQuestionCheckboxChange(question.item, value, $event)
Expand Down Expand Up @@ -169,11 +169,20 @@
return props.selectedQuestions.length >= props.maxSelectableQuestions;
}
function questionIsChecked(question) {
if (props.unselectableQuestionItems?.includes(question.item)) {
return true;
}
return props.selectedQuestions.includes(question.item);
}
const selectableQuestions = computed(() => {
if (!props.isSelectable) {
return [];
}
return props.questions.filter(question => !questionCheckboxDisabled(question));
return props.questions.filter(
question => !props.unselectableQuestionItems?.includes(question.item),
);
});
const selectAllIsChecked = computed(
Expand All @@ -197,7 +206,7 @@
if (props.disabled) {
return true;
}
if (props.maxSelectableQuestions === null) {
if (props.maxSelectableQuestions === null || selectAllIsChecked.value) {
return false;
}
if (props.selectedQuestions.length >= props.maxSelectableQuestions) {
Expand All @@ -220,6 +229,7 @@
moveUpOne,
moveDownOne,
questionIsChecked,
displayQuestionTitle,
questionCheckboxDisabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,6 @@
required: false,
default: null,
},
/**
* Function that receives a resourceId and returns a link to the resource.
*/
getResourceLink: {
type: Function,
required: true,
},
/**
* The target entity for the selection.
* It can be either 'quiz' or 'lesson'.
Expand All @@ -173,6 +166,13 @@
required: false,
default: null,
},
/**
* Function that receives a resourceId and returns a link to the resource.
*/
getResourceLink: {
type: Function,
required: true,
},
},
computed: {
resultsCountMessage() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@
const settings = ref({
maxQuestions: null,
questionCount: null,
isChoosingManually: true,
isChoosingManually: false,
selectPracticeQuiz,
});
watch(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
<template>

<p v-if="workingQuestions.length === 0">
{{ emptyQuestionsList$() }}
</p>
<QuestionsAccordion
v-else
:questions="workingQuestions"
:getQuestionContent="getQuestionContent"
:selectedQuestions="selectedQuestionsInPreview"
:selectAllIsChecked="selectAllIsChecked"
:selectAllIsIndeterminate="selectAllIsIndeterminate"
@select="handleSelect"
@selectAll="handleSelectAll"
:selectedQuestions="cartSelectedQuestions"
@selectQuestions="handleSelectQuestions"
@deselectQuestions="handleDeselectQuestions"
>
<template #header-trailing-actions>
<KIconButton
icon="trash"
:tooltip="coreString('deleteAction')"
:aria-label="coreString('deleteAction')"
:disabled="selectedQuestionsInPreview.length === 0"
:disabled="cartSelectedQuestions.length === 0"
@click="deleteQuestions"
/>
</template>
Expand All @@ -39,6 +41,8 @@

<script>
import uniq from 'lodash/uniq';
import { getCurrentInstance, watch } from 'vue';
import commonCoreStrings from 'kolibri/uiText/commonCoreStrings';
import { searchAndFilterStrings } from 'kolibri-common/strings/searchAndFilterStrings';
import QuestionsAccordion from '../../../../../common/QuestionsAccordion.vue';
Expand All @@ -50,14 +54,37 @@
QuestionsAccordion,
},
mixins: [commonCoreStrings],
setup() {
const { openExerciseLabel$ } = searchAndFilterStrings;
setup(props) {
const router = getCurrentInstance().proxy.$router;
const { openExerciseLabel$, numberOfSelectedQuestions$, emptyQuestionsList$ } =
searchAndFilterStrings;
props.setTitle(numberOfSelectedQuestions$({ count: props.selectedQuestions.length }));
props.setGoBack(() => {
router.back();
});
watch(
() => props.selectedQuestions,
() => {
props.setTitle(numberOfSelectedQuestions$({ count: props.selectedQuestions.length }));
},
);
return {
openExerciseLabel$,
emptyQuestionsList$,
};
},
props: {
setTitle: {
type: Function,
default: () => {},
},
setGoBack: {
type: Function,
default: () => {},
},
selectedQuestions: {
type: Array,
required: true,
Expand All @@ -69,55 +96,31 @@
},
data() {
return {
// questions: stubQuestions,
selectedQuestionsInPreview: [],
cartSelectedQuestions: [],
};
},
computed: {
workingQuestions() {
return this.selectedQuestions;
},
selectAllIsChecked() {
return (
this.selectedQuestionsInPreview.length > 0 &&
this.selectedQuestionsInPreview.length === this.workingQuestions.length
);
},
selectAllIsIndeterminate() {
return (
this.selectedQuestionsInPreview.length > 0 &&
this.selectedQuestionsInPreview.length < this.workingQuestions.length
);
},
},
methods: {
handleSelect(questionItem, isSelected) {
if (isSelected) {
if (!this.selectedQuestionsInPreview.includes(questionItem)) {
this.selectedQuestionsInPreview.push(questionItem);
}
} else {
const index = this.selectedQuestionsInPreview.indexOf(questionItem);
if (index > -1) {
this.selectedQuestionsInPreview.splice(index, 1);
}
}
handleSelectQuestions(questionItems) {
this.cartSelectedQuestions = uniq([...this.cartSelectedQuestions, ...questionItems]);
},
handleSelectAll(isSelected) {
if (isSelected) {
this.selectedQuestionsInPreview = this.workingQuestions.map(q => q.item);
} else {
this.selectedQuestionsInPreview = [];
}
handleDeselectQuestions(questionItems) {
this.cartSelectedQuestions = this.cartSelectedQuestions.filter(
q => !questionItems.includes(q),
);
},
getQuestionContent(question) {
return this.selectedResources.find(resource => resource.id === question.exercise_id);
},
deleteQuestions() {
const questionsToDelete = this.selectedQuestionsInPreview.map(q =>
const questionsToDelete = this.cartSelectedQuestions.map(q =>
this.workingQuestions.find(wq => wq.item === q),
);
this.selectedQuestionsInPreview = [];
this.cartSelectedQuestions = [];
this.$emit('deselectQuestions', questionsToDelete);
},
navigateToParent(question) {
Expand Down
4 changes: 4 additions & 0 deletions packages/kolibri-common/strings/searchAndFilterStrings.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ export const searchAndFilterStrings = createTranslator('SearchAndFilterStrings',
message: 'No resources selected',
context: 'Message displayed when no resources are selected',
},
emptyQuestionsList: {
message: 'No questions selected',
context: 'Message displayed when no questions are selected',
},
searchInFolder: {
message: "Search in '{folder}'",
context: 'Title for search resources in folder',
Expand Down

0 comments on commit 95ae8d6

Please sign in to comment.