switch search endpoint

This commit is contained in:
Nate Kelley 2025-09-25 10:28:10 -06:00
parent 1841953e9c
commit 9b35106a71
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
11 changed files with 59 additions and 53 deletions

View File

@ -1 +0,0 @@
export type * from './interfaces';

View File

@ -1,10 +0,0 @@
import type { ShareAssetType } from '@buster/server-shared/share';
export interface BusterSearchResult {
id: string;
highlights: string[];
name: string;
updated_at: string;
type: ShareAssetType;
score: number;
}

View File

@ -1,15 +1,22 @@
import type { SearchTextResponse } from '@buster/server-shared/search';
import { keepPreviousData, type UseQueryOptions, useQuery } from '@tanstack/react-query';
import type { RustApiError } from '@/api/errors';
import { searchQueryKeys } from '@/api/query_keys/search';
import { search } from './requests';
export const useSearch = (
export const useSearch = <T = SearchTextResponse>(
params: Parameters<typeof search>[0],
options?: Omit<UseQueryOptions<Awaited<ReturnType<typeof search>>>, 'queryKey' | 'queryFn'>
options?: Omit<UseQueryOptions<SearchTextResponse, RustApiError, T>, 'queryKey' | 'queryFn'>,
postQueryOptions?: {
doNotUnwrapData?: boolean;
}
) => {
return useQuery({
const { doNotUnwrapData = false } = postQueryOptions || {};
return useQuery<SearchTextResponse, RustApiError, T>({
...searchQueryKeys.getSearchResult(params),
queryFn: () => search(params),
placeholderData: keepPreviousData,
select: options?.select,
...options,
placeholderData: keepPreviousData,
});
};

View File

@ -1,11 +1,6 @@
import type { AssetType } from '@buster/server-shared/assets';
import type { BusterSearchResult } from '@/api/asset_interfaces/search';
import { mainApi } from '../instances';
import type { SearchTextRequest, SearchTextResponse } from '@buster/server-shared/search';
import { mainApiV2 } from '../instances';
export const search = async (params: {
query: string;
asset_types: Extract<AssetType, 'dashboard_file' | 'metric_file' | 'collection'>[];
num_results?: number;
}) => {
return mainApi.post<BusterSearchResult[]>('/search', params).then((res) => res.data);
export const search = async (params: SearchTextRequest) => {
return mainApiV2.get<SearchTextResponse>('/search', { params }).then((res) => res.data);
};

View File

@ -1,9 +1,8 @@
import type { SearchTextRequest, SearchTextResponse } from '@buster/server-shared';
import { queryOptions } from '@tanstack/react-query';
import type { BusterSearchResult } from '@/api/asset_interfaces/search';
import type { search } from '../buster_rest/search';
export const getSearchResult = (params: Parameters<typeof search>[0]) =>
queryOptions<BusterSearchResult[]>({
export const getSearchResult = (params: SearchTextRequest) =>
queryOptions<SearchTextResponse>({
queryKey: ['search', 'results', params] as const,
staleTime: 1000 * 15, // 15 seconds,
});

View File

@ -1,5 +1,5 @@
import React, { useEffect, useMemo, useState } from 'react';
import type { BusterSearchResult } from '@/api/asset_interfaces/search';
import type { SearchTextRequest, SearchTextResponse } from '@buster/server-shared/search';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useSearch } from '@/api/buster_rest/search';
import { Button } from '@/components/ui/buttons';
import {
@ -46,29 +46,34 @@ export const AddMetricModal: React.FC<{
const { data: searchResults } = useSearch(
{
query: debouncedSearchTerm,
asset_types: ['metric_file'],
num_results: 100,
},
{ enabled: true }
assetTypes: ['metric_file'],
page_size: 25,
page: 1,
} satisfies SearchTextRequest,
{ enabled: true, select: useCallback((data: SearchTextResponse) => data.data, []) }
);
const columns = useMemo<InputSelectModalProps<BusterSearchResult>['columns']>(
const columns = useMemo<InputSelectModalProps<SearchTextResponse['data'][number]>['columns']>(
() => [
{
title: 'Name',
dataIndex: 'name',
},
{
title: 'Updated',
dataIndex: 'updated_at',
width: 140,
title: 'Title',
dataIndex: 'title',
render: (value) => {
return formatDate({
date: value,
format: 'lll',
});
// biome-ignore lint/security/noDangerouslySetInnerHtml: <explanation>
return <span dangerouslySetInnerHTML={{ __html: value }}></span>;
},
},
// {
// title: 'Updated',
// dataIndex: 'updated_at',
// width: 140,
// render: (value) => {
// return formatDate({
// date: value,
// format: 'lll',
// });
// },
// },
],
[]
);
@ -76,8 +81,8 @@ export const AddMetricModal: React.FC<{
const rows = useMemo(() => {
return (
searchResults?.map((result) => ({
id: result.id,
dataTestId: `item-${result.id}`,
id: result.assetId,
dataTestId: `item-${result.assetId}`,
data: result,
})) || []
);
@ -100,7 +105,7 @@ export const AddMetricModal: React.FC<{
const item = rows.find((row) => row.id === id);
return {
id: id,
name: item?.data?.name || id,
name: item?.data?.title || id,
};
});

View File

@ -53,3 +53,8 @@ p {
th {
@apply text-base font-normal;
}
strong,
b {
@apply font-semibold
}

View File

@ -1,8 +1,9 @@
import z from 'zod';
import { AssetTypeSchema } from './asset';
export const TextSearchResultSchema = z.object({
assetId: z.string().uuid(),
assetType: z.string(),
assetType: AssetTypeSchema,
title: z.string(),
additionalText: z.string().nullable(),
});

View File

@ -99,6 +99,10 @@
"./healthcheck": {
"types": "./dist/healthcheck/index.d.ts",
"default": "./dist/healthcheck/index.js"
},
"./search": {
"types": "./dist/search/index.d.ts",
"default": "./dist/search/index.js"
}
},
"module": "src/index.ts",

View File

@ -28,7 +28,8 @@ export const SearchTextRequestSchema = z
}
return Boolean(val);
}, z.boolean())
.default(false),
.default(false)
.optional(),
endDate: z.string().datetime().optional(),
startDate: z.string().datetime().optional(),
})

View File

@ -18,6 +18,6 @@ export const PaginatedResponseSchema = <T>(schema: z.ZodType<T>) =>
export type PaginatedResponse<T> = z.infer<ReturnType<typeof PaginatedResponseSchema<T>>>;
export const PaginatedRequestSchema = z.object({
page: z.coerce.number().min(1).default(1),
page_size: z.coerce.number().min(1).max(5000).default(250),
page: z.coerce.number().min(1).optional().default(1).optional(),
page_size: z.coerce.number().min(1).max(5000).default(250).optional(),
});