diff --git a/kolibri/plugins/coach/assets/src/views/common/TruncatedItemList.vue b/kolibri/plugins/coach/assets/src/views/common/TruncatedItemList.vue index ed4430ca9e4..f27604aa0ae 100644 --- a/kolibri/plugins/coach/assets/src/views/common/TruncatedItemList.vue +++ b/kolibri/plugins/coach/assets/src/views/common/TruncatedItemList.vue @@ -5,17 +5,8 @@ v-else class="items-label" > - - {{ items[0] }} - - - {{ $tr('twoItems', { item1: items[0], item2: items[1] }) }} - - - {{ $tr('threeItems', { item1: items[0], item2: items[1], item3: items[2] }) }} - - - {{ $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 @@ + + + + + + + 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 @@ + + + + + + + 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"