mirror of https://github.com/buster-so/buster.git
add metrics to dashboard tests
This commit is contained in:
parent
025542866d
commit
abb54f4dbb
|
@ -0,0 +1,51 @@
|
||||||
|
import type { BusterDashboard } from '@/api/asset_interfaces/dashboard';
|
||||||
|
import { MAX_NUMBER_OF_ITEMS, NUMBER_OF_COLUMNS } from '@/components/ui/grid/helpers';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
export const addMetricToDashboardConfig = (
|
||||||
|
metricIds: string[],
|
||||||
|
existingConfig: BusterDashboard['config']
|
||||||
|
) => {
|
||||||
|
// Create a new config object to avoid mutating the original
|
||||||
|
const newConfig = {
|
||||||
|
...existingConfig,
|
||||||
|
rows: [...(existingConfig.rows || [])]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Filter out metrics that are already in the dashboard
|
||||||
|
const newMetricIds = metricIds.filter((metricId) => {
|
||||||
|
return !newConfig.rows?.some((row) => row.items.some((item) => item.id === metricId));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (newMetricIds.length === 0) {
|
||||||
|
return existingConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate how many rows we need
|
||||||
|
const totalNewMetrics = newMetricIds.length;
|
||||||
|
const metricsPerRow = MAX_NUMBER_OF_ITEMS;
|
||||||
|
const numRowsNeeded = Math.ceil(totalNewMetrics / metricsPerRow);
|
||||||
|
|
||||||
|
// Create new rows for the metrics
|
||||||
|
for (let i = 0; i < numRowsNeeded; i++) {
|
||||||
|
const startIdx = i * metricsPerRow;
|
||||||
|
const endIdx = Math.min(startIdx + metricsPerRow, totalNewMetrics);
|
||||||
|
const metricsInThisRow = newMetricIds.slice(startIdx, endIdx);
|
||||||
|
|
||||||
|
// Calculate column sizes for this row - each metric gets equal width
|
||||||
|
const columnSize = NUMBER_OF_COLUMNS / metricsInThisRow.length;
|
||||||
|
const columnSizes = Array(metricsInThisRow.length).fill(columnSize);
|
||||||
|
|
||||||
|
// Create the new row
|
||||||
|
const newRow = {
|
||||||
|
id: uuidv4(),
|
||||||
|
items: metricsInThisRow.map((id) => ({ id })),
|
||||||
|
columnSizes,
|
||||||
|
rowHeight: 320 // Default row height
|
||||||
|
};
|
||||||
|
|
||||||
|
newConfig.rows.push(newRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newConfig;
|
||||||
|
};
|
|
@ -0,0 +1,174 @@
|
||||||
|
import { addMetricToDashboardConfig } from './addMetricToDashboard';
|
||||||
|
import type { BusterDashboard } from '@/api/asset_interfaces/dashboard';
|
||||||
|
|
||||||
|
describe('addMetricToDashboardConfig', () => {
|
||||||
|
const createEmptyConfig = (): BusterDashboard['config'] => ({
|
||||||
|
rows: []
|
||||||
|
});
|
||||||
|
|
||||||
|
const createConfigWithRows = (
|
||||||
|
rows: BusterDashboard['config']['rows']
|
||||||
|
): BusterDashboard['config'] => ({
|
||||||
|
rows
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the same config if no new metrics are provided', () => {
|
||||||
|
const config = createEmptyConfig();
|
||||||
|
const result = addMetricToDashboardConfig([], config);
|
||||||
|
expect(result).toBe(config);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add a single metric to an empty config', () => {
|
||||||
|
const config = createEmptyConfig();
|
||||||
|
const result = addMetricToDashboardConfig(['metric1'], config);
|
||||||
|
|
||||||
|
expect(result.rows!).toHaveLength(1);
|
||||||
|
expect(result.rows![0].items).toHaveLength(1);
|
||||||
|
expect(result.rows![0].items[0].id).toBe('metric1');
|
||||||
|
expect(result.rows![0].columnSizes).toEqual([12]); // Single column takes full width
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add multiple metrics up to MAX_NUMBER_OF_ITEMS in a single row', () => {
|
||||||
|
const config = createEmptyConfig();
|
||||||
|
const result = addMetricToDashboardConfig(['metric1', 'metric2', 'metric3', 'metric4'], config);
|
||||||
|
|
||||||
|
expect(result.rows!).toHaveLength(1);
|
||||||
|
expect(result.rows![0].items).toHaveLength(4);
|
||||||
|
expect(result.rows![0].columnSizes).toEqual([3, 3, 3, 3]); // 4 equal columns
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create multiple rows when metrics exceed MAX_NUMBER_OF_ITEMS', () => {
|
||||||
|
const config = createEmptyConfig();
|
||||||
|
const result = addMetricToDashboardConfig(
|
||||||
|
['metric1', 'metric2', 'metric3', 'metric4', 'metric5', 'metric6'],
|
||||||
|
config
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.rows!).toHaveLength(2);
|
||||||
|
expect(result.rows![0].items).toHaveLength(4);
|
||||||
|
expect(result.rows![1].items).toHaveLength(2);
|
||||||
|
expect(result.rows![0].columnSizes).toEqual([3, 3, 3, 3]);
|
||||||
|
expect(result.rows![1].columnSizes).toEqual([6, 6]); // 2 equal columns
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not add duplicate metrics', () => {
|
||||||
|
const config = createConfigWithRows([
|
||||||
|
{
|
||||||
|
id: 'row1',
|
||||||
|
items: [{ id: 'metric1' }],
|
||||||
|
columnSizes: [12],
|
||||||
|
rowHeight: 320
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result = addMetricToDashboardConfig(['metric1', 'metric2'], config);
|
||||||
|
|
||||||
|
expect(result.rows!).toHaveLength(2);
|
||||||
|
expect(result.rows![0].items).toHaveLength(1);
|
||||||
|
expect(result.rows![1].items).toHaveLength(1);
|
||||||
|
expect(result.rows![1].items[0].id).toBe('metric2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should respect MIN_NUMBER_OF_COLUMNS when adding fewer metrics', () => {
|
||||||
|
const config = createEmptyConfig();
|
||||||
|
const result = addMetricToDashboardConfig(['metric1', 'metric2'], config);
|
||||||
|
|
||||||
|
expect(result.rows!).toHaveLength(1);
|
||||||
|
expect(result.rows![0].items).toHaveLength(2);
|
||||||
|
expect(result.rows![0].columnSizes).toEqual([6, 6]); // 2 equal columns
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should respect MAX_NUMBER_OF_COLUMNS when adding many metrics', () => {
|
||||||
|
const config = createEmptyConfig();
|
||||||
|
const result = addMetricToDashboardConfig(
|
||||||
|
[
|
||||||
|
'metric1',
|
||||||
|
'metric2',
|
||||||
|
'metric3',
|
||||||
|
'metric4',
|
||||||
|
'metric5',
|
||||||
|
'metric6',
|
||||||
|
'metric7',
|
||||||
|
'metric8',
|
||||||
|
'metric9',
|
||||||
|
'metric10',
|
||||||
|
'metric11',
|
||||||
|
'metric12',
|
||||||
|
'metric13'
|
||||||
|
],
|
||||||
|
config
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.rows!).toHaveLength(4);
|
||||||
|
expect(result.rows![0].items).toHaveLength(4);
|
||||||
|
expect(result.rows![1].items).toHaveLength(4);
|
||||||
|
expect(result.rows![2].items).toHaveLength(4);
|
||||||
|
expect(result.rows![3].items).toHaveLength(1);
|
||||||
|
expect(result.rows![0].columnSizes).toEqual([3, 3, 3, 3]);
|
||||||
|
expect(result.rows![3].columnSizes).toEqual([12]); // Single column for last row
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should preserve existing rows when adding new metrics', () => {
|
||||||
|
const config = createConfigWithRows([
|
||||||
|
{
|
||||||
|
id: 'row1',
|
||||||
|
items: [{ id: 'existing1' }],
|
||||||
|
columnSizes: [12],
|
||||||
|
rowHeight: 320
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
const result = addMetricToDashboardConfig(['metric1', 'metric2'], config);
|
||||||
|
|
||||||
|
expect(result.rows!).toHaveLength(2);
|
||||||
|
expect(result.rows![0].items[0].id).toBe('existing1');
|
||||||
|
expect(result.rows![1].items[0].id).toBe('metric1');
|
||||||
|
expect(result.rows![1].items[1].id).toBe('metric2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly distribute columns for exactly 2 metrics', () => {
|
||||||
|
const config = createEmptyConfig();
|
||||||
|
const result = addMetricToDashboardConfig(['metric1', 'metric2'], config);
|
||||||
|
|
||||||
|
expect(result.rows!).toHaveLength(1);
|
||||||
|
expect(result.rows![0].items).toHaveLength(2);
|
||||||
|
expect(result.rows![0].items.map((item) => item.id)).toEqual(['metric1', 'metric2']);
|
||||||
|
expect(result.rows![0].columnSizes).toEqual([6, 6]); // Two equal columns of 6
|
||||||
|
expect(result.rows![0].columnSizes!.reduce((a, b) => a + b)).toBe(12); // Sum should be 12
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly distribute columns for exactly 3 metrics', () => {
|
||||||
|
const config = createEmptyConfig();
|
||||||
|
const result = addMetricToDashboardConfig(['metric1', 'metric2', 'metric3'], config);
|
||||||
|
|
||||||
|
expect(result.rows!).toHaveLength(1);
|
||||||
|
expect(result.rows![0].items).toHaveLength(3);
|
||||||
|
expect(result.rows![0].items.map((item) => item.id)).toEqual(['metric1', 'metric2', 'metric3']);
|
||||||
|
expect(result.rows![0].columnSizes).toEqual([4, 4, 4]); // Three equal columns of 4
|
||||||
|
expect(result.rows![0].columnSizes!.reduce((a, b) => a + b)).toBe(12); // Sum should be 12
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly distribute columns for exactly 4 metrics', () => {
|
||||||
|
const config = createEmptyConfig();
|
||||||
|
const result = addMetricToDashboardConfig(['metric1', 'metric2', 'metric3', 'metric4'], config);
|
||||||
|
|
||||||
|
expect(result.rows!).toHaveLength(1);
|
||||||
|
expect(result.rows![0].items).toHaveLength(4);
|
||||||
|
expect(result.rows![0].items.map((item) => item.id)).toEqual([
|
||||||
|
'metric1',
|
||||||
|
'metric2',
|
||||||
|
'metric3',
|
||||||
|
'metric4'
|
||||||
|
]);
|
||||||
|
expect(result.rows![0].columnSizes).toEqual([3, 3, 3, 3]); // Four equal columns of 3
|
||||||
|
expect(result.rows![0].columnSizes!.reduce((a, b) => a + b)).toBe(12); // Sum should be 12
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should correctly distribute columns for exactly 0 metrics', () => {
|
||||||
|
const config = createEmptyConfig();
|
||||||
|
const result = addMetricToDashboardConfig([], config);
|
||||||
|
|
||||||
|
expect(result.rows!).toHaveLength(0);
|
||||||
|
expect(result.rows).toBe(config.rows);
|
||||||
|
});
|
||||||
|
});
|
|
@ -183,8 +183,7 @@ export const useAddDashboardToCollection = () => {
|
||||||
const mutationFn = useMemoizedFn(
|
const mutationFn = useMemoizedFn(
|
||||||
async (variables: { dashboardId: string; collectionIds: string[] }) => {
|
async (variables: { dashboardId: string; collectionIds: string[] }) => {
|
||||||
const { dashboardId, collectionIds } = variables;
|
const { dashboardId, collectionIds } = variables;
|
||||||
|
return await Promise.all(
|
||||||
await Promise.all(
|
|
||||||
collectionIds.map((collectionId) =>
|
collectionIds.map((collectionId) =>
|
||||||
addAssetToCollection({
|
addAssetToCollection({
|
||||||
id: dashboardId,
|
id: dashboardId,
|
||||||
|
@ -194,7 +193,6 @@ export const useAddDashboardToCollection = () => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn,
|
mutationFn,
|
||||||
onSuccess: (_, { collectionIds }) => {
|
onSuccess: (_, { collectionIds }) => {
|
||||||
|
@ -214,7 +212,7 @@ export const useRemoveDashboardFromCollection = () => {
|
||||||
const mutationFn = useMemoizedFn(
|
const mutationFn = useMemoizedFn(
|
||||||
async (variables: { dashboardId: string; collectionIds: string[] }) => {
|
async (variables: { dashboardId: string; collectionIds: string[] }) => {
|
||||||
const { dashboardId, collectionIds } = variables;
|
const { dashboardId, collectionIds } = variables;
|
||||||
await Promise.all(
|
return await Promise.all(
|
||||||
collectionIds.map((collectionId) =>
|
collectionIds.map((collectionId) =>
|
||||||
removeAssetFromCollection({
|
removeAssetFromCollection({
|
||||||
id: dashboardId,
|
id: dashboardId,
|
||||||
|
@ -245,30 +243,6 @@ export const useRemoveDashboardFromCollection = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useRemoveItemFromDashboard = () => {
|
|
||||||
const { mutateAsync: updateDashboardMutation } = useUpdateDashboard();
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
const mutationFn = useMemoizedFn(
|
|
||||||
async (variables: { dashboardId: string; metricId: string | string[] }) => {
|
|
||||||
const { dashboardId, metricId } = variables;
|
|
||||||
const options = dashboardQueryKeys.dashboardGetDashboard(dashboardId);
|
|
||||||
const prevDashboard = queryClient.getQueryData(options.queryKey);
|
|
||||||
|
|
||||||
if (prevDashboard) {
|
|
||||||
const prevMetricsIds = Object.keys(prevDashboard?.metrics);
|
|
||||||
const newMetricsIds = prevMetricsIds?.filter((t) => !metricId.includes(t));
|
|
||||||
console.log('TODO: remove metrics from dashboard', dashboardId, metricId);
|
|
||||||
return updateDashboardMutation({
|
|
||||||
id: dashboardId
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return useMutation({
|
|
||||||
mutationFn
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useShareDashboard = () => {
|
export const useShareDashboard = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
return useMutation({
|
return useMutation({
|
||||||
|
@ -341,3 +315,81 @@ export const useUpdateDashboardShare = () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useSaveMetricsToDashboard = () => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
const saveMetricToDashboard = useMemoizedFn(
|
||||||
|
async ({ metricIds, dashboardId }: { metricIds: string[]; dashboardId: string }) => {
|
||||||
|
// await saveMetric({
|
||||||
|
// id: metricId,
|
||||||
|
// save_to_dashboard: dashboardIds
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: saveMetricToDashboard,
|
||||||
|
onSuccess: (data, variables) => {
|
||||||
|
// queryClient.invalidateQueries({
|
||||||
|
// queryKey: variables.dashboardIds.map(
|
||||||
|
// (id) => dashboardQueryKeys.dashboardGetDashboard(id).queryKey
|
||||||
|
// )
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useRemoveMetricFromDashboard = () => {
|
||||||
|
const { openConfirmModal } = useBusterNotifications();
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const removeMetricFromDashboard = useMemoizedFn(
|
||||||
|
async ({
|
||||||
|
metricId,
|
||||||
|
dashboardId,
|
||||||
|
useConfirmModal = true
|
||||||
|
}: {
|
||||||
|
metricId: string;
|
||||||
|
dashboardId: string;
|
||||||
|
useConfirmModal?: boolean;
|
||||||
|
}) => {
|
||||||
|
const method = async () => {
|
||||||
|
// await saveMetric({
|
||||||
|
// id: metricId,
|
||||||
|
// remove_from_dashboard: [dashboardId]
|
||||||
|
// });
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!useConfirmModal) return await method();
|
||||||
|
|
||||||
|
return await openConfirmModal({
|
||||||
|
title: 'Remove from dashboard',
|
||||||
|
content: 'Are you sure you want to remove this metric from this dashboard?',
|
||||||
|
onOk: method
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return useMutation({
|
||||||
|
mutationFn: removeMetricFromDashboard,
|
||||||
|
onMutate: async (variables) => {
|
||||||
|
const currentDashboard = queryClient.getQueryData(
|
||||||
|
dashboardQueryKeys.dashboardGetDashboard(variables.dashboardId).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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
delete currentDashboard!.metrics[variables.metricId];
|
||||||
|
return currentDashboard;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
import { queryKeys } from '@/api/query_keys';
|
import { queryKeys } from '@/api/query_keys';
|
||||||
import { useBusterNotifications } from '@/context/BusterNotifications';
|
import { useBusterNotifications } from '@/context/BusterNotifications';
|
||||||
|
|
||||||
export const useListDatasources = (enabled: boolean) => {
|
export const useListDatasources = (enabled: boolean = true) => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
...queryKeys.datasourceGetList,
|
...queryKeys.datasourceGetList,
|
||||||
queryFn: listDatasources,
|
queryFn: listDatasources,
|
||||||
|
|
|
@ -247,85 +247,6 @@ export const useRemoveMetricFromCollection = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useSaveMetricToDashboard = () => {
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
const saveMetricToDashboard = useMemoizedFn(
|
|
||||||
async ({ metricId, dashboardIds }: { metricId: string; dashboardIds: string[] }) => {
|
|
||||||
// await saveMetric({
|
|
||||||
// id: metricId,
|
|
||||||
// save_to_dashboard: dashboardIds
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: saveMetricToDashboard,
|
|
||||||
onSuccess: (data, variables) => {
|
|
||||||
queryClient.invalidateQueries({
|
|
||||||
queryKey: variables.dashboardIds.map(
|
|
||||||
(id) => dashboardQueryKeys.dashboardGetDashboard(id).queryKey
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useRemoveMetricFromDashboard = () => {
|
|
||||||
const { openConfirmModal } = useBusterNotifications();
|
|
||||||
const { mutateAsync: saveMetric } = useSaveMetric();
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
const removeMetricFromDashboard = useMemoizedFn(
|
|
||||||
async ({
|
|
||||||
metricId,
|
|
||||||
dashboardId,
|
|
||||||
useConfirmModal = true
|
|
||||||
}: {
|
|
||||||
metricId: string;
|
|
||||||
dashboardId: string;
|
|
||||||
useConfirmModal?: boolean;
|
|
||||||
}) => {
|
|
||||||
const method = async () => {
|
|
||||||
// await saveMetric({
|
|
||||||
// id: metricId,
|
|
||||||
// remove_from_dashboard: [dashboardId]
|
|
||||||
// });
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!useConfirmModal) return await method();
|
|
||||||
|
|
||||||
return await openConfirmModal({
|
|
||||||
title: 'Remove from dashboard',
|
|
||||||
content: 'Are you sure you want to remove this metric from this dashboard?',
|
|
||||||
onOk: method
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: removeMetricFromDashboard,
|
|
||||||
onMutate: async (variables) => {
|
|
||||||
const currentDashboard = queryClient.getQueryData(
|
|
||||||
dashboardQueryKeys.dashboardGetDashboard(variables.dashboardId).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);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
delete currentDashboard!.metrics[variables.metricId];
|
|
||||||
return currentDashboard;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useDuplicateMetric = () => {
|
export const useDuplicateMetric = () => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: duplicateMetric
|
mutationFn: duplicateMetric
|
||||||
|
|
|
@ -2,13 +2,18 @@ import { BusterListSelectedOptionPopupContainer } from '@/components/ui/list';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { PermissionAssignedButton } from '@/components/features/PermissionComponents';
|
import { PermissionAssignedButton } from '@/components/features/PermissionComponents';
|
||||||
import { useDatasetUpdateDatasetGroups } from '@/api/buster_rest';
|
import { useDatasetUpdateDatasetGroups } from '@/api/buster_rest';
|
||||||
|
import { useMemoizedFn } from '@/hooks';
|
||||||
|
|
||||||
export const PermissionDatasetGroupSelectedPopup: React.FC<{
|
export const PermissionDatasetGroupSelectedPopup: React.FC<{
|
||||||
selectedRowKeys: string[];
|
selectedRowKeys: string[];
|
||||||
onSelectChange: (selectedRowKeys: string[]) => void;
|
onSelectChange: (selectedRowKeys: string[]) => void;
|
||||||
datasetId: string;
|
datasetId: string;
|
||||||
}> = React.memo(({ selectedRowKeys, onSelectChange, datasetId }) => {
|
}> = React.memo(({ selectedRowKeys, onSelectChange, datasetId }) => {
|
||||||
const { mutateAsync: updateDatasetGroups } = useDatasetUpdateDatasetGroups(datasetId);
|
const { mutateAsync: updateDatasetGroups } = useDatasetUpdateDatasetGroups();
|
||||||
|
|
||||||
|
const onUpdate = useMemoizedFn(async (groups: { id: string; assigned: boolean }[]) => {
|
||||||
|
return updateDatasetGroups({ dataset_id: datasetId, groups });
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BusterListSelectedOptionPopupContainer
|
<BusterListSelectedOptionPopupContainer
|
||||||
|
@ -20,7 +25,7 @@ export const PermissionDatasetGroupSelectedPopup: React.FC<{
|
||||||
text="assigned"
|
text="assigned"
|
||||||
selectedRowKeys={selectedRowKeys}
|
selectedRowKeys={selectedRowKeys}
|
||||||
onSelectChange={onSelectChange}
|
onSelectChange={onSelectChange}
|
||||||
onUpdate={updateDatasetGroups}
|
onUpdate={onUpdate}
|
||||||
/>
|
/>
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,15 +1,9 @@
|
||||||
import { DataSource } from '@/api/asset_interfaces';
|
import { DataSource } from '@/api/asset_interfaces';
|
||||||
import React, { useRef } from 'react';
|
import React, { useRef } from 'react';
|
||||||
import { Input } from '@/components/ui/inputs';
|
import { FormWrapperHandle } from './FormWrapper';
|
||||||
import { Select } from '@/components/ui/select';
|
|
||||||
import { FormWrapper, FormWrapperHandle } from './FormWrapper';
|
|
||||||
import { formatDate } from '@/lib';
|
import { formatDate } from '@/lib';
|
||||||
import {
|
import { DatasourceCreateCredentials } from '@/api/request_interfaces/datasources';
|
||||||
DatasourceCreateCredentials,
|
|
||||||
PostgresCreateCredentials
|
|
||||||
} from '@/api/request_interfaces/datasources';
|
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
import { TagInput } from '@/components/ui/inputs/InputTagInput';
|
|
||||||
|
|
||||||
const sshModeOptions = ['Do not use SSH credentials', 'Use SSH credentials'].map((item, index) => ({
|
const sshModeOptions = ['Do not use SSH credentials', 'Use SSH credentials'].map((item, index) => ({
|
||||||
label: item,
|
label: item,
|
||||||
|
|
|
@ -27,7 +27,7 @@ export const SaveDashboardToCollectionButton: React.FC<{
|
||||||
dashboardIds.map((dashboardId) => {
|
dashboardIds.map((dashboardId) => {
|
||||||
return addDashboardToCollection({
|
return addDashboardToCollection({
|
||||||
dashboardId,
|
dashboardId,
|
||||||
collectionId: collectionIds
|
collectionIds: collectionIds
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -40,7 +40,7 @@ export const SaveDashboardToCollectionButton: React.FC<{
|
||||||
dashboardIds.map((dashboardId) => {
|
dashboardIds.map((dashboardId) => {
|
||||||
return removeDashboardFromCollection({
|
return removeDashboardFromCollection({
|
||||||
dashboardId,
|
dashboardId,
|
||||||
collectionId
|
collectionIds: [collectionId]
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -38,7 +38,7 @@ export const SaveMetricToCollectionButton: React.FC<{
|
||||||
const allSelectedButLast = selectedCollections.slice(0, -1);
|
const allSelectedButLast = selectedCollections.slice(0, -1);
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
allSelectedButLast.map((metricId) => {
|
allSelectedButLast.map((metricId) => {
|
||||||
return removeMetricFromCollection({ metricId, collectionId });
|
return removeMetricFromCollection({ metricId, collectionIds: [collectionId] });
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
openInfoMessage('Metrics removed from collections');
|
openInfoMessage('Metrics removed from collections');
|
||||||
|
|
|
@ -85,14 +85,8 @@ const CollectionsButton: React.FC<{
|
||||||
|
|
||||||
const onRemoveFromCollection = useMemoizedFn(async (collectionId: string) => {
|
const onRemoveFromCollection = useMemoizedFn(async (collectionId: string) => {
|
||||||
setSelectedCollections((prev) => prev.filter((id) => id !== collectionId));
|
setSelectedCollections((prev) => prev.filter((id) => id !== collectionId));
|
||||||
const allSelectedButLast = selectedRowKeys.slice(0, -1);
|
const allRemoves: Promise<void>[] = selectedRowKeys.map((metricId) => {
|
||||||
const lastMetricId = selectedRowKeys[selectedRowKeys.length - 1];
|
return removeMetricFromCollection({ metricId, collectionIds: [collectionId] });
|
||||||
const allRemoves: Promise<void>[] = allSelectedButLast.map((metricId) => {
|
|
||||||
return removeMetricFromCollection({ metricId, collectionId });
|
|
||||||
});
|
|
||||||
await removeMetricFromCollection({
|
|
||||||
metricId: lastMetricId,
|
|
||||||
collectionId
|
|
||||||
});
|
});
|
||||||
await Promise.all(allRemoves);
|
await Promise.all(allRemoves);
|
||||||
openInfoMessage('Metrics removed from collections');
|
openInfoMessage('Metrics removed from collections');
|
||||||
|
|
|
@ -77,7 +77,7 @@ export const DashboardContentController: React.FC<{
|
||||||
);
|
);
|
||||||
|
|
||||||
const onRowLayoutChange = useMemoizedFn((rows: BusterResizeableGridRow[]) => {
|
const onRowLayoutChange = useMemoizedFn((rows: BusterResizeableGridRow[]) => {
|
||||||
onUpdateDashboardConfig({ rows, id: dashboard!.id });
|
if (dashboard) onUpdateDashboardConfig({ rows, id: dashboard.id });
|
||||||
});
|
});
|
||||||
|
|
||||||
const onDragEnd = useMemoizedFn(() => {
|
const onDragEnd = useMemoizedFn(() => {
|
||||||
|
|
|
@ -67,7 +67,7 @@ const CollectionsButton: React.FC<{
|
||||||
selectedRowKeys.map((dashboardId) => {
|
selectedRowKeys.map((dashboardId) => {
|
||||||
return onAddDashboardToCollection({
|
return onAddDashboardToCollection({
|
||||||
dashboardId,
|
dashboardId,
|
||||||
collectionId: collectionIds
|
collectionIds
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -81,7 +81,7 @@ const CollectionsButton: React.FC<{
|
||||||
selectedRowKeys.map((dashboardId) => {
|
selectedRowKeys.map((dashboardId) => {
|
||||||
return onRemoveDashboardFromCollection({
|
return onRemoveDashboardFromCollection({
|
||||||
dashboardId,
|
dashboardId,
|
||||||
collectionId
|
collectionIds: [collectionId]
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
|
@ -90,14 +90,8 @@ const CollectionsButton: React.FC<{
|
||||||
|
|
||||||
const onRemoveFromCollection = useMemoizedFn(async (collectionId: string) => {
|
const onRemoveFromCollection = useMemoizedFn(async (collectionId: string) => {
|
||||||
setSelectedCollections((prev) => prev.filter((id) => id !== collectionId));
|
setSelectedCollections((prev) => prev.filter((id) => id !== collectionId));
|
||||||
const allSelectedButLast = selectedRowKeys.slice(0, -1);
|
const allRemoves: Promise<void>[] = selectedRowKeys.map((metricId) => {
|
||||||
const lastMetricId = selectedRowKeys[selectedRowKeys.length - 1];
|
return removeMetricFromCollection({ metricId, collectionIds: [collectionId] });
|
||||||
const allRemoves: Promise<void>[] = allSelectedButLast.map((metricId) => {
|
|
||||||
return removeMetricFromCollection({ metricId, collectionId });
|
|
||||||
});
|
|
||||||
await removeMetricFromCollection({
|
|
||||||
metricId: lastMetricId,
|
|
||||||
collectionId
|
|
||||||
});
|
});
|
||||||
await Promise.all(allRemoves);
|
await Promise.all(allRemoves);
|
||||||
openInfoMessage('Metrics removed from collections');
|
openInfoMessage('Metrics removed from collections');
|
||||||
|
|
|
@ -122,12 +122,12 @@ const useCollectionSelectMenu = ({ dashboardId }: { dashboardId: string }) => {
|
||||||
}, [collections]);
|
}, [collections]);
|
||||||
|
|
||||||
const onSaveToCollection = useMemoizedFn(async (collectionIds: string[]) => {
|
const onSaveToCollection = useMemoizedFn(async (collectionIds: string[]) => {
|
||||||
await saveDashboardToCollection({ dashboardId, collectionId: collectionIds[0] });
|
await saveDashboardToCollection({ dashboardId, collectionIds });
|
||||||
openInfoMessage('Dashboard saved to collections');
|
openInfoMessage('Dashboard saved to collections');
|
||||||
});
|
});
|
||||||
|
|
||||||
const onRemoveFromCollection = useMemoizedFn(async (collectionId: string) => {
|
const onRemoveFromCollection = useMemoizedFn(async (collectionId: string) => {
|
||||||
await removeDashboardFromCollection({ dashboardId, collectionId });
|
await removeDashboardFromCollection({ dashboardId, collectionIds: [collectionId] });
|
||||||
openInfoMessage('Dashboard removed from collections');
|
openInfoMessage('Dashboard removed from collections');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue