From 04ffcbb4e5581ef1965b4604a7d57b5b9b88a336 Mon Sep 17 00:00:00 2001 From: Alex Velez Date: Tue, 14 Jan 2025 14:48:32 -0500 Subject: [PATCH 01/16] Fix SearchFilterPanel showing a blank div --- .../components/SearchFiltersPanel/index.vue | 53 +++++++++---------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/packages/kolibri-common/components/SearchFiltersPanel/index.vue b/packages/kolibri-common/components/SearchFiltersPanel/index.vue index ba2eb32634f..b7098f3524b 100644 --- a/packages/kolibri-common/components/SearchFiltersPanel/index.vue +++ b/packages/kolibri-common/components/SearchFiltersPanel/index.vue @@ -109,35 +109,34 @@ /> + +
+ +

+ {{ $tr('keywords') }} +

+ -
- -

- {{ $tr('keywords') }} -

- - - + - -
+
From fc945b4d12e54239711bae88742c893e207fd3a8 Mon Sep 17 00:00:00 2001 From: Alex Velez Date: Wed, 15 Jan 2025 14:50:20 -0500 Subject: [PATCH 02/16] Integrate Search Filters and Search Results to LessonResourceSelection --- kolibri/plugins/coach/assets/src/app.js | 2 + .../src/composables/useResourceSelection.js | 35 ++- .../coach/assets/src/constants/index.js | 2 + .../coach/assets/src/routes/lessonsRoutes.js | 21 +- .../ContentCardList.vue | 6 + .../LessonContentCard/index.vue | 13 +- .../UpdatedResourceSelection.vue | 5 + .../LessonResourceSelection/index.vue | 38 +++- .../subPages/SearchFilters.vue | 103 +++++++++ .../subPages/SelectFromSearchResults.vue | 204 ++++++++++++++++++ ...omChannels.vue => SelectFromTopicTree.vue} | 11 +- .../subPages/SelectionIndex.vue | 4 + .../kolibri-common/components/SearchBox.vue | 20 ++ .../kolibri-common/components/SearchChips.vue | 2 +- .../components/SearchFiltersPanel/index.vue | 14 +- 15 files changed, 461 insertions(+), 19 deletions(-) create mode 100644 kolibri/plugins/coach/assets/src/views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection/subPages/SearchFilters.vue create mode 100644 kolibri/plugins/coach/assets/src/views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection/subPages/SelectFromSearchResults.vue rename kolibri/plugins/coach/assets/src/views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection/subPages/{SelectFromChannels.vue => SelectFromTopicTree.vue} (93%) diff --git a/kolibri/plugins/coach/assets/src/app.js b/kolibri/plugins/coach/assets/src/app.js index 3b790935915..b9b908bb091 100644 --- a/kolibri/plugins/coach/assets/src/app.js +++ b/kolibri/plugins/coach/assets/src/app.js @@ -72,6 +72,8 @@ class CoachToolsModule extends KolibriApp { PageNames.LESSON_PREVIEW_SELECTED_RESOURCES, PageNames.LESSON_PREVIEW_RESOURCE, PageNames.LESSON_SELECT_RESOURCES_INDEX, + PageNames.LESSON_SELECT_RESOURCES_SEARCH, + PageNames.LESSON_SELECT_RESOURCES_SEARCH_RESULTS, PageNames.LESSON_SELECT_RESOURCES_BOOKMARKS, PageNames.LESSON_SELECT_RESOURCES_TOPIC_TREE, ]; diff --git a/kolibri/plugins/coach/assets/src/composables/useResourceSelection.js b/kolibri/plugins/coach/assets/src/composables/useResourceSelection.js index 86e35f9bd56..42d69baa267 100644 --- a/kolibri/plugins/coach/assets/src/composables/useResourceSelection.js +++ b/kolibri/plugins/coach/assets/src/composables/useResourceSelection.js @@ -2,6 +2,7 @@ import uniqBy from 'lodash/uniqBy'; import { ref, computed, getCurrentInstance, watch } from 'vue'; import ContentNodeResource from 'kolibri-common/apiResources/ContentNodeResource'; import ChannelResource from 'kolibri-common/apiResources/ChannelResource'; +import useBaseSearch from 'kolibri-common/composables/useBaseSearch'; import useFetch from './useFetch'; /** @@ -26,6 +27,10 @@ import useFetch from './useFetch'; * fetching bookmarks. Fetching more bookmarks is supported. * @property {FetchObject} treeFetch Topic tree fetch object to manage the process of * fetching topic trees and their resources. Fetching more resources is supported. + * @property {FetchObject} searchFetch Search fetch object to manage the process of + * fetching search results. Fetching more search results is supported. + * @property {Array} searchTerms The search terms used to filter the search results. + * @property {boolean} displayingSearchResults Indicates whether we currently have search terms. * @property {Array<(node: Object) => boolean>} selectionRules An array of functions that determine * whether a node can be selected. * @property {Array} selectedResources An array of currently selected resources. @@ -35,6 +40,9 @@ import useFetch from './useFetch'; * from the `selectedResources` array. * @property {(resources: Array) => void} setSelectedResources Replaces the current * `selectedResources` array with the provided resources array. + * @property {() => void} clearSearch Clears the current search terms and results. + * @property {(tag: Object) => void} removeSearchFilterTag Removes the specified tag from the + * search terms. * * @returns {UseResourceSelectionResponse} */ @@ -67,6 +75,19 @@ export default function useResourceSelection() { }), }); + const useSearchObject = useBaseSearch({ + descendant: topic, + }); + const searchFetch = { + data: useSearchObject.results, + loading: useSearchObject.searchLoading, + hasMore: computed(() => !!useSearchObject.more.value), + loadingMore: useSearchObject.moreLoading, + fetchData: useSearchObject.search, + fetchMore: useSearchObject.searchMore, + }; + const { displayingSearchResults } = useSearchObject; + const fetchTree = async (params = {}) => { topic.value = await ContentNodeResource.fetchTree(params); return topic.value.children; @@ -80,11 +101,13 @@ export default function useResourceSelection() { watch(topicId, () => { if (topicId.value) { treeFetch.fetchData(); + } else { + topic.value = null; } }); const loading = computed(() => { - const sources = [bookmarksFetch, channelsFetch, treeFetch]; + const sources = [bookmarksFetch, channelsFetch, treeFetch, searchFetch]; return sources.some(sourceFetch => sourceFetch.loading.value); }); @@ -95,6 +118,9 @@ export default function useResourceSelection() { if (topicId.value) { treeFetch.fetchData(); } + if (displayingSearchResults) { + searchFetch.fetchData(); + } }; fetchInitialData(); @@ -129,13 +155,18 @@ export default function useResourceSelection() { return { topic, loading, + treeFetch, channelsFetch, bookmarksFetch, - treeFetch, + searchFetch, selectionRules, selectedResources, + searchTerms: useSearchObject.searchTerms, + displayingSearchResults: useSearchObject.displayingSearchResults, selectResources, deselectResources, setSelectedResources, + clearSearch: useSearchObject.clearSearch, + removeSearchFilterTag: useSearchObject.removeFilterTag, }; } diff --git a/kolibri/plugins/coach/assets/src/constants/index.js b/kolibri/plugins/coach/assets/src/constants/index.js index 03a55ab7d3e..0e8e256bd70 100644 --- a/kolibri/plugins/coach/assets/src/constants/index.js +++ b/kolibri/plugins/coach/assets/src/constants/index.js @@ -36,8 +36,10 @@ export const PageNames = { LESSON_EDIT_DETAILS_BETTER: 'LESSON_EDIT_DETAILS_BETTER', LESSON_SELECT_RESOURCES: 'LESSON_SELECT_RESOURCES', LESSON_SELECT_RESOURCES_INDEX: 'LESSON_SELECT_RESOURCES_INDEX', + LESSON_SELECT_RESOURCES_SEARCH: 'LESSON_SELECT_RESOURCES_SEARCH', LESSON_SELECT_RESOURCES_BOOKMARKS: 'LESSON_SELECT_RESOURCES_BOOKMARKS', LESSON_SELECT_RESOURCES_TOPIC_TREE: 'LESSON_SELECT_RESOURCES_TOPIC_TREE', + LESSON_SELECT_RESOURCES_SEARCH_RESULTS: 'LESSON_SELECT_RESOURCES_SEARCH_RESULTS', LESSON_PREVIEW_SELECTED_RESOURCES: 'LESSON_PREVIEW_SELECTED_RESOURCES', LESSON_PREVIEW_RESOURCE: 'LESSON_PREVIEW_RESOURCE', LESSON_LEARNER_REPORT: 'LESSON_LEARNER_REPORT', diff --git a/kolibri/plugins/coach/assets/src/routes/lessonsRoutes.js b/kolibri/plugins/coach/assets/src/routes/lessonsRoutes.js index debb48d68d6..4f81298cf42 100644 --- a/kolibri/plugins/coach/assets/src/routes/lessonsRoutes.js +++ b/kolibri/plugins/coach/assets/src/routes/lessonsRoutes.js @@ -38,12 +38,13 @@ import LessonLearnerExercisePage from '../views/lessons/reports/LessonLearnerExe import QuestionLearnersPage from '../views/common/reports/QuestionLearnersPage.vue'; import EditLessonDetails from '../views/lessons/LessonSummaryPage/sidePanels/EditLessonDetails'; import PreviewSelectedResources from '../views/lessons/LessonSummaryPage/sidePanels/PreviewSelectedResources'; -import LessonResourceSelection from '../views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection'; +import LessonResourceSelection from '../views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection/index.vue'; +import SearchFilters from '../views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection/subPages/SearchFilters.vue'; import SelectionIndex from '../views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection/subPages/SelectionIndex.vue'; import SelectFromBookmarks from '../views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection/subPages/SelectFromBookmarks.vue'; -import SelectFromChannels from '../views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection/subPages/SelectFromChannels.vue'; +import SelectFromTopicTree from '../views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection/subPages/SelectFromTopicTree.vue'; +import SelectFromSearchResults from '../views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection/subPages/SelectFromSearchResults.vue'; import ManageSelectedResources from '../views/lessons/LessonSummaryPage/sidePanels/LessonResourceSelection/subPages/ManageSelectedResources.vue'; - import { classIdParamRequiredGuard, RouteSegments } from './utils'; const { @@ -153,8 +154,18 @@ export default [ }, { name: PageNames.LESSON_SELECT_RESOURCES_TOPIC_TREE, - path: 'channels', - component: SelectFromChannels, + path: 'topic-tree', + component: SelectFromTopicTree, + }, + { + name: PageNames.LESSON_SELECT_RESOURCES_SEARCH, + path: 'search', + component: SearchFilters, + }, + { + name: PageNames.LESSON_SELECT_RESOURCES_SEARCH_RESULTS, + path: 'search-results', + component: SelectFromSearchResults, }, { name: PageNames.LESSON_PREVIEW_SELECTED_RESOURCES, diff --git a/kolibri/plugins/coach/assets/src/views/lessons/LessonResourceSelectionPage/ContentCardList.vue b/kolibri/plugins/coach/assets/src/views/lessons/LessonResourceSelectionPage/ContentCardList.vue index 855362fe3b0..d2fead08834 100644 --- a/kolibri/plugins/coach/assets/src/views/lessons/LessonResourceSelectionPage/ContentCardList.vue +++ b/kolibri/plugins/coach/assets/src/views/lessons/LessonResourceSelectionPage/ContentCardList.vue @@ -48,6 +48,7 @@ :content="content" :message="contentCardMessage(content)" :link="contentCardLink(content)" + :headingLevel="cardsHeadingLevel" > -
+
@@ -27,19 +27,27 @@ :setGoBack="setGoBack" :topic="topic" :disabled="isSaving" + :treeFetch="treeFetch" + :searchFetch="searchFetch" :channelsFetch="channelsFetch" :bookmarksFetch="bookmarksFetch" - :treeFetch="treeFetch" + :searchTerms.sync="searchTerms" :selectionRules="selectionRules" :selectedResources="selectedResources" :unselectableResourceIds="unselectableResourceIds" :selectedResourcesSize="selectedResourcesSize" + :displayingSearchResults="displayingSearchResults" + @clearSearch="clearSearch" @selectResources="selectResources" @deselectResources="deselectResources" @setSelectedResources="setSelectedResources" + @removeSearchFilterTag="removeSearchFilterTag" /> -