mirror of https://github.com/buster-so/buster.git
updated metric data requests
This commit is contained in:
parent
b3c4bad371
commit
613d4bcfe6
|
@ -88,6 +88,7 @@
|
||||||
"@storybook/react": "^8.6.4",
|
"@storybook/react": "^8.6.4",
|
||||||
"@storybook/test": "^8.6.4",
|
"@storybook/test": "^8.6.4",
|
||||||
"@tailwindcss/postcss": "4.0.12",
|
"@tailwindcss/postcss": "4.0.12",
|
||||||
|
"@testing-library/react": "^16.2.0",
|
||||||
"@types/canvas-confetti": "^1.9.0",
|
"@types/canvas-confetti": "^1.9.0",
|
||||||
"@types/js-cookie": "^3.0.6",
|
"@types/js-cookie": "^3.0.6",
|
||||||
"@types/lodash": "^4.17.16",
|
"@types/lodash": "^4.17.16",
|
||||||
|
@ -6745,6 +6746,34 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@testing-library/react": {
|
||||||
|
"version": "16.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.2.0.tgz",
|
||||||
|
"integrity": "sha512-2cSskAvA1QNtKc8Y9VJQRv0tm3hLVgxRGDB+KYhIaPQJ1I+RHbhIXcM+zClKXzMes/wshsMVzf4B9vS4IZpqDQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime": "^7.12.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@testing-library/dom": "^10.0.0",
|
||||||
|
"@types/react": "^18.0.0 || ^19.0.0",
|
||||||
|
"@types/react-dom": "^18.0.0 || ^19.0.0",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"@types/react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@testing-library/user-event": {
|
"node_modules/@testing-library/user-event": {
|
||||||
"version": "14.5.2",
|
"version": "14.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz",
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
"@storybook/react": "^8.6.4",
|
"@storybook/react": "^8.6.4",
|
||||||
"@storybook/test": "^8.6.4",
|
"@storybook/test": "^8.6.4",
|
||||||
"@tailwindcss/postcss": "4.0.12",
|
"@tailwindcss/postcss": "4.0.12",
|
||||||
|
"@testing-library/react": "^16.2.0",
|
||||||
"@types/canvas-confetti": "^1.9.0",
|
"@types/canvas-confetti": "^1.9.0",
|
||||||
"@types/js-cookie": "^3.0.6",
|
"@types/js-cookie": "^3.0.6",
|
||||||
"@types/lodash": "^4.17.16",
|
"@types/lodash": "^4.17.16",
|
||||||
|
|
|
@ -2,8 +2,7 @@ import { DataMetadata, IDataResult } from './interfaces';
|
||||||
|
|
||||||
export type BusterMetricData = {
|
export type BusterMetricData = {
|
||||||
data: IDataResult | null;
|
data: IDataResult | null;
|
||||||
dataFromRerun?: IDataResult;
|
dataFromRerun?: IDataResult; //this is actually only used in the UI. maybe move this to ?
|
||||||
data_metadata: DataMetadata;
|
data_metadata: DataMetadata;
|
||||||
code: string | null;
|
|
||||||
metricId: string;
|
metricId: string;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { QueryClient } from '@tanstack/react-query';
|
import { QueryClient } from '@tanstack/react-query';
|
||||||
import { useMemoizedFn } from '@/hooks';
|
import { useMemoizedFn } from '@/hooks';
|
||||||
import { getMetric, getMetric_server, listMetrics, listMetrics_server } from './requests';
|
import {
|
||||||
|
getMetric,
|
||||||
|
getMetric_server,
|
||||||
|
getMetricData,
|
||||||
|
listMetrics,
|
||||||
|
listMetrics_server
|
||||||
|
} from './requests';
|
||||||
import type { GetMetricParams, ListMetricsParams } from './interfaces';
|
import type { GetMetricParams, ListMetricsParams } from './interfaces';
|
||||||
import { upgradeMetricToIMetric } from '@/lib/chat';
|
import { upgradeMetricToIMetric } from '@/lib/chat';
|
||||||
import { queryKeys } from '@/api/query_keys';
|
import { queryKeys } from '@/api/query_keys';
|
||||||
|
@ -61,3 +67,15 @@ export const prefetchGetMetricsList = async (
|
||||||
|
|
||||||
return queryClient;
|
return queryClient;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useGetMetricData = (params: { id: string }) => {
|
||||||
|
const queryFn = useMemoizedFn(() => {
|
||||||
|
return getMetricData(params);
|
||||||
|
});
|
||||||
|
|
||||||
|
return useQuery({
|
||||||
|
...queryKeys.metricsGetData(params.id),
|
||||||
|
queryFn,
|
||||||
|
enabled: !!params.id
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import { mainApi } from '../instances';
|
import { mainApi } from '../instances';
|
||||||
import { serverFetch } from '@/api/createServerInstance';
|
import { serverFetch } from '@/api/createServerInstance';
|
||||||
import type { GetMetricParams, ListMetricsParams } from './interfaces';
|
import type { GetMetricParams, ListMetricsParams } from './interfaces';
|
||||||
import type { BusterMetric, BusterMetricListItem } from '@/api/asset_interfaces/metric';
|
import type {
|
||||||
|
BusterMetric,
|
||||||
|
BusterMetricData,
|
||||||
|
BusterMetricListItem
|
||||||
|
} from '@/api/asset_interfaces/metric';
|
||||||
|
|
||||||
export const getMetric = async ({ id, password }: GetMetricParams) => {
|
export const getMetric = async ({ id, password }: GetMetricParams) => {
|
||||||
return mainApi
|
return mainApi
|
||||||
|
@ -24,3 +28,7 @@ export const listMetrics = async (params: ListMetricsParams) => {
|
||||||
export const listMetrics_server = async (params: ListMetricsParams) => {
|
export const listMetrics_server = async (params: ListMetricsParams) => {
|
||||||
return await serverFetch<BusterMetricListItem[]>('/metrics/list', { params });
|
return await serverFetch<BusterMetricListItem[]>('/metrics/list', { params });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getMetricData = async (params: { id: string }) => {
|
||||||
|
return mainApi.get<BusterMetricData>(`/metrics/data`, { params }).then((res) => res.data);
|
||||||
|
};
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
import type { BusterChartConfigProps, DataMetadata, IDataResult } from '../../asset_interfaces';
|
|
||||||
import type { EventBase } from '../base_interfaces';
|
|
||||||
|
|
||||||
export type MetricEvent_fetchingData = {
|
|
||||||
metric_id: string;
|
|
||||||
data: IDataResult;
|
|
||||||
data_metadata: DataMetadata;
|
|
||||||
chart_config: BusterChartConfigProps;
|
|
||||||
code: string | null;
|
|
||||||
} & EventBase;
|
|
|
@ -5,7 +5,6 @@ import {
|
||||||
MetricSubscribeRequest,
|
MetricSubscribeRequest,
|
||||||
MetricUpdateRequest,
|
MetricUpdateRequest,
|
||||||
MetricDeleteRequest,
|
MetricDeleteRequest,
|
||||||
MetricGetDataByMessageIdRequest,
|
|
||||||
MetricSearchRequest,
|
MetricSearchRequest,
|
||||||
MetricDuplicateRequest
|
MetricDuplicateRequest
|
||||||
} from '@/api/request_interfaces/metrics';
|
} from '@/api/request_interfaces/metrics';
|
||||||
|
@ -41,14 +40,6 @@ export type MetricUpdateMetric = BusterSocketRequestBase<'/metrics/update', Metr
|
||||||
*/
|
*/
|
||||||
export type MetricDelete = BusterSocketRequestBase<'/metrics/delete', MetricDeleteRequest>;
|
export type MetricDelete = BusterSocketRequestBase<'/metrics/delete', MetricDeleteRequest>;
|
||||||
|
|
||||||
/**
|
|
||||||
* Request payload for retrieving metric data by message ID
|
|
||||||
*/
|
|
||||||
export type MetricGetDataByMessageId = BusterSocketRequestBase<
|
|
||||||
'/metrics/data',
|
|
||||||
MetricGetDataByMessageIdRequest
|
|
||||||
>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request payload for searching metrics
|
* Request payload for searching metrics
|
||||||
*/
|
*/
|
||||||
|
@ -69,5 +60,4 @@ export type MetricEmits =
|
||||||
| MetricUpdateMetric
|
| MetricUpdateMetric
|
||||||
| MetricSubscribeToMetric
|
| MetricSubscribeToMetric
|
||||||
| MetricDelete
|
| MetricDelete
|
||||||
| MetricGetDataByMessageId
|
|
||||||
| MetricSearch;
|
| MetricSearch;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { BusterMetric, BusterMetricListItem } from '@/api/asset_interfaces/metric';
|
import { BusterMetric, BusterMetricListItem } from '@/api/asset_interfaces/metric';
|
||||||
import { MetricEvent_fetchingData } from './eventsInterfaces';
|
|
||||||
|
|
||||||
export enum MetricResponses {
|
export enum MetricResponses {
|
||||||
'/metrics/list:getMetricList' = '/metrics/list:getMetricList',
|
'/metrics/list:getMetricList' = '/metrics/list:getMetricList',
|
||||||
|
@ -29,12 +28,6 @@ export type Metric_Unsubscribe = {
|
||||||
onError?: (d: unknown) => void;
|
onError?: (d: unknown) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MetricGet_fetchingData = {
|
|
||||||
route: '/metrics/get:fetchingData';
|
|
||||||
callback: (d: MetricEvent_fetchingData) => void;
|
|
||||||
onError?: (d: unknown) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type MetricList_updateMetricList = {
|
export type MetricList_updateMetricList = {
|
||||||
route: '/metrics/list:updateMetricList';
|
route: '/metrics/list:updateMetricList';
|
||||||
callback: (d: BusterMetricListItem[]) => void;
|
callback: (d: BusterMetricListItem[]) => void;
|
||||||
|
@ -61,5 +54,4 @@ export type MetricResponseTypes =
|
||||||
| MetricGet_updateMetricState
|
| MetricGet_updateMetricState
|
||||||
| MetricList_updateMetricList
|
| MetricList_updateMetricList
|
||||||
| MetricDelete_deleteMetricState
|
| MetricDelete_deleteMetricState
|
||||||
| MetricUpdate_updateMetricState
|
| MetricUpdate_updateMetricState;
|
||||||
| MetricGet_fetchingData;
|
|
||||||
|
|
|
@ -41,9 +41,16 @@ export const metricsGetDataByMessageId = (messageId: string) =>
|
||||||
staleTime: 60 * 60 * 1000 // 1 hour
|
staleTime: 60 * 60 * 1000 // 1 hour
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const metricsGetData = (id: string) =>
|
||||||
|
queryOptions<BusterMetricData>({
|
||||||
|
queryKey: ['metrics', 'data', id] as const,
|
||||||
|
staleTime: 3 * 60 * 60 * 1000 // 3 hours,
|
||||||
|
});
|
||||||
|
|
||||||
export const metricsQueryKeys = {
|
export const metricsQueryKeys = {
|
||||||
metricsGetMetric,
|
metricsGetMetric,
|
||||||
useMetricsGetMetric,
|
useMetricsGetMetric,
|
||||||
metricsGetList,
|
metricsGetList,
|
||||||
metricsGetDataByMessageId
|
metricsGetDataByMessageId,
|
||||||
|
metricsGetData
|
||||||
};
|
};
|
||||||
|
|
|
@ -70,14 +70,6 @@ export type MetricDeleteRequest = {
|
||||||
ids: string[];
|
ids: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Request payload for retrieving metric data by message ID
|
|
||||||
*/
|
|
||||||
export type MetricGetDataByMessageIdRequest = {
|
|
||||||
/** Message ID to retrieve metric data for */
|
|
||||||
id: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request payload for searching metrics
|
* Request payload for searching metrics
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import type { ColumnMetaData } from '@/api/asset_interfaces';
|
import type { ColumnMetaData } from '@/api/asset_interfaces/metric';
|
||||||
import type { BusterChartConfigProps } from './chartConfigProps';
|
import type { BusterChartConfigProps } from './chartConfigProps';
|
||||||
|
|
||||||
export type BusterChartProps = {
|
export type BusterChartProps = {
|
||||||
|
|
|
@ -12,11 +12,11 @@ export const AppCodeBlock: React.FC<{
|
||||||
wrapperClassName?: string;
|
wrapperClassName?: string;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
|
|
||||||
showCopyButton?: boolean;
|
showCopyButton?: boolean;
|
||||||
title?: string;
|
title?: string;
|
||||||
buttons?: React.ReactNode;
|
buttons?: React.ReactNode;
|
||||||
}> = React.memo(({ title, buttons, ...props }) => {
|
showLoader?: boolean;
|
||||||
|
}> = React.memo(({ title, buttons, showLoader, ...props }) => {
|
||||||
const {
|
const {
|
||||||
children,
|
children,
|
||||||
className = '',
|
className = '',
|
||||||
|
|
|
@ -44,14 +44,7 @@ const MOCK_DATA: Required<BusterMetricData> = {
|
||||||
data: mockData(),
|
data: mockData(),
|
||||||
metricId: faker.string.uuid(),
|
metricId: faker.string.uuid(),
|
||||||
data_metadata: dataMetadata,
|
data_metadata: dataMetadata,
|
||||||
dataFromRerun: null,
|
dataFromRerun: null
|
||||||
code: `SELECT
|
|
||||||
sales,
|
|
||||||
date,
|
|
||||||
product
|
|
||||||
FROM sales_data
|
|
||||||
WHERE date BETWEEN '2024-01-01' AND '2024-01-31'
|
|
||||||
ORDER BY date ASC`
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createMockData = (metricId: string): Required<BusterMetricData> => {
|
export const createMockData = (metricId: string): Required<BusterMetricData> => {
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
import { queryKeys } from '@/api/query_keys';
|
import { useGetMetricData } from '@/api/buster_rest/metrics';
|
||||||
import { useSocketQueryEmitAndOnce } from '@/api/buster_socket_query';
|
|
||||||
import type { BusterMetricData } from '@/api/asset_interfaces/metric';
|
|
||||||
|
|
||||||
export const useMetricDataIndividual = ({ metricId }: { metricId: string }) => {
|
export const useMetricDataIndividual = ({ metricId }: { metricId: string }) => {
|
||||||
const {
|
const {
|
||||||
|
@ -9,25 +7,7 @@ export const useMetricDataIndividual = ({ metricId }: { metricId: string }) => {
|
||||||
refetch: refetchMetricData,
|
refetch: refetchMetricData,
|
||||||
dataUpdatedAt: metricDataUpdatedAt,
|
dataUpdatedAt: metricDataUpdatedAt,
|
||||||
error: metricDataError
|
error: metricDataError
|
||||||
} = useSocketQueryEmitAndOnce({
|
} = useGetMetricData({ id: metricId });
|
||||||
emitEvent: {
|
|
||||||
route: '/metrics/data',
|
|
||||||
payload: { id: metricId }
|
|
||||||
},
|
|
||||||
responseEvent: '/metrics/get:fetchingData',
|
|
||||||
options: queryKeys.chatsMessagesFetchingData(metricId),
|
|
||||||
callback: (currentData, responseData) => {
|
|
||||||
const metricId = responseData.metric_id;
|
|
||||||
const newMetricData: BusterMetricData = {
|
|
||||||
...currentData,
|
|
||||||
metricId,
|
|
||||||
data: responseData.data ?? currentData?.data!,
|
|
||||||
data_metadata: responseData.data_metadata ?? currentData?.data_metadata!,
|
|
||||||
code: responseData.code
|
|
||||||
};
|
|
||||||
return newMetricData;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
metricData,
|
metricData,
|
||||||
|
|
|
@ -51,7 +51,6 @@ export const useSQLProvider = () => {
|
||||||
metricId,
|
metricId,
|
||||||
data,
|
data,
|
||||||
data_metadata,
|
data_metadata,
|
||||||
code,
|
|
||||||
isDataFromRerun
|
isDataFromRerun
|
||||||
}: {
|
}: {
|
||||||
metricId: string;
|
metricId: string;
|
||||||
|
@ -66,8 +65,7 @@ export const useSQLProvider = () => {
|
||||||
queryClient.setQueryData(options.queryKey, {
|
queryClient.setQueryData(options.queryKey, {
|
||||||
...currentData!,
|
...currentData!,
|
||||||
[setter]: data,
|
[setter]: data,
|
||||||
data_metadata,
|
data_metadata
|
||||||
code
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,7 +78,7 @@ export const useSQLProvider = () => {
|
||||||
if (!originalConfigs.current[metricId]) {
|
if (!originalConfigs.current[metricId]) {
|
||||||
originalConfigs.current[metricId] = {
|
originalConfigs.current[metricId] = {
|
||||||
chartConfig: metricMessage?.chart_config!,
|
chartConfig: metricMessage?.chart_config!,
|
||||||
code: currentMessageData?.code!,
|
code: metricMessage?.code!,
|
||||||
data: currentMessageData?.data!,
|
data: currentMessageData?.data!,
|
||||||
dataMetadata: currentMessageData?.data_metadata!
|
dataMetadata: currentMessageData?.data_metadata!
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,9 +6,9 @@ import { useFavoriteProvider } from './useFavoriteProvider';
|
||||||
import { useGetMyUserInfo } from '@/api/buster_rest/users';
|
import { useGetMyUserInfo } from '@/api/buster_rest/users';
|
||||||
import { useSupabaseContext } from '../Supabase';
|
import { useSupabaseContext } from '../Supabase';
|
||||||
import { createContext, useContextSelector } from 'use-context-selector';
|
import { createContext, useContextSelector } from 'use-context-selector';
|
||||||
import { checkIfUserIsAdmin } from './helpers';
|
|
||||||
import { useUserOrganization } from './useUserOrganization';
|
import { useUserOrganization } from './useUserOrganization';
|
||||||
import { useInviteUser } from './useInviteUser';
|
import { useInviteUser } from './useInviteUser';
|
||||||
|
import { checkIfUserIsAdmin } from '@/lib/user';
|
||||||
|
|
||||||
export const useUserConfigProvider = ({ userInfo }: { userInfo: BusterUserResponse | null }) => {
|
export const useUserConfigProvider = ({ userInfo }: { userInfo: BusterUserResponse | null }) => {
|
||||||
const isAnonymousUser = useSupabaseContext((state) => state.isAnonymousUser);
|
const isAnonymousUser = useSupabaseContext((state) => state.isAnonymousUser);
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
import { BusterOrganizationRole } from '@/api/asset_interfaces/organizations';
|
|
||||||
import { type BusterUserResponse } from '@/api/asset_interfaces/users';
|
|
||||||
|
|
||||||
export const checkIfUserIsAdmin = (userInfo?: BusterUserResponse | null): boolean => {
|
|
||||||
if (!userInfo) return false;
|
|
||||||
|
|
||||||
const userOrganization = userInfo?.organizations?.[0];
|
|
||||||
|
|
||||||
if (!userOrganization) return false;
|
|
||||||
|
|
||||||
const userRole = userOrganization.role;
|
|
||||||
|
|
||||||
return (
|
|
||||||
userRole === BusterOrganizationRole.DATA_ADMIN ||
|
|
||||||
userRole === BusterOrganizationRole.WORKSPACE_ADMIN
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -1,2 +1 @@
|
||||||
export * from './UserConfigProvider';
|
export * from './UserConfigProvider';
|
||||||
export * from './helpers';
|
|
||||||
|
|
|
@ -24,5 +24,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"**/*.stories.tsx",
|
||||||
|
"**/*.stories.ts",
|
||||||
|
"**/*.test.tsx",
|
||||||
|
"**/*.test.ts"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue