← All changes
|
js/components/ManageMenu/CommunityCloud/WithCloudSearchContext.tsx
+26
-9
4.0.0-beta.1
→
trunk
View file →
| @@ -34,12 +34,22 @@ | ||
| 34 | 34 | status: 'status', |
| 35 | 35 | category: 'category' |
| 36 | 36 | } |
| 37 | 37 | |
| 38 | +const SEARCH_METHODS = ['term', 'codevault', 'ai'] as const | |
| 39 | + | |
| 40 | +export type CloudSearchMethod = typeof SEARCH_METHODS[number] | |
| 41 | + | |
| 42 | +const isSearchMethod = (value: unknown): value is CloudSearchMethod => | |
| 43 | + SEARCH_METHODS.some(method => method === value) | |
| 44 | + | |
| 45 | +export const parseSearchMethod = (value: unknown): CloudSearchMethod => | |
| 46 | + isSearchMethod(value) ? value : 'term' | |
| 47 | + | |
| 38 | 48 | export interface CloudSearchParams { |
| 39 | 49 | page: number |
| 40 | 50 | query: string |
| 41 | - method: 'term' | 'codevault' | |
| 51 | + method: CloudSearchMethod | |
| 42 | 52 | type: string |
| 43 | 53 | status: number |
| 44 | 54 | category: string |
| 45 | 55 | } |
| @@ -56,12 +66,8 @@ | ||
| 56 | 66 | id: number |
| 57 | 67 | name: string |
| 58 | 68 | } |
| 59 | 69 | |
| 60 | -export const clearSearchQueryParams = () => { | |
| 61 | - updateQueryParams(Object.fromEntries(Object.values(SEARCH_PARAM_VARS).map(param => [param, undefined]))) | |
| 62 | -} | |
| 63 | - | |
| 64 | 70 | const fetchSearchQueryParams = (): CloudSearchParams => { |
| 65 | 71 | const page = Number(fetchQueryParam(SEARCH_PARAM_VARS.page) ?? 1) |
| 66 | 72 | const query = fetchQueryParam(SEARCH_PARAM_VARS.query) ?? '' |
| 67 | 73 | const type = fetchQueryParam(SEARCH_PARAM_VARS.type) ?? '' |
| @@ -73,9 +79,9 @@ | ||
| 73 | 79 | page: isNaN(page) ? 1 : page, |
| 74 | 80 | type, |
| 75 | 81 | query, |
| 76 | 82 | status: Number(status), |
| 77 | - method: 'codevault' === method ? 'codevault' : 'term', | |
| 83 | + method: parseSearchMethod(method), | |
| 78 | 84 | category |
| 79 | 85 | } |
| 80 | 86 | } |
| 81 | 87 | |
| @@ -96,8 +102,9 @@ | ||
| 96 | 102 | ) => |
| 97 | 103 | buildUrl(baseUrl, { |
| 98 | 104 | query, |
| 99 | 105 | searchByCodevault: 'codevault' === method ? true : undefined, |
| 106 | + searchMethod: 'ai' === method ? 'ai' : undefined, | |
| 100 | 107 | per_page: SNIPPETS_PER_PAGE, |
| 101 | 108 | type: type || undefined, |
| 102 | 109 | category: category || undefined, |
| 103 | 110 | status: status || undefined, |
| @@ -167,8 +174,9 @@ | ||
| 167 | 174 | |
| 168 | 175 | export interface CloudSearchContext { |
| 169 | 176 | isErrored: boolean |
| 170 | 177 | doSearch: (paramsDelta?: Partial<CloudSearchParams>) => void |
| 178 | + isLoading: boolean | |
| 171 | 179 | isSearching: boolean |
| 172 | 180 | searchParams: CloudSearchParams |
| 173 | 181 | searchResults: CloudSearchResults | undefined |
| 174 | 182 | availableFilters: AvailableCloudFilters |
| @@ -178,8 +186,9 @@ | ||
| 178 | 186 | const useSearchApi = () => { |
| 179 | 187 | const { api } = useRestAPI() |
| 180 | 188 | const { isCurrentRequest, nextRequestId } = useRequestIds() |
| 181 | 189 | const [currentSearch, setCurrentSearch] = useState(false) |
| 190 | + const [isLoading, setIsLoading] = useState(false) | |
| 182 | 191 | const [searchResults, setSearchResults] = useState<CloudSearchResults | false | undefined>() |
| 183 | 192 | const [availableFilters, setAvailableFilters] = useState<AvailableCloudFilters>({}) |
| 184 | 193 | |
| 185 | 194 | const makeSearchRequest = useCallback((params: CloudSearchParams) => { |
| @@ -185,8 +194,9 @@ | ||
| 185 | 194 | const makeSearchRequest = useCallback((params: CloudSearchParams) => { |
| 186 | 195 | const requestId = nextRequestId() |
| 187 | 196 | const isFeaturedSearch = '' === params.query.trim() |
| 188 | 197 | |
| 198 | + setIsLoading(true) | |
| 189 | 199 | setCurrentSearch(!isFeaturedSearch) |
| 190 | 200 | const baseUrl = isFeaturedSearch ? SEARCH_URLS.FEATURED : SEARCH_URLS.SEARCH_QUERY |
| 191 | 201 | |
| 192 | 202 | api.getResponse<CloudSnippetsSchema>(buildSearchUrl(baseUrl, params)) |
| @@ -200,12 +210,18 @@ | ||
| 200 | 210 | if (isCurrentRequest(requestId)) { |
| 201 | 211 | setSearchResults(false) |
| 202 | 212 | } |
| 203 | 213 | }) |
| 204 | - .finally(() => setCurrentSearch(false)) | |
| 214 | + .finally(() => { | |
| 215 | + if (isCurrentRequest(requestId)) { | |
| 216 | + setCurrentSearch(false) | |
| 217 | + setIsLoading(false) | |
| 218 | + } | |
| 219 | + }) | |
| 205 | 220 | }, [api, nextRequestId, isCurrentRequest]) |
| 206 | 221 | |
| 207 | 222 | return { |
| 223 | + isLoading, | |
| 208 | 224 | isSearching: currentSearch, |
| 209 | 225 | searchResults, |
| 210 | 226 | availableFilters, |
| 211 | 227 | makeSearchRequest |
| @@ -214,9 +230,9 @@ | ||
| 214 | 230 | |
| 215 | 231 | const [Context, useCloudSearch] = createContextHook<CloudSearchContext>('useCloudSearch') |
| 216 | 232 | |
| 217 | 233 | export const WithCloudSearchContext: React.FC<PropsWithChildren> = ({ children }) => { |
| 218 | - const { isSearching, makeSearchRequest, availableFilters, searchResults } = useSearchApi() | |
| 234 | + const { isLoading, isSearching, makeSearchRequest, availableFilters, searchResults } = useSearchApi() | |
| 219 | 235 | const [searchParams, setSearchParams] = useState<CloudSearchParams>(fetchSearchQueryParams) |
| 220 | 236 | const [madeInitialRequest, setMadeInitialRequest] = useState(false) |
| 221 | 237 | |
| 222 | 238 | const updateSearchParams = useCallback( |
| @@ -232,15 +248,16 @@ | ||
| 232 | 248 | }, [makeSearchRequest, searchParams]) |
| 233 | 249 | |
| 234 | 250 | useEffect(() => { |
| 235 | 251 | if (!madeInitialRequest) { |
| 252 | + setMadeInitialRequest(true) | |
| 236 | 253 | makeSearchRequest(searchParams) |
| 237 | - setMadeInitialRequest(true) | |
| 238 | 254 | } |
| 239 | 255 | }, [makeSearchRequest, searchParams, madeInitialRequest]) |
| 240 | 256 | |
| 241 | 257 | const value: CloudSearchContext = { |
| 242 | 258 | doSearch, |
| 259 | + isLoading, | |
| 243 | 260 | isSearching, |
| 244 | 261 | searchParams, |
| 245 | 262 | availableFilters, |
| 246 | 263 | updateSearchParams, |