mirror of https://github.com/buster-so/buster.git
make new saving to dashboard endpoints
This commit is contained in:
parent
abb54f4dbb
commit
6a30100f3f
|
@ -0,0 +1,2 @@
|
|||
export * from './addMetricToDashboard';
|
||||
export * from './removeMetricFromDashboard';
|
|
@ -0,0 +1,266 @@
|
|||
import { removeMetricFromDashboardConfig } from './removeMetricFromDashboard';
|
||||
import type { BusterDashboard } from '@/api/asset_interfaces/dashboard';
|
||||
|
||||
describe('removeMetricFromDashboardConfig', () => {
|
||||
const createEmptyConfig = (): BusterDashboard['config'] => ({
|
||||
rows: []
|
||||
});
|
||||
|
||||
const createConfigWithRows = (
|
||||
rows: BusterDashboard['config']['rows']
|
||||
): BusterDashboard['config'] => ({
|
||||
rows
|
||||
});
|
||||
|
||||
it('should return the same config if no metrics to remove are provided', () => {
|
||||
const config = createConfigWithRows([
|
||||
{
|
||||
id: 'row1',
|
||||
items: [{ id: 'metric1' }],
|
||||
columnSizes: [12],
|
||||
rowHeight: 320
|
||||
}
|
||||
]);
|
||||
const result = removeMetricFromDashboardConfig([], config);
|
||||
expect(result.rows).toHaveLength(1);
|
||||
expect(result.rows![0].items).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should remove a single metric from a single row', () => {
|
||||
const config = createConfigWithRows([
|
||||
{
|
||||
id: 'row1',
|
||||
items: [{ id: 'metric1' }, { id: 'metric2' }],
|
||||
columnSizes: [6, 6],
|
||||
rowHeight: 320
|
||||
}
|
||||
]);
|
||||
const result = removeMetricFromDashboardConfig(['metric1'], config);
|
||||
|
||||
expect(result.rows).toHaveLength(1);
|
||||
expect(result.rows![0].items).toHaveLength(1);
|
||||
expect(result.rows![0].items[0].id).toBe('metric2');
|
||||
expect(result.rows![0].items.length).toBe(1);
|
||||
expect(result.rows![0].columnSizes).toEqual([12]); // Single column takes full width
|
||||
});
|
||||
|
||||
it('should remove multiple metrics from a single row', () => {
|
||||
const config = createConfigWithRows([
|
||||
{
|
||||
id: 'row1',
|
||||
items: [{ id: 'metric1' }, { id: 'metric2' }, { id: 'metric3' }, { id: 'metric4' }],
|
||||
columnSizes: [3, 3, 3, 3],
|
||||
rowHeight: 320
|
||||
}
|
||||
]);
|
||||
const result = removeMetricFromDashboardConfig(['metric1', 'metric3'], config);
|
||||
|
||||
expect(result.rows).toHaveLength(1);
|
||||
expect(result.rows![0].items).toHaveLength(2);
|
||||
expect(result.rows![0].items.map((item) => item.id)).toEqual(['metric2', 'metric4']);
|
||||
expect(result.rows![0].columnSizes).toEqual([6, 6]); // Two equal columns
|
||||
});
|
||||
|
||||
it('should remove entire row when all metrics in the row are removed', () => {
|
||||
const config = createConfigWithRows([
|
||||
{
|
||||
id: 'row1',
|
||||
items: [{ id: 'metric1' }, { id: 'metric2' }],
|
||||
columnSizes: [6, 6],
|
||||
rowHeight: 320
|
||||
},
|
||||
{
|
||||
id: 'row2',
|
||||
items: [{ id: 'metric3' }],
|
||||
columnSizes: [12],
|
||||
rowHeight: 320
|
||||
}
|
||||
]);
|
||||
const result = removeMetricFromDashboardConfig(['metric1', 'metric2'], config);
|
||||
|
||||
expect(result.rows).toHaveLength(1);
|
||||
expect(result.rows![0].items).toHaveLength(1);
|
||||
expect(result.rows![0].items.length).toBe(1);
|
||||
expect(result.rows![0].columnSizes).toEqual([12]);
|
||||
expect(result.rows![0].id).toBe('row2');
|
||||
expect(result.rows![0].items[0].id).toBe('metric3');
|
||||
});
|
||||
|
||||
it('should handle removing metrics from multiple rows', () => {
|
||||
const config = createConfigWithRows([
|
||||
{
|
||||
id: 'row1',
|
||||
items: [{ id: 'metric1' }, { id: 'metric2' }],
|
||||
columnSizes: [6, 6],
|
||||
rowHeight: 320
|
||||
},
|
||||
{
|
||||
id: 'row2',
|
||||
items: [{ id: 'metric3' }, { id: 'metric4' }],
|
||||
columnSizes: [6, 6],
|
||||
rowHeight: 320
|
||||
}
|
||||
]);
|
||||
const result = removeMetricFromDashboardConfig(['metric1', 'metric4'], config);
|
||||
|
||||
expect(result.rows).toHaveLength(2);
|
||||
expect(result.rows![0].items).toHaveLength(1);
|
||||
expect(result.rows![1].items).toHaveLength(1);
|
||||
expect(result.rows![0].items[0].id).toBe('metric2');
|
||||
expect(result.rows![1].items[0].id).toBe('metric3');
|
||||
expect(result.rows![0].columnSizes).toEqual([12]);
|
||||
expect(result.rows![1].columnSizes).toEqual([12]);
|
||||
});
|
||||
|
||||
it('should handle removing non-existent metrics', () => {
|
||||
const config = createConfigWithRows([
|
||||
{
|
||||
id: 'row1',
|
||||
items: [{ id: 'metric1' }, { id: 'metric2' }],
|
||||
columnSizes: [6, 6],
|
||||
rowHeight: 320
|
||||
}
|
||||
]);
|
||||
const result = removeMetricFromDashboardConfig(['nonexistent1', 'nonexistent2'], config);
|
||||
|
||||
expect(result.rows).toHaveLength(1);
|
||||
expect(result.rows![0].items).toHaveLength(2);
|
||||
expect(result.rows![0].columnSizes).toEqual([6, 6]);
|
||||
});
|
||||
|
||||
it('should handle empty config', () => {
|
||||
const config = createEmptyConfig();
|
||||
const result = removeMetricFromDashboardConfig(['metric1'], config);
|
||||
|
||||
expect(result.rows).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should preserve row properties while updating items and columnSizes', () => {
|
||||
const config = createConfigWithRows([
|
||||
{
|
||||
id: 'row1',
|
||||
items: [{ id: 'metric1' }, { id: 'metric2' }, { id: 'metric3' }],
|
||||
columnSizes: [4, 4, 4],
|
||||
rowHeight: 320
|
||||
}
|
||||
]);
|
||||
const result = removeMetricFromDashboardConfig(['metric2'], config);
|
||||
|
||||
expect(result.rows![0]).toMatchObject({
|
||||
id: 'row1',
|
||||
rowHeight: 320
|
||||
});
|
||||
expect(result.rows![0].items).toHaveLength(2);
|
||||
expect(result.rows![0].columnSizes).toEqual([6, 6]);
|
||||
});
|
||||
|
||||
it('should handle removing all metrics from config', () => {
|
||||
const config = createConfigWithRows([
|
||||
{
|
||||
id: 'row1',
|
||||
items: [{ id: 'metric1' }, { id: 'metric2' }],
|
||||
columnSizes: [6, 6],
|
||||
rowHeight: 320
|
||||
},
|
||||
{
|
||||
id: 'row2',
|
||||
items: [{ id: 'metric3' }],
|
||||
columnSizes: [12],
|
||||
rowHeight: 320
|
||||
}
|
||||
]);
|
||||
const result = removeMetricFromDashboardConfig(['metric1', 'metric2', 'metric3'], config);
|
||||
|
||||
expect(result.rows).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should correctly remove metrics from a large config with multiple rows', () => {
|
||||
const config = createConfigWithRows([
|
||||
{
|
||||
id: 'row1',
|
||||
items: [{ id: 'metric1' }, { id: 'metric2' }],
|
||||
columnSizes: [6, 6],
|
||||
rowHeight: 320
|
||||
},
|
||||
{
|
||||
id: 'row2',
|
||||
items: [{ id: 'metric3' }, { id: 'metric4' }, { id: 'metric5' }],
|
||||
columnSizes: [4, 4, 4],
|
||||
rowHeight: 320
|
||||
},
|
||||
{
|
||||
id: 'row3',
|
||||
items: [{ id: 'metric6' }],
|
||||
columnSizes: [12],
|
||||
rowHeight: 320
|
||||
},
|
||||
{
|
||||
id: 'row4',
|
||||
items: [{ id: 'metric7' }, { id: 'metric8' }, { id: 'metric9' }, { id: 'metric10' }],
|
||||
columnSizes: [3, 3, 3, 3],
|
||||
rowHeight: 320
|
||||
},
|
||||
{
|
||||
id: 'row5',
|
||||
items: [{ id: 'metric11' }, { id: 'metric12' }],
|
||||
columnSizes: [6, 6],
|
||||
rowHeight: 320
|
||||
}
|
||||
]);
|
||||
|
||||
const result = removeMetricFromDashboardConfig(['metric2', 'metric4', 'metric11'], config);
|
||||
|
||||
expect(result.rows).toHaveLength(5);
|
||||
// Check row 1
|
||||
expect(result.rows![0].items).toHaveLength(1);
|
||||
expect(result.rows![0].items[0].id).toBe('metric1');
|
||||
expect(result.rows![0].columnSizes).toEqual([12]);
|
||||
// Check row 2
|
||||
expect(result.rows![1].items).toHaveLength(2);
|
||||
expect(result.rows![1].items.map((item) => item.id)).toEqual(['metric3', 'metric5']);
|
||||
expect(result.rows![1].columnSizes).toEqual([6, 6]);
|
||||
// Check row 3 (unchanged)
|
||||
expect(result.rows![2].items).toHaveLength(1);
|
||||
expect(result.rows![2].items[0].id).toBe('metric6');
|
||||
// Check row 4 (unchanged)
|
||||
expect(result.rows![3].items).toHaveLength(4);
|
||||
expect(result.rows![3].columnSizes).toEqual([3, 3, 3, 3]);
|
||||
// Check row 5
|
||||
expect(result.rows![4].items).toHaveLength(1);
|
||||
expect(result.rows![4].items[0].id).toBe('metric12');
|
||||
expect(result.rows![4].columnSizes).toEqual([12]);
|
||||
});
|
||||
|
||||
it('should handle removing non-existent metrics while preserving existing structure', () => {
|
||||
const config = createConfigWithRows([
|
||||
{
|
||||
id: 'row1',
|
||||
items: [{ id: 'metric1' }, { id: 'metric2' }, { id: 'metric3' }],
|
||||
columnSizes: [4, 4, 4],
|
||||
rowHeight: 320
|
||||
},
|
||||
{
|
||||
id: 'row2',
|
||||
items: [{ id: 'metric4' }, { id: 'metric5' }],
|
||||
columnSizes: [6, 6],
|
||||
rowHeight: 320
|
||||
}
|
||||
]);
|
||||
|
||||
const result = removeMetricFromDashboardConfig(
|
||||
['nonexistent1', 'nonexistent2', 'metric1'],
|
||||
config
|
||||
);
|
||||
|
||||
// Should only remove metric1 and ignore non-existent metrics
|
||||
expect(result.rows).toHaveLength(2);
|
||||
// Check first row
|
||||
expect(result.rows![0].items).toHaveLength(2);
|
||||
expect(result.rows![0].items.map((item) => item.id)).toEqual(['metric2', 'metric3']);
|
||||
expect(result.rows![0].columnSizes).toEqual([6, 6]);
|
||||
// Check second row (should be unchanged)
|
||||
expect(result.rows![1].items).toHaveLength(2);
|
||||
expect(result.rows![1].items.map((item) => item.id)).toEqual(['metric4', 'metric5']);
|
||||
expect(result.rows![1].columnSizes).toEqual([6, 6]);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,38 @@
|
|||
import type { BusterDashboard } from '@/api/asset_interfaces/dashboard';
|
||||
import { NUMBER_OF_COLUMNS } from '@/components/ui/grid/helpers';
|
||||
|
||||
export const removeMetricFromDashboardConfig = (
|
||||
metricIds: string[],
|
||||
existingConfig: BusterDashboard['config']
|
||||
) => {
|
||||
// Create a new config object to avoid mutating the original
|
||||
const newConfig = {
|
||||
...existingConfig,
|
||||
rows: [...(existingConfig.rows || [])]
|
||||
};
|
||||
|
||||
// Filter out rows that contain metrics to be removed
|
||||
newConfig.rows = newConfig.rows
|
||||
.map((row) => {
|
||||
// Remove the specified metrics from the row
|
||||
const filteredItems = row.items.filter((item) => !metricIds.includes(item.id));
|
||||
|
||||
// If no items left in the row, return null to filter out later
|
||||
if (filteredItems.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Recalculate column sizes for remaining items
|
||||
const columnSize = NUMBER_OF_COLUMNS / filteredItems.length;
|
||||
const columnSizes = Array(filteredItems.length).fill(columnSize);
|
||||
|
||||
return {
|
||||
...row,
|
||||
items: filteredItems,
|
||||
columnSizes
|
||||
};
|
||||
})
|
||||
.filter((row): row is NonNullable<typeof row> => row !== null);
|
||||
|
||||
return newConfig;
|
||||
};
|
|
@ -25,6 +25,7 @@ import {
|
|||
useRemoveAssetFromCollection
|
||||
} from '../collections/queryRequests';
|
||||
import { collectionQueryKeys } from '@/api/query_keys/collection';
|
||||
import { addMetricToDashboardConfig, removeMetricFromDashboardConfig } from './helpers';
|
||||
|
||||
export const useGetDashboardsList = (
|
||||
params: Omit<DashboardsListRequest, 'page_token' | 'page_size'>
|
||||
|
@ -43,13 +44,12 @@ export const useGetDashboardsList = (
|
|||
});
|
||||
};
|
||||
|
||||
export const useGetDashboard = <TData = BusterDashboardResponse>(
|
||||
id: string | undefined,
|
||||
select?: (data: BusterDashboardResponse) => TData
|
||||
) => {
|
||||
const useGetDashboardAndInitializeMetrics = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const getAssetPassword = useBusterAssetsContextSelector((state) => state.getAssetPassword);
|
||||
const { password } = getAssetPassword(id!);
|
||||
|
||||
return useMemoizedFn(async (id: string) => {
|
||||
const { password } = getAssetPassword(id);
|
||||
|
||||
const initializeMetrics = useMemoizedFn((metrics: BusterDashboardResponse['metrics']) => {
|
||||
for (const metric of Object.values(metrics)) {
|
||||
|
@ -60,16 +60,22 @@ export const useGetDashboard = <TData = BusterDashboardResponse>(
|
|||
}
|
||||
});
|
||||
|
||||
const queryFn = useMemoizedFn(async () => {
|
||||
return dashboardsGetDashboard({ id: id!, password }).then((data) => {
|
||||
initializeMetrics(data.metrics);
|
||||
return data;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetDashboard = <TData = BusterDashboardResponse>(
|
||||
id: string | undefined,
|
||||
select?: (data: BusterDashboardResponse) => TData
|
||||
) => {
|
||||
const queryFn = useGetDashboardAndInitializeMetrics();
|
||||
|
||||
return useQuery({
|
||||
...dashboardQueryKeys.dashboardGetDashboard(id!),
|
||||
queryFn: queryFn,
|
||||
queryFn: () => queryFn(id!),
|
||||
enabled: !!id,
|
||||
select
|
||||
});
|
||||
|
@ -318,46 +324,87 @@ export const useUpdateDashboardShare = () => {
|
|||
|
||||
export const useSaveMetricsToDashboard = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const prefetchDashboard = useGetDashboardAndInitializeMetrics();
|
||||
const { openErrorMessage } = useBusterNotifications();
|
||||
|
||||
const saveMetricToDashboard = useMemoizedFn(
|
||||
async ({ metricIds, dashboardId }: { metricIds: string[]; dashboardId: string }) => {
|
||||
// await saveMetric({
|
||||
// id: metricId,
|
||||
// save_to_dashboard: dashboardIds
|
||||
// });
|
||||
const options = dashboardQueryKeys.dashboardGetDashboard(dashboardId);
|
||||
let dashboardResponse = queryClient.getQueryData(options.queryKey);
|
||||
if (!dashboardResponse) {
|
||||
const res = await prefetchDashboard(dashboardId).catch((e) => {
|
||||
openErrorMessage('Failed to save metrics to dashboard. Dashboard not found');
|
||||
return null;
|
||||
});
|
||||
if (res) {
|
||||
queryClient.setQueryData(options.queryKey, res);
|
||||
dashboardResponse = res;
|
||||
}
|
||||
}
|
||||
|
||||
if (dashboardResponse) {
|
||||
const newConfig = addMetricToDashboardConfig(metricIds, dashboardResponse.dashboard.config);
|
||||
return dashboardsUpdateDashboard({
|
||||
id: dashboardId,
|
||||
config: newConfig
|
||||
});
|
||||
}
|
||||
|
||||
openErrorMessage('Failed to save metrics to dashboard');
|
||||
}
|
||||
);
|
||||
|
||||
return useMutation({
|
||||
mutationFn: saveMetricToDashboard,
|
||||
onSuccess: (data, variables) => {
|
||||
// queryClient.invalidateQueries({
|
||||
// queryKey: variables.dashboardIds.map(
|
||||
// (id) => dashboardQueryKeys.dashboardGetDashboard(id).queryKey
|
||||
// )
|
||||
// });
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: dashboardQueryKeys.dashboardGetDashboard(variables.dashboardId).queryKey
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useRemoveMetricFromDashboard = () => {
|
||||
const { openConfirmModal } = useBusterNotifications();
|
||||
export const useRemoveMetricsFromDashboard = () => {
|
||||
const { openConfirmModal, openErrorMessage } = useBusterNotifications();
|
||||
const queryClient = useQueryClient();
|
||||
const prefetchDashboard = useGetDashboardAndInitializeMetrics();
|
||||
const removeMetricFromDashboard = useMemoizedFn(
|
||||
async ({
|
||||
metricId,
|
||||
metricIds,
|
||||
dashboardId,
|
||||
useConfirmModal = true
|
||||
}: {
|
||||
metricId: string;
|
||||
metricIds: string[];
|
||||
dashboardId: string;
|
||||
useConfirmModal?: boolean;
|
||||
}) => {
|
||||
const method = async () => {
|
||||
// await saveMetric({
|
||||
// id: metricId,
|
||||
// remove_from_dashboard: [dashboardId]
|
||||
// });
|
||||
const options = dashboardQueryKeys.dashboardGetDashboard(dashboardId);
|
||||
let dashboardResponse = queryClient.getQueryData(options.queryKey);
|
||||
if (!dashboardResponse) {
|
||||
const res = await prefetchDashboard(dashboardId).catch((e) => {
|
||||
openErrorMessage('Failed to remove metrics from dashboard. Dashboard not found');
|
||||
return null;
|
||||
});
|
||||
if (res) {
|
||||
queryClient.setQueryData(options.queryKey, res);
|
||||
dashboardResponse = res;
|
||||
}
|
||||
}
|
||||
|
||||
if (dashboardResponse) {
|
||||
const newConfig = removeMetricFromDashboardConfig(
|
||||
metricIds,
|
||||
dashboardResponse.dashboard.config
|
||||
);
|
||||
await dashboardsUpdateDashboard({
|
||||
id: dashboardId,
|
||||
config: newConfig
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
openErrorMessage('Failed to remove metrics from dashboard');
|
||||
};
|
||||
|
||||
if (!useConfirmModal) return await method();
|
||||
|
@ -372,24 +419,25 @@ export const useRemoveMetricFromDashboard = () => {
|
|||
|
||||
return useMutation({
|
||||
mutationFn: removeMetricFromDashboard,
|
||||
onMutate: async (variables) => {
|
||||
const currentDashboard = queryClient.getQueryData(
|
||||
dashboardQueryKeys.dashboardGetDashboard(variables.dashboardId).queryKey
|
||||
);
|
||||
onMutate: async ({ metricIds, dashboardId }) => {
|
||||
const options = dashboardQueryKeys.dashboardGetDashboard(dashboardId);
|
||||
const currentDashboard = queryClient.getQueryData(options.queryKey);
|
||||
if (currentDashboard) {
|
||||
queryClient.setQueryData(
|
||||
dashboardQueryKeys.dashboardGetDashboard(variables.dashboardId).queryKey,
|
||||
(currentDashboard) => {
|
||||
if (currentDashboard?.dashboard.config.rows) {
|
||||
currentDashboard.dashboard.config.rows.forEach((row) => {
|
||||
row.items = row.items.filter((item) => item.id !== variables.metricId);
|
||||
const newConfig = removeMetricFromDashboardConfig(
|
||||
metricIds,
|
||||
currentDashboard.dashboard.config
|
||||
);
|
||||
queryClient.setQueryData(options.queryKey, (currentDashboard) => {
|
||||
return create(currentDashboard!, (draft) => {
|
||||
draft.dashboard.config = newConfig;
|
||||
});
|
||||
});
|
||||
}
|
||||
delete currentDashboard!.metrics[variables.metricId];
|
||||
return currentDashboard;
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: dashboardQueryKeys.dashboardGetDashboard(variables.dashboardId).queryKey
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -170,7 +170,7 @@ export const useDeleteMetric = () => {
|
|||
});
|
||||
};
|
||||
|
||||
export const useSaveMetricToCollection = () => {
|
||||
export const useSaveMetricToCollections = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { data: userFavorites, refetch: refreshFavoritesList } = useGetUserFavorites();
|
||||
const { mutateAsync: addAssetToCollection } = useAddAssetToCollection();
|
||||
|
|
|
@ -5,7 +5,7 @@ import { SaveToCollectionsDropdown } from '../dropdowns/SaveToCollectionsDropdow
|
|||
import { CollectionButton } from './CollectionsButton';
|
||||
import {
|
||||
useRemoveMetricFromCollection,
|
||||
useSaveMetricToCollection
|
||||
useSaveMetricToCollections
|
||||
} from '@/api/buster_rest/metrics';
|
||||
|
||||
export const SaveMetricToCollectionButton: React.FC<{
|
||||
|
@ -14,7 +14,7 @@ export const SaveMetricToCollectionButton: React.FC<{
|
|||
useText?: boolean;
|
||||
}> = ({ metricIds, buttonType = 'ghost', useText = false }) => {
|
||||
const { openInfoMessage } = useBusterNotifications();
|
||||
const { mutateAsync: saveMetricToCollection } = useSaveMetricToCollection();
|
||||
const { mutateAsync: saveMetricToCollection } = useSaveMetricToCollections();
|
||||
const { mutateAsync: removeMetricFromCollection } = useRemoveMetricFromCollection();
|
||||
|
||||
const [selectedCollections, setSelectedCollections] = useState<
|
||||
|
|
|
@ -4,7 +4,10 @@ import { SaveToDashboardDropdown } from '../dropdowns/SaveToDashboardDropdown';
|
|||
import type { BusterMetric } from '@/api/asset_interfaces';
|
||||
import { Button } from '@/components/ui/buttons';
|
||||
import { ASSET_ICONS } from '../config/assetIcons';
|
||||
import { useRemoveMetricFromDashboard, useSaveMetricToDashboard } from '@/api/buster_rest/metrics';
|
||||
import {
|
||||
useRemoveMetricsFromDashboard,
|
||||
useSaveMetricsToDashboard
|
||||
} from '@/api/buster_rest/dashboards';
|
||||
|
||||
const EMPTY_SELECTED_DASHBOARDS: BusterMetric['dashboards'] = [];
|
||||
|
||||
|
@ -14,22 +17,18 @@ export const SaveMetricToDashboardButton: React.FC<{
|
|||
selectedDashboards?: BusterMetric['dashboards'];
|
||||
}> = React.memo(
|
||||
({ metricIds, disabled = false, selectedDashboards = EMPTY_SELECTED_DASHBOARDS }) => {
|
||||
const { mutateAsync: saveMetricToDashboard } = useSaveMetricToDashboard();
|
||||
const { mutateAsync: removeMetricFromDashboard } = useRemoveMetricFromDashboard();
|
||||
const { mutateAsync: saveMetricsToDashboard } = useSaveMetricsToDashboard();
|
||||
const { mutateAsync: removeMetricsFromDashboard } = useRemoveMetricsFromDashboard();
|
||||
|
||||
const onSaveToDashboard = useMemoizedFn(async (dashboardIds: string[]) => {
|
||||
await Promise.all(
|
||||
metricIds.map((metricId) => {
|
||||
return saveMetricToDashboard({ metricId, dashboardIds });
|
||||
})
|
||||
dashboardIds.map((dashboardId) => saveMetricsToDashboard({ metricIds, dashboardId }))
|
||||
);
|
||||
});
|
||||
|
||||
const onRemoveFromDashboard = useMemoizedFn(async (dashboardId: string) => {
|
||||
const onRemoveFromDashboard = useMemoizedFn(async (dashboardIds: string[]) => {
|
||||
await Promise.all(
|
||||
metricIds.map((metricId) => {
|
||||
return removeMetricFromDashboard({ metricId, dashboardId });
|
||||
})
|
||||
dashboardIds.map((dashboardId) => removeMetricsFromDashboard({ metricIds, dashboardId }))
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ export const SaveToDashboardDropdown: React.FC<{
|
|||
children: React.ReactNode;
|
||||
selectedDashboards: BusterMetric['dashboards'];
|
||||
onSaveToDashboard: (dashboardId: string[]) => Promise<void>;
|
||||
onRemoveFromDashboard: (dashboardId: string) => void;
|
||||
onRemoveFromDashboard: (dashboardId: string[]) => Promise<void>;
|
||||
}> = ({ children, onRemoveFromDashboard, onSaveToDashboard, selectedDashboards }) => {
|
||||
const [showDropdown, setShowDropdown] = useState(false);
|
||||
|
||||
|
@ -46,7 +46,7 @@ export const useSaveToDashboardDropdownContent = ({
|
|||
}: {
|
||||
selectedDashboards: BusterMetric['dashboards'];
|
||||
onSaveToDashboard: (dashboardId: string[]) => Promise<void>;
|
||||
onRemoveFromDashboard: (dashboardId: string) => void;
|
||||
onRemoveFromDashboard: (dashboardId: string[]) => Promise<void>;
|
||||
}): Pick<
|
||||
DropdownProps,
|
||||
'items' | 'footerContent' | 'menuHeader' | 'selectType' | 'emptyStateText'
|
||||
|
@ -58,10 +58,9 @@ export const useSaveToDashboardDropdownContent = ({
|
|||
const onClickItem = useMemoizedFn(async (dashboard: BusterDashboardListItem) => {
|
||||
const isSelected = selectedDashboards.some((d) => d.id === dashboard.id);
|
||||
if (isSelected) {
|
||||
onRemoveFromDashboard(dashboard.id);
|
||||
await onRemoveFromDashboard([dashboard.id]);
|
||||
} else {
|
||||
const allDashboardsAndSelected = selectedDashboards.map((d) => d.id).concat(dashboard.id);
|
||||
await onSaveToDashboard(allDashboardsAndSelected);
|
||||
await onSaveToDashboard([dashboard.id]);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import { ASSET_ICONS } from '@/components/features/config/assetIcons';
|
|||
import {
|
||||
useDeleteMetric,
|
||||
useRemoveMetricFromCollection,
|
||||
useSaveMetricToCollection
|
||||
useSaveMetricToCollections
|
||||
} from '@/api/buster_rest/metrics';
|
||||
import {
|
||||
useAddUserFavorite,
|
||||
|
@ -63,7 +63,7 @@ const CollectionsButton: React.FC<{
|
|||
onSelectChange: (selectedRowKeys: string[]) => void;
|
||||
}> = ({ selectedRowKeys, onSelectChange }) => {
|
||||
const { openInfoMessage } = useBusterNotifications();
|
||||
const { mutateAsync: saveMetricToCollection } = useSaveMetricToCollection();
|
||||
const { mutateAsync: saveMetricToCollection } = useSaveMetricToCollections();
|
||||
const { mutateAsync: removeMetricFromCollection } = useRemoveMetricFromCollection();
|
||||
|
||||
const [selectedCollections, setSelectedCollections] = useState<
|
||||
|
|
|
@ -7,7 +7,7 @@ import { Dropdown, DropdownItems } from '@/components/ui/dropdown';
|
|||
import { Button } from '@/components/ui/buttons';
|
||||
import Link from 'next/link';
|
||||
import React, { useContext, useMemo } from 'react';
|
||||
import { useRemoveMetricFromDashboard } from '@/api/buster_rest/metrics';
|
||||
import { useRemoveMetricsFromDashboard } from '@/api/buster_rest/dashboards';
|
||||
|
||||
export const MetricTitle: React.FC<{
|
||||
title: BusterMetric['title'];
|
||||
|
@ -105,7 +105,7 @@ const ThreeDotMenu: React.FC<{
|
|||
dashboardId: string;
|
||||
metricId: string;
|
||||
}> = React.memo(({ dashboardId, metricId, className }) => {
|
||||
const { mutateAsync: removeMetricFromDashboard } = useRemoveMetricFromDashboard();
|
||||
const { mutateAsync: removeMetricFromDashboard } = useRemoveMetricsFromDashboard();
|
||||
|
||||
const dropdownItems: DropdownItems = useMemo(
|
||||
() => [
|
||||
|
@ -117,7 +117,7 @@ const ThreeDotMenu: React.FC<{
|
|||
try {
|
||||
await removeMetricFromDashboard({
|
||||
dashboardId,
|
||||
metricId
|
||||
metricIds: [metricId]
|
||||
});
|
||||
} catch (error) {
|
||||
//
|
||||
|
|
|
@ -13,7 +13,7 @@ import { Dots, Star, Trash, Xmark } from '@/components/ui/icons';
|
|||
import {
|
||||
useDeleteMetric,
|
||||
useRemoveMetricFromCollection,
|
||||
useSaveMetricToCollection,
|
||||
useSaveMetricToCollections,
|
||||
useUpdateMetric
|
||||
} from '@/api/buster_rest/metrics';
|
||||
import {
|
||||
|
@ -68,7 +68,7 @@ const CollectionsButton: React.FC<{
|
|||
onSelectChange: (selectedRowKeys: string[]) => void;
|
||||
}> = ({ selectedRowKeys, onSelectChange }) => {
|
||||
const { openInfoMessage } = useBusterNotifications();
|
||||
const { mutateAsync: saveMetricToCollection } = useSaveMetricToCollection();
|
||||
const { mutateAsync: saveMetricToCollection } = useSaveMetricToCollections();
|
||||
const { mutateAsync: removeMetricFromCollection } = useRemoveMetricFromCollection();
|
||||
|
||||
const [selectedCollections, setSelectedCollections] = useState<
|
||||
|
|
|
@ -3,11 +3,13 @@ import {
|
|||
useGetMetric,
|
||||
useGetMetricData,
|
||||
useRemoveMetricFromCollection,
|
||||
useRemoveMetricFromDashboard,
|
||||
useSaveMetricToCollection,
|
||||
useSaveMetricToDashboard,
|
||||
useSaveMetricToCollections,
|
||||
useUpdateMetric
|
||||
} from '@/api/buster_rest/metrics';
|
||||
import {
|
||||
useSaveMetricsToDashboard,
|
||||
useRemoveMetricsFromDashboard
|
||||
} from '@/api/buster_rest/dashboards';
|
||||
import { DropdownContent, DropdownItem, DropdownItems } from '@/components/ui/dropdown';
|
||||
import {
|
||||
Trash,
|
||||
|
@ -123,16 +125,24 @@ export const ThreeDotMenuButton = React.memo(({ metricId }: { metricId: string }
|
|||
ThreeDotMenuButton.displayName = 'ThreeDotMenuButton';
|
||||
|
||||
const useDashboardSelectMenu = ({ metricId }: { metricId: string }) => {
|
||||
const { mutateAsync: saveMetricToDashboard } = useSaveMetricToDashboard();
|
||||
const { mutateAsync: removeMetricFromDashboard } = useRemoveMetricFromDashboard();
|
||||
const { mutateAsync: saveMetricsToDashboard } = useSaveMetricsToDashboard();
|
||||
const { mutateAsync: removeMetricsFromDashboard } = useRemoveMetricsFromDashboard();
|
||||
const { data: dashboards } = useGetMetric({ id: metricId }, (x) => x.dashboards);
|
||||
|
||||
const onSaveToDashboard = useMemoizedFn(async (dashboardIds: string[]) => {
|
||||
await saveMetricToDashboard({ metricId, dashboardIds });
|
||||
await Promise.all(
|
||||
dashboardIds.map((dashboardId) =>
|
||||
saveMetricsToDashboard({ metricIds: [metricId], dashboardId })
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
const onRemoveFromDashboard = useMemoizedFn(async (dashboardId: string) => {
|
||||
await removeMetricFromDashboard({ metricId, dashboardId });
|
||||
const onRemoveFromDashboard = useMemoizedFn(async (dashboardIds: string[]) => {
|
||||
await Promise.all(
|
||||
dashboardIds.map((dashboardId) =>
|
||||
removeMetricsFromDashboard({ metricIds: [metricId], dashboardId })
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
const { items, footerContent, selectType, menuHeader } = useSaveToDashboardDropdownContent({
|
||||
|
@ -193,7 +203,7 @@ const useVersionHistorySelectMenu = ({ metricId }: { metricId: string }) => {
|
|||
};
|
||||
|
||||
const useCollectionSelectMenu = ({ metricId }: { metricId: string }) => {
|
||||
const { mutateAsync: saveMetricToCollection } = useSaveMetricToCollection();
|
||||
const { mutateAsync: saveMetricToCollection } = useSaveMetricToCollections();
|
||||
const { mutateAsync: removeMetricFromCollection } = useRemoveMetricFromCollection();
|
||||
const { data: collections } = useGetMetric({ id: metricId }, (x) => x.collections);
|
||||
const { openInfoMessage } = useBusterNotifications();
|
||||
|
|
Loading…
Reference in New Issue