@@ -2,6 +2,7 @@ import uniqBy from 'lodash/uniqBy';
2
2
import { ref , computed , getCurrentInstance , watch } from 'vue' ;
3
3
import ContentNodeResource from 'kolibri-common/apiResources/ContentNodeResource' ;
4
4
import ChannelResource from 'kolibri-common/apiResources/ChannelResource' ;
5
+ import useBaseSearch from 'kolibri-common/composables/useBaseSearch' ;
5
6
import useFetch from './useFetch' ;
6
7
7
8
/**
@@ -13,6 +14,11 @@ import useFetch from './useFetch';
13
14
* This utility handles selection rules, manages fetch states for channels, bookmarks,
14
15
* and topic trees, and offers methods to add, remove, or override selected resources.
15
16
*
17
+ * @param {Object } options
18
+ * @param {string } options.searchResultsRouteName The name of the route where the search results
19
+ * will be displayed so that we can redirect to it when the search terms are updated.
20
+ *
21
+ *
16
22
* @typedef {Object } UseResourceSelectionResponse
17
23
* @property {Object } topic Topic tree object, contains the information of the topic,
18
24
* its ascendants and children.
@@ -26,6 +32,10 @@ import useFetch from './useFetch';
26
32
* fetching bookmarks. Fetching more bookmarks is supported.
27
33
* @property {FetchObject } treeFetch Topic tree fetch object to manage the process of
28
34
* fetching topic trees and their resources. Fetching more resources is supported.
35
+ * @property {FetchObject } searchFetch Search fetch object to manage the process of
36
+ * fetching search results. Fetching more search results is supported.
37
+ * @property {Array<string> } searchTerms The search terms used to filter the search results.
38
+ * @property {boolean } displayingSearchResults Indicates whether we currently have search terms.
29
39
* @property {Array<(node: Object) => boolean> } selectionRules An array of functions that determine
30
40
* whether a node can be selected.
31
41
* @property {Array<Object> } selectedResources An array of currently selected resources.
@@ -35,10 +45,13 @@ import useFetch from './useFetch';
35
45
* from the `selectedResources` array.
36
46
* @property {(resources: Array<Object>) => void } setSelectedResources Replaces the current
37
47
* `selectedResources` array with the provided resources array.
48
+ * @property {() => void } clearSearch Clears the current search terms and results.
49
+ * @property {(tag: Object) => void } removeSearchFilterTag Removes the specified tag from the
50
+ * search terms.
38
51
*
39
52
* @returns {UseResourceSelectionResponse }
40
53
*/
41
- export default function useResourceSelection ( ) {
54
+ export default function useResourceSelection ( { searchResultsRouteName } = { } ) {
42
55
const store = getCurrentInstance ( ) . proxy . $store ;
43
56
const route = computed ( ( ) => store . state . route ) ;
44
57
const topicId = computed ( ( ) => route . value . query . topicId ) ;
@@ -67,8 +80,49 @@ export default function useResourceSelection() {
67
80
} ) ,
68
81
} ) ;
69
82
83
+ const waitForTopicLoad = ( ) => {
84
+ const { searchTopicId } = route . value . query ;
85
+ const topicToWaitFor = searchTopicId || topicId . value ;
86
+ if ( ! topicToWaitFor || topicToWaitFor === topic . value ?. id ) {
87
+ return Promise . resolve ( ) ;
88
+ }
89
+ return new Promise ( resolve => {
90
+ const unwatch = watch ( topic , ( ) => {
91
+ if ( topic . value ?. id === topicToWaitFor ) {
92
+ unwatch ( ) ;
93
+ resolve ( ) ;
94
+ }
95
+ } ) ;
96
+ } ) ;
97
+ } ;
98
+
99
+ const useSearchObject = useBaseSearch ( {
100
+ descendant : topic ,
101
+ searchResultsRouteName,
102
+ // As we dont always show the search filters, we dont need to reload the search results
103
+ // each time the topic changes if not needed
104
+ reloadOnDescendantChange : false ,
105
+ } ) ;
106
+ const searchFetch = {
107
+ data : useSearchObject . results ,
108
+ loading : useSearchObject . searchLoading ,
109
+ hasMore : computed ( ( ) => ! ! useSearchObject . more . value ) ,
110
+ loadingMore : useSearchObject . moreLoading ,
111
+ fetchData : async ( ) => {
112
+ // Make sure that the topic is loaded before searching
113
+ await waitForTopicLoad ( ) ;
114
+ return useSearchObject . search ( ) ;
115
+ } ,
116
+ fetchMore : useSearchObject . searchMore ,
117
+ } ;
118
+
119
+ const { displayingSearchResults } = useSearchObject ;
120
+
70
121
const fetchTree = async ( params = { } ) => {
71
- topic . value = await ContentNodeResource . fetchTree ( params ) ;
122
+ const newTopic = await ContentNodeResource . fetchTree ( params ) ;
123
+ if ( topic . value ?. id !== newTopic . id ) {
124
+ topic . value = newTopic ;
125
+ }
72
126
return topic . value . children ;
73
127
} ;
74
128
@@ -80,11 +134,13 @@ export default function useResourceSelection() {
80
134
watch ( topicId , ( ) => {
81
135
if ( topicId . value ) {
82
136
treeFetch . fetchData ( ) ;
137
+ } else {
138
+ topic . value = null ;
83
139
}
84
140
} ) ;
85
141
86
142
const loading = computed ( ( ) => {
87
- const sources = [ bookmarksFetch , channelsFetch , treeFetch ] ;
143
+ const sources = [ bookmarksFetch , channelsFetch , treeFetch , searchFetch ] ;
88
144
89
145
return sources . some ( sourceFetch => sourceFetch . loading . value ) ;
90
146
} ) ;
@@ -95,6 +151,9 @@ export default function useResourceSelection() {
95
151
if ( topicId . value ) {
96
152
treeFetch . fetchData ( ) ;
97
153
}
154
+ if ( displayingSearchResults . value ) {
155
+ searchFetch . fetchData ( ) ;
156
+ }
98
157
} ;
99
158
100
159
fetchInitialData ( ) ;
@@ -129,13 +188,18 @@ export default function useResourceSelection() {
129
188
return {
130
189
topic,
131
190
loading,
191
+ treeFetch,
132
192
channelsFetch,
133
193
bookmarksFetch,
134
- treeFetch ,
194
+ searchFetch ,
135
195
selectionRules,
136
196
selectedResources,
197
+ searchTerms : useSearchObject . searchTerms ,
198
+ displayingSearchResults : useSearchObject . displayingSearchResults ,
137
199
selectResources,
138
200
deselectResources,
139
201
setSelectedResources,
202
+ clearSearch : useSearchObject . clearSearch ,
203
+ removeSearchFilterTag : useSearchObject . removeFilterTag ,
140
204
} ;
141
205
}
0 commit comments