Skip to content

Commit

Permalink
Update select quiz workflow to use new components and composable.
Browse files Browse the repository at this point in the history
  • Loading branch information
rtibbles committed Jun 12, 2024
1 parent f8845a7 commit 476eb51
Show file tree
Hide file tree
Showing 9 changed files with 258 additions and 130 deletions.
133 changes: 81 additions & 52 deletions kolibri/plugins/coach/assets/src/composables/useQuizCreation.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,62 @@ export default function useQuizCreation() {
question_count: originalQuestionCount,
} = targetSection;

const { resource_pool, question_count } = updates;
const { question_count, questions } = updates;

if (questions && question_count) {
throw new TypeError(
'Cannot update both `questions` and `question_count` at the same time; use one or the other.'
);
}

if (question_count) {
// The question_count is so we need to update the selected resources
if (question_count > originalQuestionCount) {
updates.questions = [
...originalQuestions,
...selectRandomQuestionsFromResources(
question_count - originalQuestionCount,
originalResourcePool
),
];
} else if (question_count < originalQuestionCount) {
updates.questions = originalQuestions.slice(0, question_count);
}
}

if (questions) {
// The questions are being updated
// Set question_count to the length of the questions array
updates.question_count = questions.length;
}

const _allSections = get(allSections);

set(_quiz, {
...get(quiz),
// Update matching QuizSections with the updates object
question_sources: [
..._allSections.slice(0, sectionIndex),
{ ...targetSection, ...updates },
..._allSections.slice(sectionIndex + 1),
],
});
}

function updateSectionResourcePool({ sectionIndex, resource_pool }) {
const targetSection = get(allSections)[sectionIndex];
if (!targetSection) {
throw new TypeError(`Section with id ${sectionIndex} not found; cannot be updated.`);
}

// original variables are the original values of the properties we're updating
const {
resource_pool: originalResourcePool,
questions: originalQuestions,
question_count: originalQuestionCount,
} = targetSection;

const updates = { resource_pool };
if (resource_pool?.length === 0) {
// The user has removed all resources from the section, so we can clear all questions too
updates.questions = [];
Expand All @@ -95,65 +149,36 @@ export default function useQuizCreation() {
// if there weren't resources in the originalResourcePool before.
// ***
updates.questions = selectRandomQuestionsFromResources(
question_count || originalQuestionCount || 0,
originalQuestionCount || 0,
resource_pool
);
} else {
// We're updating the resource_pool of a section that already had resources
if (question_count === 0) {
updates.questions = [];
} else {
// In this case, we already had resources in the section, so we need to handle the
// case where a resource has been removed so that we remove & replace the questions
const removedResourceQuestionIds = originalResourcePool.reduce(
(questionIds, originalResource) => {
if (!resource_pool.map(r => r.id).includes(originalResource.id)) {
// If the resource_pool doesn't have the originalResource, we're removing it
questionIds = [...questionIds, ...originalResource.unique_question_ids];
return questionIds;
}
// In this case, we already had resources in the section, so we need to handle the
// case where a resource has been removed so that we remove & replace the questions
const removedResourceQuestionIds = originalResourcePool.reduce(
(questionIds, originalResource) => {
if (!resource_pool.map(r => r.id).includes(originalResource.id)) {
// If the resource_pool doesn't have the originalResource, we're removing it
questionIds = [...questionIds, ...originalResource.unique_question_ids];
return questionIds;
},
[]
}
return questionIds;
},
[]
);
if (removedResourceQuestionIds.length !== 0) {
const questionsToKeep = originalQuestions.filter(
q => !removedResourceQuestionIds.includes(q.item)
);
if (removedResourceQuestionIds.length !== 0) {
const questionsToKeep = originalQuestions.filter(
q => !removedResourceQuestionIds.includes(q.item)
);
const numReplacementsNeeded =
(question_count || originalQuestionCount) - questionsToKeep.length;
updates.questions = [
...questionsToKeep,
...selectRandomQuestionsFromResources(numReplacementsNeeded, resource_pool),
];
}
const numReplacementsNeeded = originalQuestionCount - questionsToKeep.length;
updates.questions = [
...questionsToKeep,
...selectRandomQuestionsFromResources(numReplacementsNeeded, resource_pool),
];
}
}
}
// The resource pool isn't being updated but the question_count is so we need to update them
if (question_count > originalQuestionCount) {
updates.questions = [
...originalQuestions,
...selectRandomQuestionsFromResources(
question_count - originalQuestionCount,
originalResourcePool
),
];
} else if (question_count < originalQuestionCount) {
updates.questions = originalQuestions.slice(0, question_count);
}

const _allSections = get(allSections);

set(_quiz, {
...get(quiz),
// Update matching QuizSections with the updates object
question_sources: [
..._allSections.slice(0, sectionIndex),
{ ...targetSection, ...updates },
..._allSections.slice(sectionIndex + 1),
],
});
updateSection({ sectionIndex, ...updates });
}

function handleReplacement() {
Expand Down Expand Up @@ -485,6 +510,7 @@ export default function useQuizCreation() {

provide('allQuestionsInQuiz', allQuestionsInQuiz);
provide('updateSection', updateSection);
provide('updateSectionResourcePool', updateSectionResourcePool);
provide('handleReplacement', handleReplacement);
provide('replaceSelectedQuestions', replaceSelectedQuestions);
provide('addSection', addSection);
Expand Down Expand Up @@ -515,6 +541,7 @@ export default function useQuizCreation() {
// Methods
saveQuiz,
updateSection,
updateSectionResourcePool,
handleReplacement,
replaceSelectedQuestions,
addSection,
Expand Down Expand Up @@ -550,6 +577,7 @@ export default function useQuizCreation() {
export function injectQuizCreation() {
const allQuestionsInQuiz = inject('allQuestionsInQuiz');
const updateSection = inject('updateSection');
const updateSectionResourcePool = inject('updateSectionResourcePool');
const handleReplacement = inject('handleReplacement');
const replaceSelectedQuestions = inject('replaceSelectedQuestions');
const addSection = inject('addSection');
Expand Down Expand Up @@ -580,6 +608,7 @@ export function injectQuizCreation() {
deleteActiveSelectedQuestions,
selectAllQuestions,
updateSection,
updateSectionResourcePool,
handleReplacement,
replaceSelectedQuestions,
addSection,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ const _loadingMore = ref(false);
* @module useQuizResources
* @param {QuizResourcesConfig} config
*/
export default function useQuizResources({ topicId } = {}) {
export default function useQuizResources({ topicId, practiceQuiz = false } = {}) {
const params = {
kind_in: [ContentNodeKinds.EXERCISE, ContentNodeKinds.TOPIC],
include_coach_content: true,
};

if (practiceQuiz) {
params.contains_quiz = true;
}

// Initialize useFetchTree methods with the given topicId computed property and params
const { topic, fetchTree, fetchMore, hasMore, loading: treeLoading } = useFetchTree({
topicId,
Expand Down Expand Up @@ -135,7 +139,8 @@ export default function useQuizResources({ topicId } = {}) {
return (
node.kind === ContentNodeKinds.EXERCISE ||
// Has children, no more to load, and no children are topics
(node.children &&
(!practiceQuiz &&
node.children &&
!node.children.more &&
!node.children.results.some(c => c.kind === ContentNodeKinds.TOPIC))
);
Expand Down
1 change: 1 addition & 0 deletions kolibri/plugins/coach/assets/src/constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const PageNames = {
QUIZ_SECTION_EDITOR: 'QUIZ_SECTION_EDITOR',
QUIZ_REPLACE_QUESTIONS: 'QUIZ_REPLACE_QUESTIONS',
QUIZ_SELECT_RESOURCES: 'QUIZ_SELECT_RESOURCES',
QUIZ_SELECT_PRACTICE_QUIZ: 'QUIZ_SELECT_PRACTICE_QUIZ',
BOOK_MARKED_RESOURCES: 'BOOK_MARKED_RESOURCES',

/** TODO Remove unused */
Expand Down
8 changes: 8 additions & 0 deletions kolibri/plugins/coach/assets/src/routes/planExamRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ export default [
path: 'select-resources/:topic_id?',
component: ResourceSelection,
},
{
name: PageNames.QUIZ_SELECT_PRACTICE_QUIZ,
path: 'select-quiz/:topic_id?',
component: ResourceSelection,
props: {
selectPracticeQuiz: true,
},
},
],
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,12 +398,12 @@
handleSelect({ value }) {
const nextRouteName = {
MAKE_NEW_QUIZ: PageNames.EXAM_CREATION_ROOT,
SELECT_QUIZ: PageNames.EXAM_CREATION_PRACTICE_QUIZ,
SELECT_QUIZ: PageNames.QUIZ_SELECT_PRACTICE_QUIZ,
}[value];
const nextRoute = { name: nextRouteName, params: { ...this.$route.params } };
if (value === 'MAKE_NEW_QUIZ') {
nextRoute.params.quizId = 'new';
}
const nextRoute = {
name: nextRouteName,
params: { ...this.$route.params, quizId: 'new', sectionIndex: 0 },
};
this.$router.push(nextRoute);
},
},
Expand Down
Loading

0 comments on commit 476eb51

Please sign in to comment.