From acda61344c7aef7bebda7e7a436b2dea4257d99b Mon Sep 17 00:00:00 2001 From: Evgeni Date: Wed, 11 Aug 2021 18:00:16 +0300 Subject: [PATCH 01/11] add bookmarks menu to the creation of a new quiz and managing a lesson --- .bash_profile | 1 + .../core/assets/src/api-resources/index.js | 4 + kolibri/core/assets/src/views/ContentIcon.vue | 9 ++ .../src/views/plan/CreateExamPage/index.vue | 149 ++++++++++++----- .../LessonResourceSelectionPage/index.vue | 152 +++++++++++++----- 5 files changed, 237 insertions(+), 78 deletions(-) create mode 100644 .bash_profile diff --git a/.bash_profile b/.bash_profile new file mode 100644 index 00000000000..6f414eb68c5 --- /dev/null +++ b/.bash_profile @@ -0,0 +1 @@ +export KOLIBRI_RUN_MODE="dev" \ No newline at end of file diff --git a/kolibri/core/assets/src/api-resources/index.js b/kolibri/core/assets/src/api-resources/index.js index 1dae54b9b59..04d31d7976c 100644 --- a/kolibri/core/assets/src/api-resources/index.js +++ b/kolibri/core/assets/src/api-resources/index.js @@ -12,6 +12,10 @@ export const DynamicNetworkLocationResource = new Resource({ name: 'dynamicnetworklocation', }); +export const BookmarksResource = new Resource({ + name: 'bookmarks', +}); + export { default as ClassroomResource } from './classroom'; export { default as ContentNodeResource } from './contentNode'; export { default as ContentNodeGranularResource } from './contentNodeGranular'; diff --git a/kolibri/core/assets/src/views/ContentIcon.vue b/kolibri/core/assets/src/views/ContentIcon.vue index 568385e7743..4d074c4231a 100644 --- a/kolibri/core/assets/src/views/ContentIcon.vue +++ b/kolibri/core/assets/src/views/ContentIcon.vue @@ -58,6 +58,13 @@ :color="color" style="top:0;" /> +

{{ $tr('chooseExercises') }}

+
+
+ +
+
+

Select from bookmarks

+
+ +
+ - - - - - -

{{ topicTitle }}

-

{{ topicDescription }}

- - - + + +

{{ topicTitle }}

+

{{ topicDescription }}

+

Select from channels

+ +
{ + this.bookmarkNodes = bookmarks; + }); + } + }, filters(newVal) { this.$router.push({ query: { ...this.$route.query, ...pickBy(newVal) }, }); }, }, + created() { + this.getBookmarks().then(data => { + this.getBookmarksData(); + }); + }, methods: { ...mapActions('examCreation', [ 'addToSelectedExercises', 'removeFromSelectedExercises', 'fetchAdditionalSearchResults', ]), + getBookmarksData() { + this.bookmarks.forEach(bookmark => { + ContentNodeResource.fetchModel({ id: bookmark.contentnode_id }).then(data => { + this.bookmarkNodes.push(data); + }); + }); + }, + getBookmarks() { + return BookmarksResource.fetchCollection().then(bookmarks => { + this.bookmarks = bookmarks; + }); + }, + lessonCardClicked() { + this.showChannels = false; + }, contentLink(content) { if (!content.is_leaf) { return { @@ -551,4 +617,13 @@ vertical-align: middle; } + .bookmarks-container { + display: flex; + align-items: center; + } + + .lesson-content-card { + width: 100%; + } + diff --git a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue index 904338c134e..3305e2b2bae 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue @@ -15,52 +15,84 @@

{{ $tr('documentTitle', { lessonName: currentLesson.title }) }}

+
+ + + +
+
+
+ +
+ + + + - - - - + +

+ {{ $tr('totalResourcesSelected', { total: workingResources.length }) }} +

+
+
- -

- {{ $tr('totalResourcesSelected', { total: workingResources.length }) }} -

-
-
+ - - - - -

{{ topicTitle }}

-

{{ topicDescription }}

+ - +

{{ topicTitle }}

+

{{ topicDescription }}

+ +
@@ -88,6 +120,11 @@ import commonCoreStrings from 'kolibri.coreVue.mixins.commonCoreStrings'; import commonCoach from '../../common'; import { LessonsPageNames } from '../../../constants/lessonsConstants'; + import { + BookmarksResource, + ContentNodeResource, + } from '../../../../../../../../kolibri/core/assets/src/api-resources/index.js'; + import LessonContentCard from './LessonContentCard/index'; import LessonsSearchBox from './SearchTools/LessonsSearchBox'; import LessonsSearchFilters from './SearchTools/LessonsSearchFilters'; import ResourceSelectionBreadcrumbs from './SearchTools/ResourceSelectionBreadcrumbs'; @@ -107,6 +144,7 @@ LessonsSearchBox, ResourceSelectionBreadcrumbs, BottomAppBar, + LessonContentCard, }, mixins: [commonCoach, commonCoreStrings], data() { @@ -120,6 +158,9 @@ isExiting: false, moreResultsState: null, resourcesChanged: false, + bookmarks: [], + bookmarkNodes: [], + showChannels: true, }; }, computed: { @@ -240,6 +281,15 @@ }, }, watch: { + $route(to, from) { + if (this.$route.params.topicId) { + ContentNodeResource.fetchCollection({ + getParams: { parent: this.$route.params.topicId }, + }).then(bookmarks => { + this.bookmarkNodes = bookmarks; + }); + } + }, workingResources(newVal, oldVal) { this.showResourcesDifferenceMessage(newVal.length - oldVal.length); this.debouncedSaveResources(); @@ -290,6 +340,11 @@ }); } }, + created() { + this.getBookmarks().then(data => { + this.getBookmarksData(); + }); + }, methods: { ...mapActions(['createSnackbar', 'clearSnackbar']), ...mapActions('lessonSummary', ['saveLessonResources', 'addToResourceCache']), @@ -298,6 +353,21 @@ addToWorkingResources: 'ADD_TO_WORKING_RESOURCES', removeFromSelectedResources: 'REMOVE_FROM_WORKING_RESOURCES', }), + getBookmarksData() { + this.bookmarks.forEach(bookmark => { + ContentNodeResource.fetchModel({ id: bookmark.contentnode_id }).then(data => { + this.bookmarkNodes.push(data); + }); + }); + }, + getBookmarks() { + return BookmarksResource.fetchCollection().then(bookmarks => { + this.bookmarks = bookmarks; + }); + }, + lessonCardClicked() { + this.showChannels = false; + }, showResourcesDifferenceMessage(difference) { if (difference === 0) { return; From fd36535f48ff16baa87109f7cd756fda24e5591d Mon Sep 17 00:00:00 2001 From: Evgeni Date: Tue, 17 Aug 2021 15:52:47 +0300 Subject: [PATCH 02/11] use translations for strings, add bookmark icon in seperate file and more fixes --- .bash_profile | 1 - kolibri/core/assets/src/constants.js | 1 + kolibri/core/assets/src/views/ContentIcon.vue | 8 ------- .../src/views/plan/CreateExamPage/index.vue | 19 +++++++-------- .../LessonContentCard/BookmarkIcon.vue | 23 +++++++++++++++++++ .../LessonContentCard/CardThumbnail.vue | 7 +++++- .../LessonResourceSelectionPage/index.vue | 13 ++++------- 7 files changed, 42 insertions(+), 30 deletions(-) delete mode 100644 .bash_profile create mode 100644 kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/LessonContentCard/BookmarkIcon.vue diff --git a/.bash_profile b/.bash_profile deleted file mode 100644 index 6f414eb68c5..00000000000 --- a/.bash_profile +++ /dev/null @@ -1 +0,0 @@ -export KOLIBRI_RUN_MODE="dev" \ No newline at end of file diff --git a/kolibri/core/assets/src/constants.js b/kolibri/core/assets/src/constants.js index a4fc476a977..b3fad90c9c7 100644 --- a/kolibri/core/assets/src/constants.js +++ b/kolibri/core/assets/src/constants.js @@ -27,6 +27,7 @@ export const ContentNodeKinds = { CLASSROOM: 'CLASSROOM', ACTIVITY: 'ACTIVITY', SLIDESHOW: 'slideshow', + BOOKMARK: 'bookmark' }; export const LearningActivities = { diff --git a/kolibri/core/assets/src/views/ContentIcon.vue b/kolibri/core/assets/src/views/ContentIcon.vue index 4c96e7c818d..3d4246c16cc 100644 --- a/kolibri/core/assets/src/views/ContentIcon.vue +++ b/kolibri/core/assets/src/views/ContentIcon.vue @@ -58,13 +58,6 @@ :color="color" style="top:0;" /> - {{ $tr('chooseExercises') }}
-
Select from bookmarks

@@ -186,11 +185,7 @@ import pickBy from 'lodash/pickBy'; import BottomAppBar from 'kolibri.coreVue.components.BottomAppBar'; import commonCoreStrings from 'kolibri.coreVue.mixins.commonCoreStrings'; - import { - BookmarksResource, - ContentNodeResource, - } from '../../../../../../../core/assets/src/api-resources/index'; - + import { BookmarksResource, ContentNodeResource } from 'kolibri.resources'; import { PageNames } from '../../../constants/'; import { MAX_QUESTIONS } from '../../../constants/examConstants'; import LessonsSearchBox from '../../plan/LessonResourceSelectionPage/SearchTools/LessonsSearchBox'; @@ -592,6 +587,8 @@ }, }, $trs: { + bookmark: 'bookmark', + bookmarks: 'Bookmarks', createNewExamLabel: { message: 'Create new quiz', context: "Title of the screen launched from the 'New quiz' button on the 'Plan' tab.", diff --git a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/LessonContentCard/BookmarkIcon.vue b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/LessonContentCard/BookmarkIcon.vue new file mode 100644 index 00000000000..7eee2cdb0fe --- /dev/null +++ b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/LessonContentCard/BookmarkIcon.vue @@ -0,0 +1,23 @@ + + + + + + + diff --git a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/LessonContentCard/CardThumbnail.vue b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/LessonContentCard/CardThumbnail.vue index e5b3ababa61..66c980a4fcc 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/LessonContentCard/CardThumbnail.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/LessonContentCard/CardThumbnail.vue @@ -4,7 +4,7 @@ class="card-thumbnail-wrapper" :style="thumbnailBackground" > - + diff --git a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue index 515379ebef0..1d36e733288 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue @@ -16,13 +16,6 @@ {{ $tr('documentTitle', { lessonName: currentLesson.title }) }}
- -
@@ -492,6 +485,8 @@ }, }, $trs: { + bookmark: 'bookmark', + bookmarks: 'Bookmarks', selectionInformation: { message: '{count, number, integer} of {total, number, integer} {total, plural, one {resource} other {resources}} selected', From 4ae9c6c555c690a3c673a683c075a56292f81adf Mon Sep 17 00:00:00 2001 From: Evgeni Date: Tue, 17 Aug 2021 16:03:12 +0300 Subject: [PATCH 03/11] remove unused code --- .../coach/assets/src/views/plan/CreateExamPage/index.vue | 4 ++-- .../src/views/plan/LessonResourceSelectionPage/index.vue | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue index 079194184fe..f3d7b368c48 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue @@ -391,7 +391,7 @@ }, }, watch: { - $route(to, from) { + $route() { if (this.$route.params.topicId) { ContentNodeResource.fetchCollection({ getParams: { parent: this.$route.params.topicId }, @@ -407,7 +407,7 @@ }, }, created() { - this.getBookmarks().then(data => { + this.getBookmarks().then(() => { this.getBookmarksData(); }); }, diff --git a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue index 1d36e733288..5b9e50cad79 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue @@ -274,7 +274,7 @@ }, }, watch: { - $route(to, from) { + $route() { if (this.$route.params.topicId) { ContentNodeResource.fetchCollection({ getParams: { parent: this.$route.params.topicId }, @@ -334,7 +334,7 @@ } }, created() { - this.getBookmarks().then(data => { + this.getBookmarks().then(() => { this.getBookmarksData(); }); }, From babf0451089705737121bd5228231cc2d2734703 Mon Sep 17 00:00:00 2001 From: Evgeni Date: Fri, 20 Aug 2021 15:57:11 +0300 Subject: [PATCH 04/11] move the data fetching logic into route handlers --- .../coach/assets/src/constants/index.js | 2 + .../src/modules/examCreation/handlers.js | 60 ++++++++++++++++++- .../assets/src/modules/examCreation/index.js | 4 ++ .../coach/assets/src/routes/planExamRoutes.js | 18 ++++++ .../src/views/plan/CreateExamPage/index.vue | 47 +++++++++++---- 5 files changed, 119 insertions(+), 12 deletions(-) diff --git a/kolibri/plugins/coach/assets/src/constants/index.js b/kolibri/plugins/coach/assets/src/constants/index.js index 8db071bb83b..a1d6121a8ff 100644 --- a/kolibri/plugins/coach/assets/src/constants/index.js +++ b/kolibri/plugins/coach/assets/src/constants/index.js @@ -10,6 +10,8 @@ export const PageNames = { EXAM_CREATION_SELECT_CHANNEL_QUIZ_TOPIC: 'EXAM_CREATION_SELECT_CHANNEL_QUIZ_TOPIC', EXAM_CREATION_CHANNEL_QUIZ_PREVIEW: 'EXAM_CREATION_CHANNEL_QUIZ_PREVIEW', EXAM_CREATION_TOPIC: 'EXAM_CREATION_TOPIC', + EXAM_CREATION_BOOKMARKS: 'EXAM_CREATION_BOOKMARKS', + EXAM_CREATION_BOOKMARKS_MAIN: 'EXAM_CREATION_BOOKMARKS_MAIN', EXAM_CREATION_PREVIEW: 'EXAM_CREATION_PREVIEW', EXAM_CREATION_SEARCH: 'EXAM_CREATION_SEARCH', EXAM_CREATION_QUESTION_SELECTION: 'EXAM_CREATION_QUESTION_SELECTION', diff --git a/kolibri/plugins/coach/assets/src/modules/examCreation/handlers.js b/kolibri/plugins/coach/assets/src/modules/examCreation/handlers.js index 039c4f17fa3..5e887286a28 100644 --- a/kolibri/plugins/coach/assets/src/modules/examCreation/handlers.js +++ b/kolibri/plugins/coach/assets/src/modules/examCreation/handlers.js @@ -1,17 +1,23 @@ import pickBy from 'lodash/pickBy'; import uniq from 'lodash/uniq'; import { ContentNodeKinds } from 'kolibri.coreVue.vuex.constants'; -import { ContentNodeResource, ContentNodeSearchResource, ChannelResource } from 'kolibri.resources'; +import { + ContentNodeResource, + BookmarksResource, + ContentNodeSearchResource, + ChannelResource, +} from 'kolibri.resources'; import { assessmentMetaDataState } from 'kolibri.coreVue.vuex.mappers'; import router from 'kolibri.coreVue.router'; import { PageNames } from '../../constants'; import { filterAndAnnotateContentList, fetchChannelQuizzes } from './actions'; function showExamCreationPage(store, params) { - const { contentList, pageName, ancestors = [], searchResults = null } = params; + const { contentList, bookmarksList, pageName, ancestors = [], searchResults = null } = params; return store.dispatch('loading').then(() => { store.commit('examCreation/SET_ANCESTORS', ancestors); store.commit('examCreation/SET_CONTENT_LIST', contentList); + store.commit('examCreation/SET_BOOKMARKS_LIST', bookmarksList); if (searchResults) { store.commit('examCreation/SET_SEARCH_RESULTS', searchResults); } @@ -118,6 +124,56 @@ export function showExamCreationTopicPage(store, params) { }); }); } +export function showExamCreationBookamrksPage(store, params) { + return store.dispatch('loading').then(() => { + const { topicId } = params; + const topicNodePromise = ContentNodeResource.fetchModel({ id: topicId }); + const childNodesPromise = ContentNodeResource.fetchCollection({ + getParams: { + parent: topicId, + kind_in: [ContentNodeKinds.TOPIC, ContentNodeKinds.VIDEO, ContentNodeKinds.EXERCISE], + }, + }); + const loadRequirements = [topicNodePromise, childNodesPromise]; + + return Promise.all(loadRequirements).then(([topicNode, childNodes]) => { + return filterAndAnnotateContentList(childNodes).then(() => { + store.commit('SET_TOOLBAR_ROUTE', { + name: PageNames.EXAMS, + }); + return showExamCreationPage(store, { + classId: params.classId, + bookmarksList: childNodes, + pageName: PageNames.EXAM_CREATION_BOOKMARKS, + ancestors: [...topicNode.ancestors, topicNode], + }); + }); + }); + }); +} +export function showExamCreationAllBookmarks(store) { + return store.dispatch('loading').then(() => { + let dataArr = []; + getBookmarks() + .then(bookmarks => { + bookmarks.forEach(bookmark => { + ContentNodeResource.fetchModel({ id: bookmark.contentnode_id }).then(data => { + dataArr.push(data); + }); + }); + }) + .then(() => { + return showExamCreationPage(store, { + bookmarksList: dataArr, + }); + }); + }); +} +function getBookmarks() { + return BookmarksResource.fetchCollection().then(bookmarks => { + return bookmarks; + }); +} export function showExamCreationPreviewPage(store, params, query = {}) { const { classId, contentId } = params; diff --git a/kolibri/plugins/coach/assets/src/modules/examCreation/index.js b/kolibri/plugins/coach/assets/src/modules/examCreation/index.js index ff31072b95d..2e829077c1b 100644 --- a/kolibri/plugins/coach/assets/src/modules/examCreation/index.js +++ b/kolibri/plugins/coach/assets/src/modules/examCreation/index.js @@ -11,6 +11,7 @@ function defaultState() { numberOfQuestions: 10, seed: getRandomInt(), // consistent seed is used for question selection contentList: [], + bookmarksList: [], selectedExercises: {}, availableQuestions: 0, searchResults: { @@ -70,6 +71,9 @@ export default { SET_CONTENT_LIST(state, contentList) { state.contentList = contentList; }, + SET_BOOKMARKS_LIST(state, bookmarksList) { + state.bookmarksList = bookmarksList; + }, ADD_TO_SELECTED_EXERCISES(state, exercises) { state.selectedExercises = Object.assign( {}, diff --git a/kolibri/plugins/coach/assets/src/routes/planExamRoutes.js b/kolibri/plugins/coach/assets/src/routes/planExamRoutes.js index 80dd8eab8e4..7ac2ad468e2 100644 --- a/kolibri/plugins/coach/assets/src/routes/planExamRoutes.js +++ b/kolibri/plugins/coach/assets/src/routes/planExamRoutes.js @@ -3,6 +3,8 @@ import { PageNames } from '../constants'; import { showExamCreationRootPage, showExamCreationTopicPage, + showExamCreationBookamrksPage, + showExamCreationAllBookmarks, showExamCreationSearchPage, showExamCreationQuestionSelectionPage, showExamCreationPreviewPage, @@ -64,6 +66,22 @@ export default [ showExamCreationTopicPage(store, toRoute.params); }, }, + { + name: PageNames.EXAM_CREATION_BOOKMARKS, + path: '/:classId/plan/quizzes/new/bookmark/:topicId', + component: CreateExamPage, + handler: toRoute => { + showExamCreationBookamrksPage(store, toRoute.params); + }, + }, + { + name: PageNames.EXAM_CREATION_BOOKMARKS_MAIN, + path: '/:classId/plan/quizzes/new/bookmarks', + component: CreateExamPage, + handler: toRoute => { + showExamCreationAllBookmarks(store, toRoute.params); + }, + }, { name: PageNames.EXAM_CREATION_SEARCH, path: '/:classId/plan/quizzes/new/search/:searchTerm', diff --git a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue index f3d7b368c48..6b0117cccd5 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue @@ -83,16 +83,14 @@

{{ $tr('chooseExercises') }}

{ - this.getBookmarksData(); - }); - }, methods: { ...mapActions('examCreation', [ 'addToSelectedExercises', @@ -432,6 +429,36 @@ lessonCardClicked() { this.showChannels = false; }, + getBookmarksLink() { + return { + name: PageNames.EXAM_CREATION_BOOKMARKS_MAIN, + }; + }, + bookmarksLink(content) { + if (!content.is_leaf) { + return { + name: PageNames.EXAM_CREATION_BOOKMARKS, + params: { + classId: this.classId, + topicId: content.id, + }, + }; + } + const { query } = this.$route; + return { + name: PageNames.EXAM_CREATION_PREVIEW, + params: { + classId: this.classId, + contentId: content.id, + }, + query: { + ...query, + ...pickBy({ + searchTerm: this.$route.params.searchTerm, + }), + }, + }; + }, contentLink(content) { if (!content.is_leaf) { return { From 5cd86c4009927a69831942efdd16b8bc4f429dfb Mon Sep 17 00:00:00 2001 From: Evgeni Date: Fri, 20 Aug 2021 16:27:29 +0300 Subject: [PATCH 05/11] remove unused code --- kolibri/core/assets/src/constants.js | 2 +- .../src/views/plan/CreateExamPage/index.vue | 26 +------------------ 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/kolibri/core/assets/src/constants.js b/kolibri/core/assets/src/constants.js index b3fad90c9c7..5f4d014a8dc 100644 --- a/kolibri/core/assets/src/constants.js +++ b/kolibri/core/assets/src/constants.js @@ -27,7 +27,7 @@ export const ContentNodeKinds = { CLASSROOM: 'CLASSROOM', ACTIVITY: 'ACTIVITY', SLIDESHOW: 'slideshow', - BOOKMARK: 'bookmark' + BOOKMARK: 'bookmark', }; export const LearningActivities = { diff --git a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue index 6b0117cccd5..a4015545b88 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue @@ -103,7 +103,7 @@ :title="$tr('bookmarks')" :link="getBookmarksLink()" :kind="$tr('bookmark')" - :description="this.bookmarks.length + ' resources'" + :description="'0 resources'" :isLeaf="false" />
@@ -183,7 +183,6 @@ import pickBy from 'lodash/pickBy'; import BottomAppBar from 'kolibri.coreVue.components.BottomAppBar'; import commonCoreStrings from 'kolibri.coreVue.mixins.commonCoreStrings'; - import { BookmarksResource, ContentNodeResource } from 'kolibri.resources'; import { PageNames } from '../../../constants/'; import { MAX_QUESTIONS } from '../../../constants/examConstants'; import LessonsSearchBox from '../../plan/LessonResourceSelectionPage/SearchTools/LessonsSearchBox'; @@ -218,8 +217,6 @@ }, numQuestionsBlurred: false, showChannels: true, - bookmarks: [], - bookmarkNodes: [], }; }, computed: { @@ -393,15 +390,6 @@ }, }, watch: { - $route() { - if (this.$route.params.topicId) { - ContentNodeResource.fetchCollection({ - getParams: { parent: this.$route.params.topicId }, - }).then(bookmarks => { - this.bookmarkNodes = bookmarks; - }); - } - }, filters(newVal) { this.$router.push({ query: { ...this.$route.query, ...pickBy(newVal) }, @@ -414,18 +402,6 @@ 'removeFromSelectedExercises', 'fetchAdditionalSearchResults', ]), - getBookmarksData() { - this.bookmarks.forEach(bookmark => { - ContentNodeResource.fetchModel({ id: bookmark.contentnode_id }).then(data => { - this.bookmarkNodes.push(data); - }); - }); - }, - getBookmarks() { - return BookmarksResource.fetchCollection().then(bookmarks => { - this.bookmarks = bookmarks; - }); - }, lessonCardClicked() { this.showChannels = false; }, From 2615b25d95dd5d3b125206d58d5623f21b477419 Mon Sep 17 00:00:00 2001 From: Evgeni Date: Mon, 23 Aug 2021 15:35:24 +0300 Subject: [PATCH 06/11] get the bookmarks count --- .../assets/src/views/plan/CreateExamPage/index.vue | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue index a4015545b88..4695d8e8bfd 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue @@ -103,7 +103,7 @@ :title="$tr('bookmarks')" :link="getBookmarksLink()" :kind="$tr('bookmark')" - :description="'0 resources'" + :description="this.bookmarksCount + $tr('resources')" :isLeaf="false" />
@@ -183,6 +183,7 @@ import pickBy from 'lodash/pickBy'; import BottomAppBar from 'kolibri.coreVue.components.BottomAppBar'; import commonCoreStrings from 'kolibri.coreVue.mixins.commonCoreStrings'; + import { BookmarksResource } from 'kolibri.resources'; import { PageNames } from '../../../constants/'; import { MAX_QUESTIONS } from '../../../constants/examConstants'; import LessonsSearchBox from '../../plan/LessonResourceSelectionPage/SearchTools/LessonsSearchBox'; @@ -217,6 +218,7 @@ }, numQuestionsBlurred: false, showChannels: true, + bookmarksCount: 0 }; }, computed: { @@ -396,6 +398,11 @@ }); }, }, + created() { + BookmarksResource.fetchCollection().then(bookmarks => { + this.bookmarksCount = bookmarks.length + }); + }, methods: { ...mapActions('examCreation', [ 'addToSelectedExercises', @@ -590,6 +597,7 @@ }, }, $trs: { + resources: ' resources', bookmark: 'bookmark', bookmarks: 'Bookmarks', createNewExamLabel: { From c6ef999f90dec97357035a72ce85d2548fe54995 Mon Sep 17 00:00:00 2001 From: Evgeni Date: Thu, 26 Aug 2021 19:02:48 +0300 Subject: [PATCH 07/11] fix issues and add new logic to lesson resources component --- .../assets/src/constants/lessonsConstants.js | 2 + .../src/modules/examCreation/handlers.js | 31 ++-- .../src/modules/lessonResources/handlers.js | 172 ++++++++++++------ .../src/modules/lessonResources/index.js | 4 + .../coach/assets/src/routes/planExamRoutes.js | 4 +- .../assets/src/routes/planLessonsRoutes.js | 29 +++ .../src/views/plan/CreateExamPage/index.vue | 11 +- .../LessonResourceSelectionPage/index.vue | 81 ++++++--- 8 files changed, 221 insertions(+), 113 deletions(-) diff --git a/kolibri/plugins/coach/assets/src/constants/lessonsConstants.js b/kolibri/plugins/coach/assets/src/constants/lessonsConstants.js index 0f0309abdd7..ef498a4664e 100644 --- a/kolibri/plugins/coach/assets/src/constants/lessonsConstants.js +++ b/kolibri/plugins/coach/assets/src/constants/lessonsConstants.js @@ -10,6 +10,8 @@ export const LessonsPageNames = { SELECTION_SEARCH: 'SELECTION_SEARCH', SELECTION_CONTENT_PREVIEW: 'SELECTION_CONTENT_PREVIEW', // exclusively a route name CONTENT_PREVIEW: 'CONTENT_PREVIEW', + LESSON_SELECTION_BOOKMARKS: 'LESSON_SELECTION_BOOKMARKS', + LESSON_SELECTION_BOOKMARKS_MAIN: 'LESSON_SELECTION_BOOKMARKS_MAIN', }; export const CollectionTypes = { diff --git a/kolibri/plugins/coach/assets/src/modules/examCreation/handlers.js b/kolibri/plugins/coach/assets/src/modules/examCreation/handlers.js index 5e887286a28..633e737290b 100644 --- a/kolibri/plugins/coach/assets/src/modules/examCreation/handlers.js +++ b/kolibri/plugins/coach/assets/src/modules/examCreation/handlers.js @@ -124,7 +124,7 @@ export function showExamCreationTopicPage(store, params) { }); }); } -export function showExamCreationBookamrksPage(store, params) { +export function showExamCreationBookmarksPage(store, params) { return store.dispatch('loading').then(() => { const { topicId } = params; const topicNodePromise = ContentNodeResource.fetchModel({ id: topicId }); @@ -153,26 +153,23 @@ export function showExamCreationBookamrksPage(store, params) { } export function showExamCreationAllBookmarks(store) { return store.dispatch('loading').then(() => { - let dataArr = []; - getBookmarks() - .then(bookmarks => { - bookmarks.forEach(bookmark => { - ContentNodeResource.fetchModel({ id: bookmark.contentnode_id }).then(data => { - dataArr.push(data); - }); - }); - }) - .then(() => { - return showExamCreationPage(store, { - bookmarksList: dataArr, - }); + getBookmarks().then(bookmarks => { + return showExamCreationPage(store, { + bookmarksList: bookmarks, }); + }); }); } function getBookmarks() { - return BookmarksResource.fetchCollection().then(bookmarks => { - return bookmarks; - }); + return BookmarksResource.fetchCollection() + .then(bookmarks => { + return bookmarks.map(bookmark => { + return ContentNodeResource.fetchModel({ id: bookmark.contentnode_id }); + }); + }) + .then(bookmarkPromises => { + return Promise.all(bookmarkPromises); + }); } export function showExamCreationPreviewPage(store, params, query = {}) { diff --git a/kolibri/plugins/coach/assets/src/modules/lessonResources/handlers.js b/kolibri/plugins/coach/assets/src/modules/lessonResources/handlers.js index a8ce0f73666..86696199ccd 100644 --- a/kolibri/plugins/coach/assets/src/modules/lessonResources/handlers.js +++ b/kolibri/plugins/coach/assets/src/modules/lessonResources/handlers.js @@ -1,12 +1,16 @@ import pickBy from 'lodash/pickBy'; import { assessmentMetaDataState } from 'kolibri.coreVue.vuex.mappers'; -import { ContentNodeResource, ContentNodeSearchResource } from 'kolibri.resources'; +import { + BookmarksResource, + ContentNodeResource, + ContentNodeSearchResource, +} from 'kolibri.resources'; import { ContentNodeKinds } from 'kolibri.coreVue.vuex.constants'; import { getContentNodeThumbnail } from 'kolibri.utils.contentNode'; import { LessonsPageNames } from '../../constants/lessonsConstants'; function showResourceSelectionPage(store, params) { - const { lessonId, contentList, pageName, ancestors = [] } = params; + const { lessonId, contentList, pageName, bookmarksList, ancestors = [] } = params; const pendingSelections = store.state.lessonSummary.workingResources || []; const cache = store.state.lessonSummary.resourceCache || {}; const lessonSummaryState = { @@ -18,73 +22,77 @@ function showResourceSelectionPage(store, params) { return store.dispatch('loading').then(() => { store.commit('SET_TOOLBAR_ROUTE', {}); store.commit('lessonSummary/SET_STATE', lessonSummaryState); + store.commit('lessonSummary/resources/SET_BOOKMARKS_LIST', bookmarksList); store.commit('lessonSummary/resources/SET_STATE', { contentList: [], ancestors: [], }); + store.dispatch('notLoading'); - const loadRequirements = [store.dispatch('lessonSummary/updateCurrentLesson', lessonId)]; - return Promise.all(loadRequirements).then(([currentLesson]) => { - // TODO make a state mapper - // contains selections that were commited to server prior to opening this page - if (!pendingSelections.length) { - store.commit('lessonSummary/SET_WORKING_RESOURCES', currentLesson.resources); - } - - if (ancestors.length) { - store.commit('lessonSummary/resources/SET_ANCESTORS', ancestors); - } - - const ancestorCounts = {}; - - let resourceAncestors; - - resourceAncestors = store.state.lessonSummary.workingResources.map( - resource => (cache[resource.contentnode_id] || {}).ancestors || [] - ); - // store ancestor ids to get their descendants later - const ancestorIds = new Set(); - - resourceAncestors.forEach(ancestorArray => - ancestorArray.forEach(ancestor => { - ancestorIds.add(ancestor.id); - if (ancestorCounts[ancestor.id]) { - ancestorCounts[ancestor.id].count++; - } else { - ancestorCounts[ancestor.id] = {}; - // total number of working/added resources - ancestorCounts[ancestor.id].count = 1; - // total number of descendants - ancestorCounts[ancestor.id].total = 0; + if (lessonId) { + const loadRequirements = [store.dispatch('lessonSummary/updateCurrentLesson', lessonId)]; + return Promise.all(loadRequirements).then(([currentLesson]) => { + // TODO make a state mapper + // contains selections that were commited to server prior to opening this page + if (!pendingSelections.length) { + store.commit('lessonSummary/SET_WORKING_RESOURCES', currentLesson.resources); + } + + if (ancestors.length) { + store.commit('lessonSummary/resources/SET_ANCESTORS', ancestors); + } + + const ancestorCounts = {}; + + let resourceAncestors; + + resourceAncestors = store.state.lessonSummary.workingResources.map( + resource => (cache[resource.contentnode_id] || {}).ancestors || [] + ); + // store ancestor ids to get their descendants later + const ancestorIds = new Set(); + + resourceAncestors.forEach(ancestorArray => + ancestorArray.forEach(ancestor => { + ancestorIds.add(ancestor.id); + if (ancestorCounts[ancestor.id]) { + ancestorCounts[ancestor.id].count++; + } else { + ancestorCounts[ancestor.id] = {}; + // total number of working/added resources + ancestorCounts[ancestor.id].count = 1; + // total number of descendants + ancestorCounts[ancestor.id].total = 0; + } + }) + ); + ContentNodeResource.fetchDescendants(Array.from(ancestorIds)).then(nodes => { + nodes.data.forEach(node => { + // exclude topics from total resource calculation + if (node.kind !== ContentNodeKinds.TOPIC) { + ancestorCounts[node.ancestor_id].total++; + } + }); + store.commit('lessonSummary/resources/SET_ANCESTOR_COUNTS', ancestorCounts); + // carry pendingSelections over from other interactions in this modal + store.commit('lessonSummary/resources/SET_CONTENT_LIST', contentList); + if (params.searchResults) { + store.commit('lessonSummary/resources/SET_SEARCH_RESULTS', params.searchResults); } - }) - ); - ContentNodeResource.fetchDescendants(Array.from(ancestorIds)).then(nodes => { - nodes.data.forEach(node => { - // exclude topics from total resource calculation - if (node.kind !== ContentNodeKinds.TOPIC) { - ancestorCounts[node.ancestor_id].total++; + store.commit('SET_PAGE_NAME', pageName); + if (pageName === LessonsPageNames.SELECTION_SEARCH) { + store.commit('SET_TOOLBAR_ROUTE', { + name: LessonsPageNames.SELECTION_ROOT, + }); + } else { + store.commit('SET_TOOLBAR_ROUTE', { + name: LessonsPageNames.SUMMARY, + }); } + store.dispatch('notLoading'); }); - store.commit('lessonSummary/resources/SET_ANCESTOR_COUNTS', ancestorCounts); - // carry pendingSelections over from other interactions in this modal - store.commit('lessonSummary/resources/SET_CONTENT_LIST', contentList); - if (params.searchResults) { - store.commit('lessonSummary/resources/SET_SEARCH_RESULTS', params.searchResults); - } - store.commit('SET_PAGE_NAME', pageName); - if (pageName === LessonsPageNames.SELECTION_SEARCH) { - store.commit('SET_TOOLBAR_ROUTE', { - name: LessonsPageNames.SELECTION_ROOT, - }); - } else { - store.commit('SET_TOOLBAR_ROUTE', { - name: LessonsPageNames.SUMMARY, - }); - } - store.dispatch('notLoading'); }); - }); + } }); } @@ -132,7 +140,50 @@ export function showLessonResourceSelectionTopicPage(store, params) { }); }); } +export function showLessonResourceBookmarks(store, params) { + return store.dispatch('loading').then(() => { + const { topicId } = params; + const loadRequirements = [ + ContentNodeResource.fetchModel({ id: topicId }), + ContentNodeResource.fetchCollection({ getParams: { parent: topicId } }), + ]; + + return Promise.all(loadRequirements).then(([topicNode, childNodes]) => { + const topicContentList = childNodes.map(node => { + return { ...node, thumbnail: getContentNodeThumbnail(node) }; + }); + return showResourceSelectionPage(store, { + classId: params.classId, + lessonId: params.lessonId, + bookmarksList: topicContentList, + pageName: LessonsPageNames.SELECTION, + ancestors: [...topicNode.ancestors, topicNode], + }); + }); + }); +} +export function showLessonResourceBookmarksMain(store) { + return store.dispatch('loading').then(() => { + getBookmarks().then(bookmarks => { + console.log(111111, bookmarks); + return showResourceSelectionPage(store, { + bookmarksList: bookmarks, + }); + }); + }); +} +function getBookmarks() { + return BookmarksResource.fetchCollection() + .then(bookmarks => { + return bookmarks.map(bookmark => { + return ContentNodeResource.fetchModel({ id: bookmark.contentnode_id }); + }); + }) + .then(bookmarkPromises => { + return Promise.all(bookmarkPromises); + }); +} export function showLessonResourceContentPreview(store, params) { const { classId, lessonId, contentId } = params; return store.dispatch('loading').then(() => { @@ -143,6 +194,7 @@ export function showLessonResourceContentPreview(store, params) { } export function showLessonSelectionContentPreview(store, params, query = {}) { + console.log('in prview', params); const { classId, lessonId, contentId } = params; return store.dispatch('loading').then(() => { const pendingSelections = store.state.lessonSummary.workingResources || []; diff --git a/kolibri/plugins/coach/assets/src/modules/lessonResources/index.js b/kolibri/plugins/coach/assets/src/modules/lessonResources/index.js index 10142af60af..84934c90b41 100644 --- a/kolibri/plugins/coach/assets/src/modules/lessonResources/index.js +++ b/kolibri/plugins/coach/assets/src/modules/lessonResources/index.js @@ -4,6 +4,7 @@ import * as actions from './actions'; function defaultState() { return { + bookmarksList: [], ancestorCounts: {}, ancestors: [], contentList: [], @@ -40,6 +41,9 @@ export default { SET_ANCESTORS(state, ancestors) { state.ancestors = [...ancestors]; }, + SET_BOOKMARKS_LIST(state, bookmarks) { + state.bookmarksList = bookmarks; + }, SET_ANCESTOR_COUNTS(state, ancestorCountsObject) { state.ancestorCounts = ancestorCountsObject; }, diff --git a/kolibri/plugins/coach/assets/src/routes/planExamRoutes.js b/kolibri/plugins/coach/assets/src/routes/planExamRoutes.js index 7ac2ad468e2..10ba0135b17 100644 --- a/kolibri/plugins/coach/assets/src/routes/planExamRoutes.js +++ b/kolibri/plugins/coach/assets/src/routes/planExamRoutes.js @@ -3,7 +3,7 @@ import { PageNames } from '../constants'; import { showExamCreationRootPage, showExamCreationTopicPage, - showExamCreationBookamrksPage, + showExamCreationBookmarksPage, showExamCreationAllBookmarks, showExamCreationSearchPage, showExamCreationQuestionSelectionPage, @@ -71,7 +71,7 @@ export default [ path: '/:classId/plan/quizzes/new/bookmark/:topicId', component: CreateExamPage, handler: toRoute => { - showExamCreationBookamrksPage(store, toRoute.params); + showExamCreationBookmarksPage(store, toRoute.params); }, }, { diff --git a/kolibri/plugins/coach/assets/src/routes/planLessonsRoutes.js b/kolibri/plugins/coach/assets/src/routes/planLessonsRoutes.js index a0de5855a2c..ccb25166230 100644 --- a/kolibri/plugins/coach/assets/src/routes/planLessonsRoutes.js +++ b/kolibri/plugins/coach/assets/src/routes/planLessonsRoutes.js @@ -5,6 +5,8 @@ import { showLessonResourceSelectionTopicPage, showLessonSelectionContentPreview, showLessonResourceSearchPage, + showLessonResourceBookmarks, + showLessonResourceBookmarksMain, } from '../modules/lessonResources/handlers'; import { showLessonsRootPage } from '../modules/lessonsRoot/handlers'; import { showLessonSummaryPage } from '../modules/lessonSummary/handlers'; @@ -101,6 +103,33 @@ export default [ showLessonResourceSearchPage(store, toRoute.params, toRoute.query); }, }, + { + name: LessonsPageNames.LESSON_SELECTION_BOOKMARKS, + path: path(CLASS, LESSON, SELECTION, TOPIC), + component: LessonResourceSelectionPage, + handler(toRoute, fromRoute) { + let preHandlerPromise; + if (fromRoute.name === LessonsPageNames.SELECTION_CONTENT_PREVIEW) { + preHandlerPromise = store.dispatch('lessonSummary/saveLessonResources', { + lessonId: toRoute.params.lessonId, + resources: store.state.lessonSummary.workingResources, + }); + } else { + preHandlerPromise = Promise.resolve(); + } + preHandlerPromise.then(() => { + showLessonResourceBookmarks(store, toRoute.params, toRoute.query); + }); + }, + }, + { + name: LessonsPageNames.LESSON_SELECTION_BOOKMARKS_MAIN, + path: path(CLASS, LESSON, SELECTION), + component: LessonResourceSelectionPage, + handler(toRoute) { + showLessonResourceBookmarksMain(store, toRoute.params, toRoute.query); + }, + }, { name: LessonsPageNames.SELECTION_CONTENT_PREVIEW, path: path(CLASS, LESSON, SELECTION, PREVIEW), diff --git a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue index 4695d8e8bfd..e299885c96f 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue @@ -103,7 +103,7 @@ :title="$tr('bookmarks')" :link="getBookmarksLink()" :kind="$tr('bookmark')" - :description="this.bookmarksCount + $tr('resources')" + :description="$tr('resources', { count: this.bookmarksCount })" :isLeaf="false" />
@@ -218,7 +218,7 @@ }, numQuestionsBlurred: false, showChannels: true, - bookmarksCount: 0 + bookmarksCount: 0, }; }, computed: { @@ -400,7 +400,7 @@ }, created() { BookmarksResource.fetchCollection().then(bookmarks => { - this.bookmarksCount = bookmarks.length + this.bookmarksCount = bookmarks.length; }); }, methods: { @@ -519,7 +519,8 @@ }, toggleSelected({ content, checked }) { let exercises; - const contentNode = this.contentList.find(item => item.id === content.id); + const list = this.contentList ? this.contentList: this.bookmarksList + const contentNode = list.find(item => item.id === content.id); const isTopic = contentNode.kind === ContentNodeKinds.TOPIC; if (checked && isTopic) { this.showError = false; @@ -597,7 +598,7 @@ }, }, $trs: { - resources: ' resources', + resources: '{count} {count, plural, one {resource} other {resources}}', bookmark: 'bookmark', bookmarks: 'Bookmarks', createNewExamLabel: { diff --git a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue index 5b9e50cad79..21943334066 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue @@ -17,11 +17,10 @@
@@ -151,8 +150,7 @@ isExiting: false, moreResultsState: null, resourcesChanged: false, - bookmarks: [], - bookmarkNodes: [], + bookmarksCount: 0, showChannels: true, }; }, @@ -163,6 +161,7 @@ ...mapState('lessonSummary/resources', [ 'ancestorCounts', 'contentList', + 'bookmarksList', 'searchResults', 'ancestors', ]), @@ -176,12 +175,16 @@ pageTitle() { return this.$tr('documentTitle', { lessonName: this.currentLesson.title }); }, + bookmarksContentList() { + return this.bookmarksList ? this.bookmarksList : []; + }, filteredContentList() { const { role } = this.filters; if (!this.inSearchMode) { return this.contentList; } - return this.contentList.filter(contentNode => { + const list = this.contentList ? this.contentList : this.bookmarksList; + return list.filter(contentNode => { let passesFilters = true; if (role === 'nonCoach') { passesFilters = passesFilters && contentNode.num_coach_contents === 0; @@ -202,7 +205,10 @@ return this.$route.params.searchTerm || ''; }, routerParams() { - return { classId: this.classId, lessonId: this.lessonId }; + return { + classId: this.classId, + lessonId: this.lessonId ? this.lessonId : this.$route.params.lessonId, + }; }, debouncedSaveResources() { return debounce(this.saveResources, 1000); @@ -231,7 +237,8 @@ }, addableContent() { // Content in the topic that can be added if 'Select All' is clicked - return this.contentList.filter( + const list = this.contentList ? this.contentList : this.bookmarksList; + return list.filter( content => !this.contentIsDirectoryKind(content) && !this.contentIsInLesson(content) ); }, @@ -274,15 +281,6 @@ }, }, watch: { - $route() { - if (this.$route.params.topicId) { - ContentNodeResource.fetchCollection({ - getParams: { parent: this.$route.params.topicId }, - }).then(bookmarks => { - this.bookmarkNodes = bookmarks; - }); - } - }, workingResources(newVal, oldVal) { this.showResourcesDifferenceMessage(newVal.length - oldVal.length); this.debouncedSaveResources(); @@ -334,8 +332,8 @@ } }, created() { - this.getBookmarks().then(() => { - this.getBookmarksData(); + this.getBookmarks().then(count => { + this.bookmarksCount = count; }); }, methods: { @@ -346,18 +344,16 @@ addToWorkingResources: 'ADD_TO_WORKING_RESOURCES', removeFromSelectedResources: 'REMOVE_FROM_WORKING_RESOURCES', }), - getBookmarksData() { - this.bookmarks.forEach(bookmark => { - ContentNodeResource.fetchModel({ id: bookmark.contentnode_id }).then(data => { - this.bookmarkNodes.push(data); - }); - }); - }, getBookmarks() { return BookmarksResource.fetchCollection().then(bookmarks => { - this.bookmarks = bookmarks; + return bookmarks.length; }); }, + getBookmarksLink() { + return { + name: LessonsPageNames.LESSON_SELECTION_BOOKMARKS_MAIN, + }; + }, lessonCardClicked() { this.showChannels = false; }, @@ -402,6 +398,32 @@ topicListingLink({ topicId }) { return this.$router.getRoute(LessonsPageNames.SELECTION, { topicId }, this.$route.query); }, + bookmarkListingLink({ topicId }) { + return this.$router.getRoute( + LessonsPageNames.LESSON_SELECTION_BOOKMARKS, + { topicId }, + this.$route.query + ); + }, + bookmarkLink(content) { + if (this.contentIsDirectoryKind(content)) { + return this.bookmarkListingLink({ ...this.routerParams, topicId: content.id }); + } + const { query } = this.$route; + return { + name: LessonsPageNames.SELECTION_CONTENT_PREVIEW, + params: { + ...this.routerParams, + contentId: content.id, + }, + query: { + ...query, + ...pickBy({ + searchTerm: this.$route.params.searchTerm, + }), + }, + }; + }, contentLink(content) { if (this.contentIsDirectoryKind(content)) { return this.topicListingLink({ ...this.routerParams, topicId: content.id }); @@ -485,6 +507,7 @@ }, }, $trs: { + resources: '{count} {count, plural, one {resource} other {resources}}', bookmark: 'bookmark', bookmarks: 'Bookmarks', selectionInformation: { From 09ffb86061a596075806869cc5349ac0babfe251 Mon Sep 17 00:00:00 2001 From: Evgeni Date: Fri, 27 Aug 2021 17:14:51 +0300 Subject: [PATCH 08/11] linter and checkbox fixes --- .../coach/assets/src/views/plan/CreateExamPage/index.vue | 7 +++++-- .../src/views/plan/LessonResourceSelectionPage/index.vue | 8 +++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue index e299885c96f..3bd74005434 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue @@ -84,7 +84,7 @@
item.id === content.id); const isTopic = contentNode.kind === ContentNodeKinds.TOPIC; if (checked && isTopic) { diff --git a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue index 21943334066..43cacb73692 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue @@ -112,10 +112,7 @@ import commonCoreStrings from 'kolibri.coreVue.mixins.commonCoreStrings'; import commonCoach from '../../common'; import { LessonsPageNames } from '../../../constants/lessonsConstants'; - import { - BookmarksResource, - ContentNodeResource, - } from '../../../../../../../../kolibri/core/assets/src/api-resources/index.js'; + import { BookmarksResource } from '../../../../../../../../kolibri/core/assets/src/api-resources/index.js'; import LessonContentCard from './LessonContentCard/index'; import LessonsSearchBox from './SearchTools/LessonsSearchBox'; import LessonsSearchFilters from './SearchTools/LessonsSearchFilters'; @@ -384,8 +381,9 @@ } }, addToSelectedResources(content) { + const list = this.contentList?.length ? this.contentList : this.bookmarksList; this.addToResourceCache({ - node: this.contentList.find(n => n.id === content.id), + node: list.find(n => n.id === content.id), }); this.addToWorkingResources([content]); }, From ab04c39f9a57daebe1514f268d9f7a925b66e59b Mon Sep 17 00:00:00 2001 From: Evgeni Date: Tue, 31 Aug 2021 18:20:04 +0300 Subject: [PATCH 09/11] use custom HTML for showing bookmarks container instead of using component and optimize data fetching logic --- .../src/modules/examCreation/handlers.js | 20 +++++---- .../src/modules/lessonResources/handlers.js | 21 ++++++---- .../src/views/plan/CreateExamPage/index.vue | 39 ++++++++++++++---- .../LessonResourceSelectionPage/index.vue | 41 +++++++++++++++---- 4 files changed, 91 insertions(+), 30 deletions(-) diff --git a/kolibri/plugins/coach/assets/src/modules/examCreation/handlers.js b/kolibri/plugins/coach/assets/src/modules/examCreation/handlers.js index 633e737290b..f7119a75b17 100644 --- a/kolibri/plugins/coach/assets/src/modules/examCreation/handlers.js +++ b/kolibri/plugins/coach/assets/src/modules/examCreation/handlers.js @@ -9,6 +9,7 @@ import { } from 'kolibri.resources'; import { assessmentMetaDataState } from 'kolibri.coreVue.vuex.mappers'; import router from 'kolibri.coreVue.router'; +import chunk from 'lodash/chunk'; import { PageNames } from '../../constants'; import { filterAndAnnotateContentList, fetchChannelQuizzes } from './actions'; @@ -155,20 +156,25 @@ export function showExamCreationAllBookmarks(store) { return store.dispatch('loading').then(() => { getBookmarks().then(bookmarks => { return showExamCreationPage(store, { - bookmarksList: bookmarks, + bookmarksList: bookmarks[0], }); }); }); } function getBookmarks() { return BookmarksResource.fetchCollection() - .then(bookmarks => { - return bookmarks.map(bookmark => { - return ContentNodeResource.fetchModel({ id: bookmark.contentnode_id }); + .then(bookmarks => bookmarks.map(bookmark => bookmark.contentnode_id)) + .then(contentNodeIds => { + const chunkedContentNodeIds = chunk(contentNodeIds, 50); // Breaking contentNodeIds into lists no more than 50 in length + // Now we will create an array of promises, each of which queries for the 50-id chunk + const fetchPromises = chunkedContentNodeIds.map(idsChunk => { + return ContentNodeResource.fetchCollection({ + getParams: { + ids: idsChunk, // This filters only the ids we want + }, + }); }); - }) - .then(bookmarkPromises => { - return Promise.all(bookmarkPromises); + return Promise.all(fetchPromises); }); } diff --git a/kolibri/plugins/coach/assets/src/modules/lessonResources/handlers.js b/kolibri/plugins/coach/assets/src/modules/lessonResources/handlers.js index 86696199ccd..8439c17f7b6 100644 --- a/kolibri/plugins/coach/assets/src/modules/lessonResources/handlers.js +++ b/kolibri/plugins/coach/assets/src/modules/lessonResources/handlers.js @@ -7,6 +7,7 @@ import { } from 'kolibri.resources'; import { ContentNodeKinds } from 'kolibri.coreVue.vuex.constants'; import { getContentNodeThumbnail } from 'kolibri.utils.contentNode'; +import chunk from 'lodash/chunk'; import { LessonsPageNames } from '../../constants/lessonsConstants'; function showResourceSelectionPage(store, params) { @@ -166,22 +167,26 @@ export function showLessonResourceBookmarks(store, params) { export function showLessonResourceBookmarksMain(store) { return store.dispatch('loading').then(() => { getBookmarks().then(bookmarks => { - console.log(111111, bookmarks); return showResourceSelectionPage(store, { - bookmarksList: bookmarks, + bookmarksList: bookmarks[0], }); }); }); } function getBookmarks() { return BookmarksResource.fetchCollection() - .then(bookmarks => { - return bookmarks.map(bookmark => { - return ContentNodeResource.fetchModel({ id: bookmark.contentnode_id }); + .then(bookmarks => bookmarks.map(bookmark => bookmark.contentnode_id)) + .then(contentNodeIds => { + const chunkedContentNodeIds = chunk(contentNodeIds, 50); // Breaking contentNodeIds into lists no more than 50 in length + // Now we will create an array of promises, each of which queries for the 50-id chunk + const fetchPromises = chunkedContentNodeIds.map(idsChunk => { + return ContentNodeResource.fetchCollection({ + getParams: { + ids: idsChunk, // This filters only the ids we want + }, + }); }); - }) - .then(bookmarkPromises => { - return Promise.all(bookmarkPromises); + return Promise.all(fetchPromises); }); } export function showLessonResourceContentPreview(store, params) { diff --git a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue index 3bd74005434..85671e23553 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue @@ -99,13 +99,19 @@

Select from bookmarks

- + +
+ +
+

{{$tr('bookmarks')}}

+

{{ $tr('resources', { count: this.bookmarksCount })}}

+
+
+
diff --git a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue index 43cacb73692..eeb8dca734b 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue @@ -12,7 +12,7 @@ > -

+

{{ $tr('documentTitle', { lessonName: currentLesson.title }) }}

@@ -32,13 +32,19 @@
- + +
+ +
+

{{$tr('bookmarks')}}

+

{{ $tr('resources', { count: this.bookmarksCount })}}

+
+
+
@@ -118,6 +124,7 @@ import LessonsSearchFilters from './SearchTools/LessonsSearchFilters'; import ResourceSelectionBreadcrumbs from './SearchTools/ResourceSelectionBreadcrumbs'; import ContentCardList from './ContentCardList'; + import BookmarkIcon from './LessonContentCard/BookmarkIcon'; export default { // this is inaccurately named because it applies to exams also @@ -134,6 +141,7 @@ ResourceSelectionBreadcrumbs, BottomAppBar, LessonContentCard, + BookmarkIcon, }, mixins: [commonCoach, commonCoreStrings], data() { @@ -555,4 +563,21 @@ margin-top: 24px; } + .bookmark-container { + display: flex; + min-height: 141px; + margin-bottom: 24px; + border-radius: 2px; + box-shadow: 0 1px 5px 0 #a1a1a1, 0 2px 2px 0 #e6e6e6, 0 3px 1px -2px #ffffff; + transition: box-shadow 0.25s ease; + } + + .bookmark-container:hover { + box-shadow: 0 5px 5px -3px #a1a1a1, 0 8px 10px 1px #d1d1d1, 0 3px 14px 2px #d4d4d4; + } + + .text { + margin-left: 15rem; + } + From 065599882db8da5b653bb82ed88472249a49de3d Mon Sep 17 00:00:00 2001 From: Evgeni Date: Fri, 3 Sep 2021 16:33:59 +0300 Subject: [PATCH 10/11] linter fixes --- .../coach/assets/src/views/plan/CreateExamPage/index.vue | 2 +- .../src/views/plan/LessonResourceSelectionPage/index.vue | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue index 85671e23553..5ed426cb0f4 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue @@ -82,7 +82,7 @@

{{ $tr('chooseExercises') }}

-
- +
-

{{$tr('bookmarks')}}

-

{{ $tr('resources', { count: this.bookmarksCount })}}

+

{{ $tr('bookmarks') }}

+

{{ $tr('resources', { count: this.bookmarksCount }) }}

From 43ab6393f0acaf5cc74615e948e5954a1ae5cab2 Mon Sep 17 00:00:00 2001 From: Evgeni Date: Tue, 14 Sep 2021 13:36:37 +0300 Subject: [PATCH 11/11] fix linting --- .../src/views/plan/CreateExamPage/index.vue | 19 ++++++++----------- .../LessonResourceSelectionPage/index.vue | 9 +++------ 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue index 5ed426cb0f4..d16eb40a65e 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/index.vue @@ -99,16 +99,16 @@

Select from bookmarks

-
- +
-

{{$tr('bookmarks')}}

-

{{ $tr('resources', { count: this.bookmarksCount })}}

+

{{ $tr('bookmarks') }}

+

{{ $tr('resources', { count: bookmarksCount }) }}

@@ -197,7 +197,6 @@ import ResourceSelectionBreadcrumbs from '../../plan/LessonResourceSelectionPage/SearchTools/ResourceSelectionBreadcrumbs'; import ContentCardList from '../../plan/LessonResourceSelectionPage/ContentCardList'; import commonCoach from '../../common'; - import LessonContentCard from '../LessonResourceSelectionPage/LessonContentCard/index'; import BookmarkIcon from '../LessonResourceSelectionPage/LessonContentCard/BookmarkIcon'; export default { @@ -210,7 +209,6 @@ ResourceSelectionBreadcrumbs, ContentCardList, BottomAppBar, - LessonContentCard, BookmarkIcon, }, mixins: [commonCoreStrings, commonCoach, responsiveWindowMixin], @@ -530,7 +528,7 @@ }, toggleSelected({ content, checked }) { let exercises; - const list = this.contentList?.length ? this.contentList : this.bookmarksList; + const list = this.contentList.length ? this.contentList : this.bookmarksList; const contentNode = list.find(item => item.id === content.id); const isTopic = contentNode.kind === ContentNodeKinds.TOPIC; if (checked && isTopic) { @@ -610,7 +608,6 @@ }, $trs: { resources: '{count} {count, plural, one {resource} other {resources}}', - bookmark: 'bookmark', bookmarks: 'Bookmarks', createNewExamLabel: { message: 'Create new quiz', diff --git a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue index 056dcd1a1e1..8369ce39d5c 100644 --- a/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue +++ b/kolibri/plugins/coach/assets/src/views/plan/LessonResourceSelectionPage/index.vue @@ -33,7 +33,7 @@
@@ -41,7 +41,7 @@

{{ $tr('bookmarks') }}

-

{{ $tr('resources', { count: this.bookmarksCount }) }}

+

{{ $tr('resources', { count: bookmarksCount }) }}

@@ -119,7 +119,6 @@ import commonCoach from '../../common'; import { LessonsPageNames } from '../../../constants/lessonsConstants'; import { BookmarksResource } from '../../../../../../../../kolibri/core/assets/src/api-resources/index.js'; - import LessonContentCard from './LessonContentCard/index'; import LessonsSearchBox from './SearchTools/LessonsSearchBox'; import LessonsSearchFilters from './SearchTools/LessonsSearchFilters'; import ResourceSelectionBreadcrumbs from './SearchTools/ResourceSelectionBreadcrumbs'; @@ -140,7 +139,6 @@ LessonsSearchBox, ResourceSelectionBreadcrumbs, BottomAppBar, - LessonContentCard, BookmarkIcon, }, mixins: [commonCoach, commonCoreStrings], @@ -389,7 +387,7 @@ } }, addToSelectedResources(content) { - const list = this.contentList?.length ? this.contentList : this.bookmarksList; + const list = this.contentList.length ? this.contentList : this.bookmarksList; this.addToResourceCache({ node: list.find(n => n.id === content.id), }); @@ -514,7 +512,6 @@ }, $trs: { resources: '{count} {count, plural, one {resource} other {resources}}', - bookmark: 'bookmark', bookmarks: 'Bookmarks', selectionInformation: { message: