- {{ $tr('manyItems', { item1: items[0], item2: items[1], count: items.length - 2 }) }}
+
+ {{ getTruncatedItemsString(items) }}
@@ -24,6 +15,8 @@
+
+
+
diff --git a/kolibri/plugins/coach/assets/src/views/common/assignments/SidePanelRecipientsSelector/LearnersSelectorSidePanel.vue b/kolibri/plugins/coach/assets/src/views/common/assignments/SidePanelRecipientsSelector/LearnersSelectorSidePanel.vue
new file mode 100644
index 00000000000..c22d8ba367b
--- /dev/null
+++ b/kolibri/plugins/coach/assets/src/views/common/assignments/SidePanelRecipientsSelector/LearnersSelectorSidePanel.vue
@@ -0,0 +1,222 @@
+
+
+
+
+
+ {{ $tr('selectGroupsAndIndividualLearnersTitle') }}
+
+
+
+
+
+ {{ coachString('groupsLabel') }}
+
+
+
+
+
+
+
+
+
+ {{ coachString('individualLearnersLabel') }}
+
+ {{ coachString('onlyShowingEnrolledLabel') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/kolibri/plugins/coach/assets/src/views/common/assignments/SidePanelRecipientsSelector/index.vue b/kolibri/plugins/coach/assets/src/views/common/assignments/SidePanelRecipientsSelector/index.vue
new file mode 100644
index 00000000000..4de2e8fe452
--- /dev/null
+++ b/kolibri/plugins/coach/assets/src/views/common/assignments/SidePanelRecipientsSelector/index.vue
@@ -0,0 +1,262 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ selectedMessage }}
+
+
+
+
+ {{ assignmentInvalidText }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/kolibri/plugins/coach/assets/src/views/common/commonCoachStrings.js b/kolibri/plugins/coach/assets/src/views/common/commonCoachStrings.js
index 2c602fff59e..06fa823fab9 100644
--- a/kolibri/plugins/coach/assets/src/views/common/commonCoachStrings.js
+++ b/kolibri/plugins/coach/assets/src/views/common/commonCoachStrings.js
@@ -200,6 +200,16 @@ const coachStrings = createTranslator('CommonCoachStrings', {
context:
'A group is a collection of learners created by a coach inside a class to help with differentiated learning. Quizzes and lessons can be assigned to individual groups as well as to the whole class.',
},
+ individualLearnersLabel: {
+ message: 'Individual learners',
+ context:
+ 'A label for a checkbox that allows the Coach to assign the quiz to individual learners who may not be in a selected group.',
+ },
+ onlyShowingEnrolledLabel: {
+ message: 'Only showing learners that are enrolled in this class',
+ context:
+ "Shows beneath 'Select individual learners' explaining that the table only includes enrolled learners.",
+ },
helpNeededLabel: {
message: 'Help needed',
context:
@@ -635,6 +645,11 @@ const coachStrings = createTranslator('CommonCoachStrings', {
context:
"In the 'Manage lesson resources' coaches can add new/remove resource material to a lesson.",
},
+ groupsAndLearnersLabel: {
+ message: 'Groups and individual learners',
+ context:
+ 'Label for the radio button that allows the coach to select groups or individual learners to assign a quiz to.',
+ },
});
// Strings for the Missing Content modals, tooltips, alerts, etc.
@@ -656,6 +671,24 @@ const MissingContentStrings = createTranslator('MissingContentStrings', {
},
});
+// Strings for showing lists of items that can be truncated
+const truncatedItemsStrings = createTranslator('TruncatedItemsStrings', {
+ twoItems: {
+ message: '{item1}, {item2}',
+ context:
+ "DO NOT TRANSLATE\nCopy the source string.\n\nFor reference: 'item' will be replaced by the name of the coach(es) in the list of classes.",
+ },
+ threeItems: {
+ message: '{item1}, {item2}, {item3}',
+ context:
+ "DO NOT TRANSLATE\nCopy the source string.\n\nFor reference: 'item' will be replaced by the name of the coach(es) in the list of classes.",
+ },
+ manyItems: {
+ message: '{item1}, {item2}, and {count, number, integer} others',
+ context: "'item' will be replaced by the name of the coach(es) in the list of classes.",
+ },
+});
+
function coachString(key, args) {
return coachStrings.$tr(key, args);
}
@@ -669,4 +702,28 @@ const coachStringsMixin = {
},
};
-export { coachString, coachStrings, coachStringsMixin };
+function getTruncatedItemsString(items) {
+ if (items.length <= 1) {
+ return items[0] || '';
+ }
+ if (items.length === 2) {
+ return truncatedItemsStrings.$tr('twoItems', {
+ item1: items[0],
+ item2: items[1],
+ });
+ }
+ if (items.length === 3) {
+ return truncatedItemsStrings.$tr('threeItems', {
+ item1: items[0],
+ item2: items[1],
+ item3: items[2],
+ });
+ }
+ return truncatedItemsStrings.$tr('manyItems', {
+ item1: items[0],
+ item2: items[1],
+ count: items.length - 2,
+ });
+}
+
+export { coachString, coachStrings, coachStringsMixin, getTruncatedItemsString };
diff --git a/kolibri/plugins/coach/assets/src/views/quizzes/CreateExamPage/index.vue b/kolibri/plugins/coach/assets/src/views/quizzes/CreateExamPage/index.vue
index c60b7065895..b160e7eac08 100644
--- a/kolibri/plugins/coach/assets/src/views/quizzes/CreateExamPage/index.vue
+++ b/kolibri/plugins/coach/assets/src/views/quizzes/CreateExamPage/index.vue
@@ -19,6 +19,7 @@
v-if="quizInitialized"
ref="detailsModal"
assignmentType="quiz"
+ :selectRecipientsWithSidePanel="true"
:assignment="quiz"
:classId="classId"
:groups="groups"
@@ -334,6 +335,10 @@
}
},
saveQuizAndRedirect(close = true) {
+ const errorText = this.$refs.detailsModal.validate();
+ if (errorText) {
+ return;
+ }
this.saveQuiz()
.then(exam => {
this.$refs.detailsModal.handleSubmitSuccess();
diff --git a/kolibri/plugins/coach/assets/src/views/quizzes/QuizSummaryPage/QuizOptionsDropdownMenu.vue b/kolibri/plugins/coach/assets/src/views/quizzes/QuizSummaryPage/QuizOptionsDropdownMenu.vue
index fb40a75fc74..68ef7bd45d0 100644
--- a/kolibri/plugins/coach/assets/src/views/quizzes/QuizSummaryPage/QuizOptionsDropdownMenu.vue
+++ b/kolibri/plugins/coach/assets/src/views/quizzes/QuizSummaryPage/QuizOptionsDropdownMenu.vue
@@ -26,26 +26,30 @@
name: 'QuizOptionsDropdownMenu',
mixins: [coachStringsMixin, commonCoreStrings],
props: {
- draft: {
- type: Boolean,
- default: false,
+ exam: {
+ type: Object,
+ required: false,
+ default: null,
},
},
computed: {
options() {
- return [
- {
- label: this.draft
- ? this.coreString('editAction')
- : this.coreString('editDetailsAction'),
- value: 'EDIT_DETAILS',
- },
+ const options = [
{
label: this.$tr('copyQuizAction'),
value: 'COPY',
},
{ label: this.coreString('deleteAction'), value: 'DELETE' },
];
+ if (!this.exam?.archive) {
+ options.unshift({
+ label: this.exam?.draft
+ ? this.coreString('editAction')
+ : this.coreString('editDetailsAction'),
+ value: 'EDIT_DETAILS',
+ });
+ }
+ return options;
},
},
$trs: {
diff --git a/kolibri/plugins/coach/assets/src/views/quizzes/QuizSummaryPage/index.vue b/kolibri/plugins/coach/assets/src/views/quizzes/QuizSummaryPage/index.vue
index c2f9348159c..7857db317cb 100644
--- a/kolibri/plugins/coach/assets/src/views/quizzes/QuizSummaryPage/index.vue
+++ b/kolibri/plugins/coach/assets/src/views/quizzes/QuizSummaryPage/index.vue
@@ -23,7 +23,7 @@
style="margin-right: 8px"
/>
diff --git a/packages/kolibri-common/components/PaginatedListContainer.vue b/packages/kolibri-common/components/PaginatedListContainer.vue
index 5facd29b654..58ab38d5a5f 100644
--- a/packages/kolibri-common/components/PaginatedListContainer.vue
+++ b/packages/kolibri-common/components/PaginatedListContainer.vue
@@ -2,16 +2,17 @@
-
+
@@ -75,6 +76,10 @@
required: false,
default: 30,
},
+ searchFieldBlock: {
+ type: Boolean,
+ required: false,
+ },
},
data() {
return {
diff --git a/packages/kolibri-common/components/SidePanelModal/index.vue b/packages/kolibri-common/components/SidePanelModal/index.vue
index 375714e843f..26b1029c8fe 100644
--- a/packages/kolibri-common/components/SidePanelModal/index.vue
+++ b/packages/kolibri-common/components/SidePanelModal/index.vue
@@ -88,8 +88,6 @@
/* Will be calculated in mounted() as it will get the height of the fixedHeader then */
// @type {RefImpl}
windowBreakpoint,
- fixedHeaderHeight: 0,
- fixedBottombarHeight: 0,
lastFocus: null,
};
},
@@ -181,11 +179,6 @@
mounted() {
const htmlTag = window.document.getElementsByTagName('html')[0];
htmlTag.style['overflow-y'] = 'hidden';
- // Gets the height of the fixed header - adds 40 to account for padding + 24 for closeButton
- this.fixedHeaderHeight = this.$refs.fixedHeader.clientHeight;
- if (this.$refs.fixedBottombar) {
- this.fixedBottombarHeight = this.$refs.fixedBottombar.clientHeight;
- }
this.$nextTick(() => {
this.$emit('shouldFocusFirstEl');
});
diff --git a/packages/kolibri/package.json b/packages/kolibri/package.json
index c00f0ff1a58..da4d73b2d34 100644
--- a/packages/kolibri/package.json
+++ b/packages/kolibri/package.json
@@ -77,7 +77,7 @@
"frame-throttle": "^3.0.0",
"intl": "^1.2.4",
"kolibri-constants": "0.2.8",
- "kolibri-design-system": "5.0.0-rc11",
+ "kolibri-design-system": "5.0.0-rc12",
"lockr": "0.8.5",
"lodash": "^4.17.21",
"path-to-regexp": "1.9.0",
diff --git a/yarn.lock b/yarn.lock
index 7e6147ae544..c79af4867cf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7791,10 +7791,10 @@ kolibri-constants@0.2.8:
resolved "https://registry.yarnpkg.com/kolibri-constants/-/kolibri-constants-0.2.8.tgz#34ad2e2b87cf132ebe8dbaa9b64dc4a7bf261f8d"
integrity sha512-ycXeK+ePw7zkiNtf+nX/yF5BO52+onoYS2V3d9HZDIvx7X6CDJPtMcypkXrK9aZ0JbWAegRFMD/lAd8q21cf4Q==
-kolibri-design-system@5.0.0-rc11:
- version "5.0.0-rc11"
- resolved "https://registry.yarnpkg.com/kolibri-design-system/-/kolibri-design-system-5.0.0-rc11.tgz#433b31d25337255708cf1bc28b86e4d619962f98"
- integrity sha512-g3mxd+Bd82al5Bf3zfO3tizItI/LeMVCUVXwifv8rtbukIa5aoWDwCTUJkdnEQCFSZR5WQ0k9mhieIAe47ebvQ==
+kolibri-design-system@5.0.0-rc12:
+ version "5.0.0-rc12"
+ resolved "https://registry.yarnpkg.com/kolibri-design-system/-/kolibri-design-system-5.0.0-rc12.tgz#326fa3446dbf597c1cdd8b08e3a4b64cb5d6ea30"
+ integrity sha512-IDbt5ADUSkvG6LyR9tUwMZz26xVcRBk1PBYCTbjNK+dJeuATp92QhTSh87sWXxlSoYV7/1DURqLA3lCefsaQnA==
dependencies:
aphrodite "https://github.com/learningequality/aphrodite/"
autosize "3.0.21"