mirror of https://github.com/buster-so/buster.git
update dashboard request strucutre
This commit is contained in:
parent
0e2fd9a93c
commit
c66b1878f3
|
@ -32,6 +32,7 @@ import { addMetricToDashboardConfig, removeMetricFromDashboardConfig } from './h
|
|||
import { addAndRemoveMetricsToDashboard } from './helpers/addAndRemoveMetricsToDashboard';
|
||||
import { useParams, useSearchParams } from 'next/navigation';
|
||||
import { RustApiError } from '../errors';
|
||||
import { useOriginalDashboardStore } from '@/context/Dashboards';
|
||||
|
||||
export const useGetDashboardsList = (
|
||||
params: Omit<Parameters<typeof dashboardsGetList>[0], 'page_token' | 'page_size'>
|
||||
|
@ -125,7 +126,8 @@ export const useUpdateDashboard = (params?: {
|
|||
updateVersion?: boolean;
|
||||
saveToServer?: boolean;
|
||||
}) => {
|
||||
const { updateVersion = true, saveToServer = false } = params || {};
|
||||
const setOriginalDashboards = useOriginalDashboardStore((x) => x.setOriginalDashboard);
|
||||
const { updateVersion = false, saveToServer = false } = params || {};
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
|
@ -159,6 +161,7 @@ export const useUpdateDashboard = (params?: {
|
|||
dashboardQueryKeys.dashboardGetDashboard(variables.id).queryKey,
|
||||
data
|
||||
);
|
||||
setOriginalDashboards(data.dashboard);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -176,12 +179,13 @@ export const useUpdateDashboardConfig = (params?: {
|
|||
const queryClient = useQueryClient();
|
||||
|
||||
const method = useMemoizedFn(
|
||||
async (
|
||||
newDashboard: Partial<BusterDashboard['config']> & {
|
||||
id: string;
|
||||
}
|
||||
) => {
|
||||
const options = dashboardQueryKeys.dashboardGetDashboard(newDashboard.id);
|
||||
async ({
|
||||
dashboardId,
|
||||
...newDashboard
|
||||
}: Partial<BusterDashboard['config']> & {
|
||||
dashboardId: string;
|
||||
}) => {
|
||||
const options = dashboardQueryKeys.dashboardGetDashboard(dashboardId);
|
||||
const previousDashboard = queryClient.getQueryData(options.queryKey);
|
||||
const previousConfig = previousDashboard?.dashboard?.config;
|
||||
if (previousConfig) {
|
||||
|
@ -189,7 +193,7 @@ export const useUpdateDashboardConfig = (params?: {
|
|||
Object.assign(draft, newDashboard);
|
||||
});
|
||||
return mutateAsync({
|
||||
id: newDashboard.id,
|
||||
id: dashboardId,
|
||||
config: newConfig
|
||||
});
|
||||
}
|
||||
|
|
|
@ -390,7 +390,7 @@ export const useUpdateMetric = (params: {
|
|||
const {
|
||||
wait = 0,
|
||||
updateOnSave = false,
|
||||
updateVersion = true,
|
||||
updateVersion = false,
|
||||
saveToServer = false
|
||||
} = params || {};
|
||||
const queryClient = useQueryClient();
|
||||
|
@ -408,8 +408,10 @@ export const useUpdateMetric = (params: {
|
|||
);
|
||||
|
||||
const combineAndSaveMetric = useMemoizedFn(
|
||||
(newMetricPartial: Omit<Partial<IBusterMetric>, 'status'> & { id: string }) => {
|
||||
const metricId = newMetricPartial.id;
|
||||
({
|
||||
id: metricId,
|
||||
...newMetricPartial
|
||||
}: Omit<Partial<IBusterMetric>, 'status'> & { id: string }) => {
|
||||
const options = metricsQueryKeys.metricsGetMetric(metricId);
|
||||
const prevMetric = getOriginalMetric(metricId);
|
||||
const newMetric = create(prevMetric, (draft) => {
|
||||
|
|
|
@ -133,7 +133,7 @@ export const BusterResizeColumns: React.FC<ContainerProps> = ({
|
|||
|
||||
useLayoutEffect(() => {
|
||||
setSizes(columnSpansToPercent(columnSizes));
|
||||
}, [items.length, columnSizes?.length]);
|
||||
}, [items.length, columnSizes]);
|
||||
|
||||
return (
|
||||
<SortableContext id={rowId} items={items} disabled={false}>
|
||||
|
|
|
@ -63,7 +63,6 @@ export const BusterResizeableGrid: React.FC<{
|
|||
if (checkRowEquality(filteredRows, rows)) {
|
||||
return;
|
||||
}
|
||||
|
||||
onRowLayoutChange(filteredRows);
|
||||
setRows(filteredRows);
|
||||
});
|
||||
|
|
|
@ -8,8 +8,8 @@ export const useChatUpdate = () => {
|
|||
const queryClient = useQueryClient();
|
||||
|
||||
const onUpdateChat = useMemoizedFn(
|
||||
async (newChatConfig: Partial<IBusterChat> & { id: string }) => {
|
||||
const options = queryKeys.chatsGetChat(newChatConfig.id);
|
||||
async ({ id: chatId, ...newChatConfig }: Partial<IBusterChat> & { id: string }) => {
|
||||
const options = queryKeys.chatsGetChat(chatId);
|
||||
const queryKey = options.queryKey;
|
||||
const currentData = queryClient.getQueryData<IBusterChat>(queryKey);
|
||||
const iChat = create(currentData || ({} as IBusterChat), (draft) => {
|
||||
|
|
|
@ -5,6 +5,8 @@ import { useGetDashboard } from '@/api/buster_rest/dashboards';
|
|||
import { BusterDashboardResponse } from '@/api/asset_interfaces/dashboard';
|
||||
import { dashboardQueryKeys } from '@/api/query_keys/dashboard';
|
||||
import { compareObjectsByKeys } from '@/lib/objects';
|
||||
import { useMemo } from 'react';
|
||||
import { create } from 'mutative';
|
||||
|
||||
export const useIsDashboardChanged = ({ dashboardId }: { dashboardId: string }) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
@ -26,17 +28,16 @@ export const useIsDashboardChanged = ({ dashboardId }: { dashboardId: string })
|
|||
const options = dashboardQueryKeys.dashboardGetDashboard(dashboardId);
|
||||
const currentDashboard = queryClient.getQueryData<BusterDashboardResponse>(options.queryKey);
|
||||
if (originalDashboard && currentDashboard) {
|
||||
queryClient.setQueryData(options.queryKey, {
|
||||
...currentDashboard,
|
||||
dashboard: originalDashboard
|
||||
const resetDashboard = create(currentDashboard, (draft) => {
|
||||
Object.assign(draft, originalDashboard);
|
||||
});
|
||||
queryClient.setQueryData(options.queryKey, resetDashboard);
|
||||
}
|
||||
refetchCurrentDashboard();
|
||||
});
|
||||
|
||||
return {
|
||||
onResetDashboardToOriginal,
|
||||
isDashboardChanged:
|
||||
const isDashboardChanged = useMemo(() => {
|
||||
return (
|
||||
!originalDashboard ||
|
||||
!currentDashboard ||
|
||||
!compareObjectsByKeys(originalDashboard, currentDashboard, [
|
||||
|
@ -45,5 +46,11 @@ export const useIsDashboardChanged = ({ dashboardId }: { dashboardId: string })
|
|||
'config',
|
||||
'file'
|
||||
])
|
||||
);
|
||||
}, [originalDashboard, currentDashboard]);
|
||||
|
||||
return {
|
||||
onResetDashboardToOriginal,
|
||||
isDashboardChanged
|
||||
};
|
||||
};
|
||||
|
|
|
@ -10,7 +10,6 @@ import { useUpdateMetric } from '@/api/buster_rest/metrics';
|
|||
import { useMemoizedFn } from '@/hooks';
|
||||
import { useGetMetricMemoized } from './useGetMetricMemoized';
|
||||
import { useParams } from 'next/navigation';
|
||||
import { useOriginalMetricStore } from './useOriginalMetricStore';
|
||||
import { timeout } from '@/lib';
|
||||
import { useState } from 'react';
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ export const DashboardContentController: React.FC<{
|
|||
|
||||
const onRowLayoutChange = useMemoizedFn((rows: BusterResizeableGridRow[]) => {
|
||||
if (dashboard) {
|
||||
onUpdateDashboardConfig({ rows: removeChildrenFromItems(rows), id: dashboard.id });
|
||||
onUpdateDashboardConfig({ rows: removeChildrenFromItems(rows), dashboardId: dashboard.id });
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -108,7 +108,7 @@ export const DashboardContentController: React.FC<{
|
|||
|
||||
useEffect(() => {
|
||||
if (remapMetrics && dashboard?.id) {
|
||||
debouncedForInitialRenderOnUpdateDashboardConfig({ rows, id: dashboard.id });
|
||||
debouncedForInitialRenderOnUpdateDashboardConfig({ rows, dashboardId: dashboard.id });
|
||||
}
|
||||
}, [dashboard?.id, remapMetrics]);
|
||||
|
||||
|
|
|
@ -25,11 +25,10 @@ export const DashboardEditTitles: React.FC<{
|
|||
if (!readOnly) onUpdateDashboard({ name, id: dashboardId });
|
||||
});
|
||||
|
||||
const { run: onChangeDashboardDescription } = useDebounceFn(
|
||||
useMemoizedFn((value: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
const onChangeDashboardDescription = useMemoizedFn(
|
||||
(value: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
if (!readOnly) onUpdateDashboard({ description: value.target.value, id: dashboardId });
|
||||
}),
|
||||
{ wait: 650 }
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -37,6 +36,7 @@ export const DashboardEditTitles: React.FC<{
|
|||
<EditableTitle
|
||||
className="w-full truncate"
|
||||
readOnly={readOnly}
|
||||
onSetValue={onChangeTitle}
|
||||
onChange={onChangeTitle}
|
||||
id={DASHBOARD_TITLE_INPUT_ID}
|
||||
placeholder="New dashboard"
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
import { useGetDashboard, useUpdateDashboard } from '@/api/buster_rest/dashboards';
|
||||
import { SaveResetFilePopup } from '@/components/features/popups/SaveResetFilePopup';
|
||||
import { useIsDashboardChanged } from '@/context/Dashboards';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import React from 'react';
|
||||
|
||||
export const DashboardSaveFilePopup: React.FC<{ dashboardId: string }> = React.memo(
|
||||
({ dashboardId }) => {
|
||||
const { data: dashboardResponse } = useGetDashboard({ id: dashboardId });
|
||||
const { isDashboardChanged, onResetDashboardToOriginal } = useIsDashboardChanged({
|
||||
dashboardId
|
||||
});
|
||||
const { mutateAsync: onSaveDashboard, isPending: isSaving } = useUpdateDashboard({
|
||||
saveToServer: true
|
||||
});
|
||||
|
||||
const onSaveDashboardToServer = useMemoizedFn(() => {
|
||||
const dashboard = dashboardResponse?.dashboard;
|
||||
onSaveDashboard({
|
||||
id: dashboardId,
|
||||
name: dashboard?.name,
|
||||
description: dashboard?.description,
|
||||
config: dashboard?.config,
|
||||
file: dashboard?.file
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<SaveResetFilePopup
|
||||
open={isDashboardChanged}
|
||||
onReset={onResetDashboardToOriginal}
|
||||
onSave={onSaveDashboardToServer}
|
||||
isSaving={isSaving}
|
||||
showHotsKeys={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
|
@ -8,6 +8,8 @@ import { useDashboardContentStore, useIsDashboardChanged } from '@/context/Dashb
|
|||
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||
import { StatusCard } from '@/components/ui/card/StatusCard';
|
||||
import { useIsDashboardReadOnly } from '@/context/Dashboards/useIsDashboardReadOnly';
|
||||
import { useChatLayoutContextSelector } from '@/layouts/ChatLayout';
|
||||
import { DashboardSaveFilePopup } from './DashboardSaveFilePopup';
|
||||
|
||||
export const DashboardViewDashboardController: React.FC<{
|
||||
dashboardId: string;
|
||||
|
@ -22,10 +24,8 @@ export const DashboardViewDashboardController: React.FC<{
|
|||
} = useGetDashboard({ id: dashboardId });
|
||||
|
||||
const { mutateAsync: onUpdateDashboardConfig } = useUpdateDashboardConfig();
|
||||
const isVersionHistoryMode = useChatLayoutContextSelector((x) => x.isVersionHistoryMode);
|
||||
const onOpenAddContentModal = useDashboardContentStore((x) => x.onOpenAddContentModal);
|
||||
const { isDashboardChanged, onResetDashboardToOriginal } = useIsDashboardChanged({
|
||||
dashboardId
|
||||
});
|
||||
|
||||
const metrics = dashboardResponse?.metrics;
|
||||
const dashboard = dashboardResponse?.dashboard;
|
||||
|
@ -34,6 +34,10 @@ export const DashboardViewDashboardController: React.FC<{
|
|||
readOnly: readOnlyProp
|
||||
});
|
||||
|
||||
if (!isFetched) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
if (isError) {
|
||||
return (
|
||||
<div className="p-10">
|
||||
|
@ -42,10 +46,6 @@ export const DashboardViewDashboardController: React.FC<{
|
|||
);
|
||||
}
|
||||
|
||||
if (!isFetched) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollArea className="h-full">
|
||||
<div className="flex h-full flex-col space-y-3 p-10">
|
||||
|
@ -64,6 +64,8 @@ export const DashboardViewDashboardController: React.FC<{
|
|||
onOpenAddContentModal={onOpenAddContentModal}
|
||||
readOnly={isReadOnly}
|
||||
/>
|
||||
|
||||
{!isVersionHistoryMode && <DashboardSaveFilePopup dashboardId={dashboardId} />}
|
||||
</div>
|
||||
</ScrollArea>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
import { SaveResetFilePopup } from '@/components/features/popups/SaveResetFilePopup';
|
||||
import { useIsMetricChanged } from '@/context/Metrics/useIsMetricChanged';
|
||||
import { useUpdateMetricChart } from '@/context/Metrics/useUpdateMetricChart';
|
||||
import React from 'react';
|
||||
|
||||
export const MetricSaveFilePopup: React.FC<{ metricId: string }> = React.memo(({ metricId }) => {
|
||||
const { isMetricChanged, onResetMetricToOriginal } = useIsMetricChanged({ metricId });
|
||||
const { onSaveMetricToServer, isSaving } = useUpdateMetricChart({ metricId });
|
||||
|
||||
return (
|
||||
<SaveResetFilePopup
|
||||
open={isMetricChanged}
|
||||
onReset={onResetMetricToOriginal}
|
||||
onSave={onSaveMetricToServer}
|
||||
isSaving={isSaving}
|
||||
showHotsKeys={false}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
MetricSaveFilePopup.displayName = 'MetricSaveFilePopup';
|
|
@ -14,6 +14,7 @@ import { SaveResetFilePopup } from '@/components/features/popups/SaveResetFilePo
|
|||
import { useIsMetricChanged } from '@/context/Metrics/useIsMetricChanged';
|
||||
import { useUpdateMetricChart } from '@/context/Metrics';
|
||||
import { useIsMetricReadOnly } from '@/context/Metrics/useIsMetricReadOnly';
|
||||
import { MetricSaveFilePopup } from './MetricSaveFilePopup';
|
||||
|
||||
export const MetricViewChart: React.FC<{
|
||||
metricId: string;
|
||||
|
@ -161,20 +162,3 @@ const AnimatePresenceWrapper: React.FC<{
|
|||
</AnimatePresence>
|
||||
);
|
||||
};
|
||||
|
||||
const MetricSaveFilePopup: React.FC<{ metricId: string }> = React.memo(({ metricId }) => {
|
||||
const { isMetricChanged, onResetMetricToOriginal } = useIsMetricChanged({ metricId });
|
||||
const { onSaveMetricToServer, isSaving } = useUpdateMetricChart({ metricId });
|
||||
|
||||
return (
|
||||
<SaveResetFilePopup
|
||||
open={isMetricChanged}
|
||||
onReset={onResetMetricToOriginal}
|
||||
onSave={onSaveMetricToServer}
|
||||
isSaving={isSaving}
|
||||
showHotsKeys={false}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
MetricSaveFilePopup.displayName = 'MetricSaveFilePopup';
|
||||
|
|
|
@ -14,8 +14,7 @@ import {
|
|||
useBulkUpdateMetricVerificationStatus,
|
||||
useDeleteMetric,
|
||||
useRemoveMetricFromCollection,
|
||||
useSaveMetricToCollections,
|
||||
useUpdateMetric
|
||||
useSaveMetricToCollections
|
||||
} from '@/api/buster_rest/metrics';
|
||||
import { useThreeDotFavoritesOptions } from '@/components/features/dropdowns/useThreeDotFavoritesOptions';
|
||||
|
||||
|
@ -123,7 +122,6 @@ const StatusButton: React.FC<{
|
|||
const isAdmin = useUserConfigContextSelector((state) => state.isAdmin);
|
||||
|
||||
const onVerify = useMemoizedFn(async (data: { id: string; status: VerificationStatus }[]) => {
|
||||
console.log('onVerify', data);
|
||||
await updateStatus(data);
|
||||
onSelectChange([]);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue