mirror of https://github.com/buster-so/buster.git
Merge pull request #1141 from buster-so/big-nate-bus-1935-copying-project-ids-from-buster-reports-results-in-empty
Big nate bus 1935 copying project ids from buster reports results in empty
This commit is contained in:
commit
c1832d4c19
|
@ -127,6 +127,7 @@
|
||||||
"@tiptap/react": "^3.5.0",
|
"@tiptap/react": "^3.5.0",
|
||||||
"@tiptap/starter-kit": "^3.5.0",
|
"@tiptap/starter-kit": "^3.5.0",
|
||||||
"@tiptap/suggestion": "^3.5.0",
|
"@tiptap/suggestion": "^3.5.0",
|
||||||
|
"@types/qs": "^6.14.0",
|
||||||
"@udecode/cn": "^49.0.15",
|
"@udecode/cn": "^49.0.15",
|
||||||
"@uploadthing/react": "^7.3.3",
|
"@uploadthing/react": "^7.3.3",
|
||||||
"axios": "catalog:",
|
"axios": "catalog:",
|
||||||
|
@ -157,6 +158,7 @@
|
||||||
"platejs": "49.2.21",
|
"platejs": "49.2.21",
|
||||||
"pluralize": "^8.0.0",
|
"pluralize": "^8.0.0",
|
||||||
"posthog-js": "^1.268.1",
|
"posthog-js": "^1.268.1",
|
||||||
|
"qs": "^6.14.0",
|
||||||
"react": "catalog:",
|
"react": "catalog:",
|
||||||
"react-colorful": "^5.6.1",
|
"react-colorful": "^5.6.1",
|
||||||
"react-day-picker": "^8.10.1",
|
"react-day-picker": "^8.10.1",
|
||||||
|
|
|
@ -7,7 +7,6 @@ export type * from './datasources';
|
||||||
export type * from './metric';
|
export type * from './metric';
|
||||||
export type * from './permission';
|
export type * from './permission';
|
||||||
export type * from './permission_groups';
|
export type * from './permission_groups';
|
||||||
export type * from './search';
|
|
||||||
export type * from './sql';
|
export type * from './sql';
|
||||||
export type * from './teams';
|
export type * from './teams';
|
||||||
export type * from './terms';
|
export type * from './terms';
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export type * from './interfaces';
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -1,15 +1,22 @@
|
||||||
|
import type { SearchTextResponse } from '@buster/server-shared/search';
|
||||||
import { keepPreviousData, type UseQueryOptions, useQuery } from '@tanstack/react-query';
|
import { keepPreviousData, type UseQueryOptions, useQuery } from '@tanstack/react-query';
|
||||||
|
import type { RustApiError } from '@/api/errors';
|
||||||
import { searchQueryKeys } from '@/api/query_keys/search';
|
import { searchQueryKeys } from '@/api/query_keys/search';
|
||||||
import { search } from './requests';
|
import { search } from './requests';
|
||||||
|
|
||||||
export const useSearch = (
|
export const useSearch = <T = SearchTextResponse>(
|
||||||
params: Parameters<typeof search>[0],
|
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),
|
...searchQueryKeys.getSearchResult(params),
|
||||||
queryFn: () => search(params),
|
queryFn: () => search(params),
|
||||||
placeholderData: keepPreviousData,
|
select: options?.select,
|
||||||
...options,
|
...options,
|
||||||
|
placeholderData: keepPreviousData,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
import type { AssetType } from '@buster/server-shared/assets';
|
import type { SearchTextRequest, SearchTextResponse } from '@buster/server-shared/search';
|
||||||
import type { BusterSearchResult } from '@/api/asset_interfaces/search';
|
import qs from 'qs';
|
||||||
import { mainApi } from '../instances';
|
import { mainApiV2 } from '../instances';
|
||||||
|
|
||||||
export const search = async (params: {
|
export const search = async (params: SearchTextRequest) => {
|
||||||
query: string;
|
return mainApiV2.get<SearchTextResponse>('/search', { params }).then((res) => res.data);
|
||||||
asset_types: Extract<AssetType, 'dashboard_file' | 'metric_file' | 'collection'>[];
|
|
||||||
num_results?: number;
|
|
||||||
}) => {
|
|
||||||
return mainApi.post<BusterSearchResult[]>('/search', params).then((res) => res.data);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { isServer } from '@tanstack/react-query';
|
import { isServer } from '@tanstack/react-query';
|
||||||
import type { AxiosRequestHeaders } from 'axios';
|
import type { AxiosRequestHeaders } from 'axios';
|
||||||
import axios, { type AxiosError, type InternalAxiosRequestConfig } from 'axios';
|
import axios, { type AxiosError, type InternalAxiosRequestConfig } from 'axios';
|
||||||
|
import qs from 'qs';
|
||||||
import { getSupabaseSession } from '@/integrations/supabase/getSupabaseUserClient';
|
import { getSupabaseSession } from '@/integrations/supabase/getSupabaseUserClient';
|
||||||
import { Route as AuthRoute } from '@/routes/auth.login';
|
import { Route as AuthRoute } from '@/routes/auth.login';
|
||||||
import { BASE_URL_V2 } from './config';
|
import { BASE_URL_V2 } from './config';
|
||||||
|
@ -15,6 +16,9 @@ export const createAxiosInstance = (baseURL = BASE_URL_V2) => {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
|
paramsSerializer: (params) => {
|
||||||
|
return qs.stringify(params, { arrayFormat: 'repeat' }); //💰
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Response interceptor with retry logic for auth errors
|
// Response interceptor with retry logic for auth errors
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
|
import type { SearchTextRequest, SearchTextResponse } from '@buster/server-shared';
|
||||||
import { queryOptions } from '@tanstack/react-query';
|
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]) =>
|
export const getSearchResult = (params: SearchTextRequest) =>
|
||||||
queryOptions<BusterSearchResult[]>({
|
queryOptions<SearchTextResponse>({
|
||||||
queryKey: ['search', 'results', params] as const,
|
queryKey: ['search', 'results', params] as const,
|
||||||
staleTime: 1000 * 15, // 15 seconds,
|
staleTime: 1000 * 15, // 15 seconds,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
import type { SearchTextResponse } from '@buster/server-shared/search';
|
||||||
import type { ShareAssetType } from '@buster/server-shared/share';
|
import type { ShareAssetType } from '@buster/server-shared/share';
|
||||||
import React, { useLayoutEffect, useMemo, useState } from 'react';
|
import React, { useLayoutEffect, useMemo, useState } from 'react';
|
||||||
import type { BusterSearchResult } from '@/api/asset_interfaces/search';
|
|
||||||
import {
|
import {
|
||||||
useAddAndRemoveAssetsFromCollection,
|
useAddAndRemoveAssetsFromCollection,
|
||||||
useGetCollection,
|
useGetCollection,
|
||||||
|
@ -33,8 +33,9 @@ export const AddToCollectionModal: React.FC<{
|
||||||
|
|
||||||
const { data: searchResults } = useSearch({
|
const { data: searchResults } = useSearch({
|
||||||
query: debouncedSearchTerm,
|
query: debouncedSearchTerm,
|
||||||
asset_types: ['metric_file', 'dashboard_file'],
|
assetTypes: ['metric_file', 'dashboard_file'],
|
||||||
num_results: 100,
|
page_size: 50,
|
||||||
|
page: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [selectedAssets, setSelectedAssets] = useState<SelectedAsset[]>([]);
|
const [selectedAssets, setSelectedAssets] = useState<SelectedAsset[]>([]);
|
||||||
|
@ -42,13 +43,13 @@ export const AddToCollectionModal: React.FC<{
|
||||||
return selectedAssets.map((asset) => asset.id);
|
return selectedAssets.map((asset) => asset.id);
|
||||||
}, [selectedAssets]);
|
}, [selectedAssets]);
|
||||||
|
|
||||||
const columns = useMemo<InputSelectModalProps<BusterSearchResult>['columns']>(
|
const columns = useMemo<InputSelectModalProps<SearchTextResponse['data'][number]>['columns']>(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
title: 'Name',
|
title: 'Name',
|
||||||
dataIndex: 'name',
|
dataIndex: 'title',
|
||||||
render: (name, data) => {
|
render: (name, record) => {
|
||||||
const Icon = assetTypeToIcon(data.type) || ASSET_ICONS.metrics;
|
const Icon = assetTypeToIcon(record.assetType) || ASSET_ICONS.metrics;
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<span className="text-icon-color">
|
<span className="text-icon-color">
|
||||||
|
@ -61,7 +62,7 @@ export const AddToCollectionModal: React.FC<{
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Updated',
|
title: 'Updated',
|
||||||
dataIndex: 'updated_at',
|
dataIndex: 'updatedAt',
|
||||||
width: 140,
|
width: 140,
|
||||||
render: (value: string) => {
|
render: (value: string) => {
|
||||||
return formatDate({
|
return formatDate({
|
||||||
|
@ -74,10 +75,10 @@ export const AddToCollectionModal: React.FC<{
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
const rows: BusterListRowItem<BusterSearchResult>[] = useMemo(() => {
|
const rows: BusterListRowItem<SearchTextResponse['data'][number]>[] = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
searchResults?.map((asset) => ({
|
searchResults?.data?.map((asset) => ({
|
||||||
id: asset.id,
|
id: asset.assetId,
|
||||||
data: asset,
|
data: asset,
|
||||||
})) || []
|
})) || []
|
||||||
);
|
);
|
||||||
|
@ -86,7 +87,7 @@ export const AddToCollectionModal: React.FC<{
|
||||||
const createKeySearchResultMap = useMemoizedFn(() => {
|
const createKeySearchResultMap = useMemoizedFn(() => {
|
||||||
const map = new Map<string, SelectedAsset>();
|
const map = new Map<string, SelectedAsset>();
|
||||||
rows.forEach((asset) => {
|
rows.forEach((asset) => {
|
||||||
if (asset.data?.type) map.set(asset.id, { type: asset.data?.type, id: asset.id });
|
if (asset.data?.assetType) map.set(asset.id, { type: asset.data?.assetType, id: asset.id });
|
||||||
});
|
});
|
||||||
return map;
|
return map;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import type { SearchTextRequest, SearchTextResponse } from '@buster/server-shared/search';
|
||||||
import type { BusterSearchResult } from '@/api/asset_interfaces/search';
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { useSearch } from '@/api/buster_rest/search';
|
import { useSearch } from '@/api/buster_rest/search';
|
||||||
import { Button } from '@/components/ui/buttons';
|
import { Button } from '@/components/ui/buttons';
|
||||||
import {
|
import {
|
||||||
|
@ -9,6 +9,7 @@ import {
|
||||||
import { useDebounce } from '@/hooks/useDebounce';
|
import { useDebounce } from '@/hooks/useDebounce';
|
||||||
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
|
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
|
||||||
import { formatDate } from '@/lib/date';
|
import { formatDate } from '@/lib/date';
|
||||||
|
import { assetTypeToIcon } from '../icons/assetIcons';
|
||||||
|
|
||||||
export const AddMetricModal: React.FC<{
|
export const AddMetricModal: React.FC<{
|
||||||
open: boolean;
|
open: boolean;
|
||||||
|
@ -46,21 +47,34 @@ export const AddMetricModal: React.FC<{
|
||||||
const { data: searchResults } = useSearch(
|
const { data: searchResults } = useSearch(
|
||||||
{
|
{
|
||||||
query: debouncedSearchTerm,
|
query: debouncedSearchTerm,
|
||||||
asset_types: ['metric_file'],
|
assetTypes: ['metric_file'],
|
||||||
num_results: 100,
|
page_size: 25,
|
||||||
},
|
page: 1,
|
||||||
{ enabled: true }
|
} 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',
|
title: 'Title',
|
||||||
dataIndex: 'name',
|
dataIndex: 'title',
|
||||||
|
render: (value, record) => {
|
||||||
|
const Icon = assetTypeToIcon(record.assetType);
|
||||||
|
return (
|
||||||
|
<div className="flex items-center gap-1.5">
|
||||||
|
<span className="text-icon-color">
|
||||||
|
<Icon />
|
||||||
|
</span>
|
||||||
|
{/* biome-ignore lint/security/noDangerouslySetInnerHtml: this endpoint is sanitized */}
|
||||||
|
<span dangerouslySetInnerHTML={{ __html: value }}></span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Updated',
|
title: 'Updated at',
|
||||||
dataIndex: 'updated_at',
|
dataIndex: 'updatedAt',
|
||||||
width: 140,
|
width: 140,
|
||||||
render: (value) => {
|
render: (value) => {
|
||||||
return formatDate({
|
return formatDate({
|
||||||
|
@ -76,8 +90,8 @@ export const AddMetricModal: React.FC<{
|
||||||
const rows = useMemo(() => {
|
const rows = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
searchResults?.map((result) => ({
|
searchResults?.map((result) => ({
|
||||||
id: result.id,
|
id: result.assetId,
|
||||||
dataTestId: `item-${result.id}`,
|
dataTestId: `item-${result.assetId}`,
|
||||||
data: result,
|
data: result,
|
||||||
})) || []
|
})) || []
|
||||||
);
|
);
|
||||||
|
@ -100,7 +114,7 @@ export const AddMetricModal: React.FC<{
|
||||||
const item = rows.find((row) => row.id === id);
|
const item = rows.find((row) => row.id === id);
|
||||||
return {
|
return {
|
||||||
id: id,
|
id: id,
|
||||||
name: item?.data?.name || id,
|
name: item?.data?.title || id,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ import {
|
||||||
SquareChart,
|
SquareChart,
|
||||||
Table,
|
Table,
|
||||||
} from '@/components/ui/icons';
|
} from '@/components/ui/icons';
|
||||||
import type { iconProps } from '@/components/ui/icons/NucleoIconOutlined/iconProps';
|
|
||||||
import SquareChartPlus from '@/components/ui/icons/NucleoIconOutlined/square-chart-plus';
|
import SquareChartPlus from '@/components/ui/icons/NucleoIconOutlined/square-chart-plus';
|
||||||
|
|
||||||
export const ASSET_ICONS = {
|
export const ASSET_ICONS = {
|
||||||
|
|
|
@ -16,7 +16,6 @@ export type MetricChartCardProps = {
|
||||||
metricId: string;
|
metricId: string;
|
||||||
versionNumber: number | undefined;
|
versionNumber: number | undefined;
|
||||||
readOnly?: boolean;
|
readOnly?: boolean;
|
||||||
className?: string;
|
|
||||||
attributes?: DraggableAttributes;
|
attributes?: DraggableAttributes;
|
||||||
listeners?: DraggableSyntheticListeners;
|
listeners?: DraggableSyntheticListeners;
|
||||||
headerSecondaryContent?: React.ReactNode;
|
headerSecondaryContent?: React.ReactNode;
|
||||||
|
@ -25,7 +24,7 @@ export type MetricChartCardProps = {
|
||||||
renderChartContent?: boolean; // we do this to avoid expensive rendering if off screen
|
renderChartContent?: boolean; // we do this to avoid expensive rendering if off screen
|
||||||
disableTooltip?: boolean;
|
disableTooltip?: boolean;
|
||||||
cacheDataId?: string;
|
cacheDataId?: string;
|
||||||
};
|
} & React.HTMLAttributes<HTMLDivElement>;
|
||||||
|
|
||||||
const stableMetricSelect = ({
|
const stableMetricSelect = ({
|
||||||
chart_config,
|
chart_config,
|
||||||
|
@ -62,6 +61,7 @@ export const MetricChartCard = React.memo(
|
||||||
renderChartContent = true,
|
renderChartContent = true,
|
||||||
disableTooltip,
|
disableTooltip,
|
||||||
cacheDataId,
|
cacheDataId,
|
||||||
|
...rest
|
||||||
},
|
},
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
|
@ -102,6 +102,7 @@ export const MetricChartCard = React.memo(
|
||||||
errorData={errorData}
|
errorData={errorData}
|
||||||
isTable={isTable}
|
isTable={isTable}
|
||||||
className={className}
|
className={className}
|
||||||
|
{...rest}
|
||||||
>
|
>
|
||||||
<MetricViewChartHeader
|
<MetricViewChartHeader
|
||||||
name={name}
|
name={name}
|
||||||
|
@ -144,13 +145,12 @@ type MetricViewChartCardContainerProps = {
|
||||||
hasData: boolean;
|
hasData: boolean;
|
||||||
errorData: boolean;
|
errorData: boolean;
|
||||||
isTable: boolean;
|
isTable: boolean;
|
||||||
className?: string;
|
} & React.HTMLAttributes<HTMLDivElement>;
|
||||||
};
|
|
||||||
|
|
||||||
const MetricViewChartCardContainer = React.forwardRef<
|
const MetricViewChartCardContainer = React.forwardRef<
|
||||||
HTMLDivElement,
|
HTMLDivElement,
|
||||||
MetricViewChartCardContainerProps
|
MetricViewChartCardContainerProps
|
||||||
>(({ children, loadingData, hasData, errorData, isTable, className }, ref) => {
|
>(({ children, loadingData, hasData, errorData, isTable, className, ...divProps }, ref) => {
|
||||||
const cardClass = React.useMemo(() => {
|
const cardClass = React.useMemo(() => {
|
||||||
if (loadingData || errorData || !hasData) return 'h-full max-h-[600px]';
|
if (loadingData || errorData || !hasData) return 'h-full max-h-[600px]';
|
||||||
if (isTable) return 'h-full';
|
if (isTable) return 'h-full';
|
||||||
|
@ -161,6 +161,7 @@ const MetricViewChartCardContainer = React.forwardRef<
|
||||||
<MetricViewChartProvider>
|
<MetricViewChartProvider>
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
{...divProps}
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-background flex flex-col overflow-hidden rounded border shadow',
|
'bg-background flex flex-col overflow-hidden rounded border shadow',
|
||||||
cardClass,
|
cardClass,
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { MetricChartCard } from '@/components/features/metrics/MetricChartCard';
|
||||||
import { ReportMetricThreeDotMenu } from '@/components/features/metrics/ReportMetricItem';
|
import { ReportMetricThreeDotMenu } from '@/components/features/metrics/ReportMetricItem';
|
||||||
import { useGetReportParams } from '@/context/Reports/useGetReportParams';
|
import { useGetReportParams } from '@/context/Reports/useGetReportParams';
|
||||||
import { useInViewport } from '@/hooks/useInViewport';
|
import { useInViewport } from '@/hooks/useInViewport';
|
||||||
|
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
|
||||||
|
|
||||||
export const MetricContent = React.memo(
|
export const MetricContent = React.memo(
|
||||||
({
|
({
|
||||||
|
@ -30,6 +31,10 @@ export const MetricContent = React.memo(
|
||||||
}
|
}
|
||||||
const renderChart = inViewport || isExportMode || hasBeenInViewport.current;
|
const renderChart = inViewport || isExportMode || hasBeenInViewport.current;
|
||||||
|
|
||||||
|
const handleCopy = useMemoizedFn((e: React.ClipboardEvent<HTMLDivElement>) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MetricChartCard
|
<MetricChartCard
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
@ -50,6 +55,7 @@ export const MetricContent = React.memo(
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
onCopy={handleCopy}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,3 +53,8 @@ p {
|
||||||
th {
|
th {
|
||||||
@apply text-base font-normal;
|
@apply text-base font-normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
strong,
|
||||||
|
b {
|
||||||
|
@apply font-semibold;
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import z from 'zod';
|
import z from 'zod';
|
||||||
|
import { AssetTypeSchema } from './asset';
|
||||||
|
|
||||||
export const TextSearchResultSchema = z.object({
|
export const TextSearchResultSchema = z.object({
|
||||||
assetId: z.string().uuid(),
|
assetId: z.string().uuid(),
|
||||||
assetType: z.string(),
|
assetType: AssetTypeSchema,
|
||||||
title: z.string(),
|
title: z.string(),
|
||||||
additionalText: z.string().nullable(),
|
additionalText: z.string().nullable(),
|
||||||
updatedAt: z.string().datetime(),
|
updatedAt: z.string().datetime(),
|
||||||
|
|
|
@ -99,6 +99,10 @@
|
||||||
"./healthcheck": {
|
"./healthcheck": {
|
||||||
"types": "./dist/healthcheck/index.d.ts",
|
"types": "./dist/healthcheck/index.d.ts",
|
||||||
"default": "./dist/healthcheck/index.js"
|
"default": "./dist/healthcheck/index.js"
|
||||||
|
},
|
||||||
|
"./search": {
|
||||||
|
"types": "./dist/search/index.d.ts",
|
||||||
|
"default": "./dist/search/index.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"module": "src/index.ts",
|
"module": "src/index.ts",
|
||||||
|
|
|
@ -28,7 +28,8 @@ export const SearchTextRequestSchema = z
|
||||||
}
|
}
|
||||||
return Boolean(val);
|
return Boolean(val);
|
||||||
}, z.boolean())
|
}, z.boolean())
|
||||||
.default(false),
|
.default(false)
|
||||||
|
.optional(),
|
||||||
endDate: z.string().datetime().optional(),
|
endDate: z.string().datetime().optional(),
|
||||||
startDate: z.string().datetime().optional(),
|
startDate: z.string().datetime().optional(),
|
||||||
})
|
})
|
||||||
|
|
|
@ -18,6 +18,6 @@ export const PaginatedResponseSchema = <T>(schema: z.ZodType<T>) =>
|
||||||
export type PaginatedResponse<T> = z.infer<ReturnType<typeof PaginatedResponseSchema<T>>>;
|
export type PaginatedResponse<T> = z.infer<ReturnType<typeof PaginatedResponseSchema<T>>>;
|
||||||
|
|
||||||
export const PaginatedRequestSchema = z.object({
|
export const PaginatedRequestSchema = z.object({
|
||||||
page: z.coerce.number().min(1).default(1),
|
page: z.coerce.number().min(1).optional().default(1),
|
||||||
page_size: z.coerce.number().min(1).max(5000).default(250),
|
page_size: z.coerce.number().min(1).max(5000).default(250),
|
||||||
});
|
});
|
||||||
|
|
|
@ -703,6 +703,9 @@ importers:
|
||||||
'@tiptap/suggestion':
|
'@tiptap/suggestion':
|
||||||
specifier: ^3.5.0
|
specifier: ^3.5.0
|
||||||
version: 3.5.0(@tiptap/core@3.5.0(@tiptap/pm@3.5.0))(@tiptap/pm@3.5.0)
|
version: 3.5.0(@tiptap/core@3.5.0(@tiptap/pm@3.5.0))(@tiptap/pm@3.5.0)
|
||||||
|
'@types/qs':
|
||||||
|
specifier: ^6.14.0
|
||||||
|
version: 6.14.0
|
||||||
'@udecode/cn':
|
'@udecode/cn':
|
||||||
specifier: ^49.0.15
|
specifier: ^49.0.15
|
||||||
version: 49.0.15(@types/react@19.1.13)(class-variance-authority@0.7.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(tailwind-merge@3.3.1)
|
version: 49.0.15(@types/react@19.1.13)(class-variance-authority@0.7.1)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(tailwind-merge@3.3.1)
|
||||||
|
@ -793,6 +796,9 @@ importers:
|
||||||
posthog-js:
|
posthog-js:
|
||||||
specifier: ^1.268.1
|
specifier: ^1.268.1
|
||||||
version: 1.268.1
|
version: 1.268.1
|
||||||
|
qs:
|
||||||
|
specifier: ^6.14.0
|
||||||
|
version: 6.14.0
|
||||||
react:
|
react:
|
||||||
specifier: 'catalog:'
|
specifier: 'catalog:'
|
||||||
version: 19.1.1
|
version: 19.1.1
|
||||||
|
@ -6356,6 +6362,9 @@ packages:
|
||||||
'@types/prismjs@1.26.5':
|
'@types/prismjs@1.26.5':
|
||||||
resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==}
|
resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==}
|
||||||
|
|
||||||
|
'@types/qs@6.14.0':
|
||||||
|
resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==}
|
||||||
|
|
||||||
'@types/react-dom@19.1.9':
|
'@types/react-dom@19.1.9':
|
||||||
resolution: {integrity: sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==}
|
resolution: {integrity: sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -19323,6 +19332,8 @@ snapshots:
|
||||||
|
|
||||||
'@types/prismjs@1.26.5': {}
|
'@types/prismjs@1.26.5': {}
|
||||||
|
|
||||||
|
'@types/qs@6.14.0': {}
|
||||||
|
|
||||||
'@types/react-dom@19.1.9(@types/react@19.1.13)':
|
'@types/react-dom@19.1.9(@types/react@19.1.13)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/react': 19.1.13
|
'@types/react': 19.1.13
|
||||||
|
@ -19591,7 +19602,7 @@ snapshots:
|
||||||
sirv: 3.0.1
|
sirv: 3.0.1
|
||||||
tinyglobby: 0.2.14
|
tinyglobby: 0.2.14
|
||||||
tinyrainbow: 2.0.0
|
tinyrainbow: 2.0.0
|
||||||
vitest: 3.2.4(@edge-runtime/vm@3.2.0)(@types/debug@4.1.12)(@types/node@22.18.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.5.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.30.1)(msw@2.11.3(@types/node@22.18.1)(typescript@5.9.2))(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)
|
vitest: 3.2.4(@edge-runtime/vm@3.2.0)(@types/debug@4.1.12)(@types/node@24.3.1)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(jiti@2.5.1)(jsdom@27.0.0(postcss@8.5.6))(lightningcss@1.30.1)(msw@2.11.3(@types/node@24.3.1)(typescript@5.9.2))(sass@1.93.1)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1)
|
||||||
|
|
||||||
'@vitest/utils@3.2.4':
|
'@vitest/utils@3.2.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|
Loading…
Reference in New Issue