-
+
+
+
+
+
@@ -32,19 +52,24 @@
@@ -56,48 +81,77 @@
import { computed, getCurrentInstance } from 'vue';
import { coreStrings } from 'kolibri/uiText/commonCoreStrings';
import { searchAndFilterStrings } from 'kolibri-common/strings/searchAndFilterStrings';
- import UpdatedResourceSelection from '../../../UpdatedResourceSelection.vue';
- import { coachStrings } from '../../../../../common/commonCoachStrings';
- import { PageNames } from '../../../../../../constants';
+ import { enhancedQuizManagementStrings } from 'kolibri-common/strings/enhancedQuizManagementStrings';
+ import { coachStrings } from '../../commonCoachStrings';
+ import { PageNames } from '../../../../constants';
+ import UpdatedResourceSelection from '../UpdatedResourceSelection.vue';
+ import QuizResourceSelectionHeader from '../QuizResourceSelectionHeader.vue';
+ import { SelectionTarget } from '../contants';
/**
- * @typedef {import('../../../../../../composables/useFetch').FetchObject} FetchObject
+ * @typedef {import('../../../../composables/useFetch').FetchObject} FetchObject
*/
export default {
name: 'SelectFromTopicTree',
components: {
UpdatedResourceSelection,
+ QuizResourceSelectionHeader,
},
setup(props) {
const { selectFromChannels$, searchLabel$ } = coreStrings;
const { manageLessonResourcesTitle$ } = coachStrings;
- const { backToSearchResultsLabel$ } = searchAndFilterStrings;
const instance = getCurrentInstance();
+
+ const { selectResourcesDescription$, selectPracticeQuizLabel$ } =
+ enhancedQuizManagementStrings;
+ const { backToSearchResultsLabel$ } = searchAndFilterStrings;
+
const routeQuery = instance.proxy.$route.query;
const isTopicFromSearchResult = computed(() => !!routeQuery.searchResultTopicId);
- props.setTitle(
- isTopicFromSearchResult.value ? backToSearchResultsLabel$() : manageLessonResourcesTitle$(),
- );
+ const getTitle = () => {
+ if (isTopicFromSearchResult.value) {
+ return backToSearchResultsLabel$();
+ }
+ if (props.target === SelectionTarget.LESSON) {
+ return manageLessonResourcesTitle$();
+ }
+ if (props.settings.selectPracticeQuiz) {
+ return selectPracticeQuizLabel$();
+ }
+ return selectResourcesDescription$({ sectionTitle: props.sectionTitle });
+ };
+ props.setTitle(getTitle());
- props.setGoBack(() => {
+ const redirectBack = () => {
const { searchTopicId } = routeQuery;
if (!isTopicFromSearchResult.value) {
return instance.proxy.$router.push({
- name: PageNames.LESSON_SELECT_RESOURCES_INDEX,
+ name:
+ props.target === SelectionTarget.LESSON
+ ? PageNames.LESSON_SELECT_RESOURCES_INDEX
+ : PageNames.QUIZ_SELECT_RESOURCES_INDEX,
});
}
+
const query = { ...instance.proxy.$route.query };
query.topicId = searchTopicId;
delete query.searchTopicId;
delete query.searchResultTopicId;
-
instance.proxy.$router.push({
- name: PageNames.LESSON_SELECT_RESOURCES_SEARCH_RESULTS,
+ name:
+ props.target === SelectionTarget.LESSON
+ ? PageNames.LESSON_SELECT_RESOURCES_SEARCH_RESULTS
+ : PageNames.QUIZ_SELECT_RESOURCES_SEARCH_RESULTS,
query,
});
- });
+ };
+ const { topicId } = instance.proxy.$route.query;
+ if (!topicId) {
+ redirectBack();
+ }
+ props.setGoBack(redirectBack);
const computedTopic = computed(() => {
if (!isTopicFromSearchResult.value) {
@@ -113,7 +167,6 @@
);
const newAncestors =
searchResultTopicIndex === -1 ? [] : topicAncestors.slice(searchResultTopicIndex);
-
return {
...props.topic,
ancestors: newAncestors,
@@ -126,6 +179,7 @@
hasMore,
fetchMore,
loadingMore,
+ SelectionTarget,
computedTopic,
isTopicFromSearchResult,
searchLabel$,
@@ -158,6 +212,11 @@
required: false,
default: () => [],
},
+ selectAllRules: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
selectedResources: {
type: Array,
required: true,
@@ -171,6 +230,47 @@
type: Boolean,
default: false,
},
+ /**
+ * The target entity for the selection.
+ * It can be either 'quiz' or 'lesson'.
+ */
+ target: {
+ type: String,
+ required: true,
+ },
+ /**
+ * The title of the section (valid just for quizzes).
+ * @type {string}
+ */
+ sectionTitle: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ /**
+ * Selection settings used for quizzes.
+ */
+ settings: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ /**
+ * Function that returns a message to be displayed based in the content
+ * passed as argument.
+ */
+ contentCardMessage: {
+ type: Function,
+ required: false,
+ default: () => '',
+ },
+ /**
+ * Function that receives a resourceId and returns a link to the resource.
+ */
+ getResourceLink: {
+ type: Function,
+ required: true,
+ },
},
computed: {
breadcrumbChannelsLink() {
@@ -179,29 +279,23 @@
return null;
}
return {
- name: PageNames.LESSON_SELECT_RESOURCES_INDEX,
+ name:
+ this.target === SelectionTarget.LESSON
+ ? PageNames.LESSON_SELECT_RESOURCES_INDEX
+ : PageNames.QUIZ_SELECT_RESOURCES_INDEX,
};
},
hideBreadcrumbs() {
return this.isTopicFromSearchResult && this.computedTopic.ancestors.length === 0;
},
},
- beforeRouteEnter(to, _, next) {
- const { topicId } = to.query;
- if (!topicId) {
- return next({
- name: PageNames.LESSON_SELECT_RESOURCES_INDEX,
- params: {
- ...to.params,
- },
- });
- }
- return next();
- },
methods: {
onSearchClick() {
this.$router.push({
- name: PageNames.LESSON_SELECT_RESOURCES_SEARCH,
+ name:
+ this.target === SelectionTarget.LESSON
+ ? PageNames.LESSON_SELECT_RESOURCES_SEARCH
+ : PageNames.QUIZ_SELECT_RESOURCES_SEARCH,
query: this.$route.query,
});
},
@@ -213,12 +307,25 @@
diff --git a/kolibri/plugins/coach/assets/src/views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection/subPages/SelectionIndex.vue b/kolibri/plugins/coach/assets/src/views/common/resourceSelection/subPages/SelectionIndex.vue
similarity index 53%
rename from kolibri/plugins/coach/assets/src/views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection/subPages/SelectionIndex.vue
rename to kolibri/plugins/coach/assets/src/views/common/resourceSelection/subPages/SelectionIndex.vue
index 838efe9da2e..322c9b8d6dc 100644
--- a/kolibri/plugins/coach/assets/src/views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection/subPages/SelectionIndex.vue
+++ b/kolibri/plugins/coach/assets/src/views/common/resourceSelection/subPages/SelectionIndex.vue
@@ -1,10 +1,41 @@
-
-
- {{ selectFromBookmarks$() }}
+
-
-
-
+
0"
+ >
+
+ import { ref } from 'vue';
import { get } from '@vueuse/core';
import Backdrop from 'kolibri/components/Backdrop';
import commonCoreStrings from 'kolibri/uiText/commonCoreStrings';
@@ -89,6 +93,7 @@
// @type {RefImpl}
windowBreakpoint,
lastFocus: null,
+ isScrolled: ref(false),
};
},
props: {
diff --git a/packages/kolibri-common/strings/enhancedQuizManagementStrings.js b/packages/kolibri-common/strings/enhancedQuizManagementStrings.js
index 83c14223065..a781c46c7f0 100644
--- a/packages/kolibri-common/strings/enhancedQuizManagementStrings.js
+++ b/packages/kolibri-common/strings/enhancedQuizManagementStrings.js
@@ -205,6 +205,42 @@ export const enhancedQuizManagementStrings = createTranslator('EnhancedQuizManag
saveAndClose: {
message: 'Save and close',
},
+ questionsSettingsLabel: {
+ message: "Questions settings for '{ sectionTitle }'",
+ context:
+ 'A title label for the section of the page that contains settings for questions selection',
+ },
+ maxNumberOfQuestionsInfo: {
+ message:
+ 'You can add up to { count, number } { count, plural, one { question } other { questions }} to this section',
+ context: 'A message that informs the user about the maximum number of questions they can add',
+ },
+ chooseQuestionsManuallyLabel: {
+ message: 'Choose questions manually',
+ context: 'A label for a checkbox that allows the user to manually select questions',
+ },
+ selectUpToNResources: {
+ message:
+ 'Select up to { count, number } { count, plural, one { resource } other { resources }}',
+ context:
+ 'A message that informs the user about the maximum number of resources they can select',
+ },
+ selectUpToNQuestions: {
+ message:
+ 'Select up to { count, number } { count, plural, one { question } other { questions }}',
+ context:
+ 'A message that informs the user about the maximum number of questions they can select',
+ },
+ maximumResourcesSelectedWarning: {
+ message: 'Maximum resources selected',
+ context:
+ 'A warning message that appears when the user has already selected the maximum number of resources',
+ },
+ maximumQuestionsSelectedWarning: {
+ message: 'Maximum questions selected',
+ context:
+ 'A warning message that appears when the user has already selected the maximum number of questions',
+ },
});
const { sectionLabel$ } = enhancedQuizManagementStrings;