mirror of https://github.com/buster-so/buster.git
dashboard pass the version number
This commit is contained in:
parent
f3a8dbd89d
commit
a05a81feaf
|
@ -36,36 +36,41 @@ import { RustApiError } from '../../buster_rest/errors';
|
|||
export const useGetMetric = <TData = IBusterMetric>(
|
||||
{
|
||||
id,
|
||||
version_number: version_number_prop
|
||||
versionNumber: versionNumberProp
|
||||
}: {
|
||||
id: string | undefined;
|
||||
version_number?: number | null; //if null it will not use a params from the query params
|
||||
versionNumber?: number | null; //if null it will not use a params from the query params
|
||||
},
|
||||
params?: Omit<UseQueryOptions<IBusterMetric, RustApiError, TData>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
const queryClient = useQueryClient();
|
||||
const setOriginalMetric = useOriginalMetricStore((x) => x.setOriginalMetric);
|
||||
const { versionNumber: versionNumberPathParam } = useParams() as {
|
||||
versionNumber: string | undefined;
|
||||
};
|
||||
const versionNumberQueryParam = useSearchParams().get('versionNumber');
|
||||
const versionNumber = versionNumberQueryParam || versionNumberPathParam;
|
||||
const getAssetPassword = useBusterAssetsContextSelector((x) => x.getAssetPassword);
|
||||
const setAssetPasswordError = useBusterAssetsContextSelector((x) => x.setAssetPasswordError);
|
||||
const { password } = getAssetPassword(id!);
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
const { versionNumber: versionNumberPathParam, metricId: metricIdPathParam } = useParams() as {
|
||||
versionNumber: string | undefined;
|
||||
metricId: string | undefined;
|
||||
};
|
||||
const versionNumberQueryParam = useSearchParams().get('versionNumber');
|
||||
const versionNumberFromParams = metricIdPathParam
|
||||
? versionNumberQueryParam || versionNumberPathParam
|
||||
: undefined;
|
||||
|
||||
const version_number = useMemo(() => {
|
||||
if (version_number_prop === null) return undefined;
|
||||
return version_number_prop || versionNumber ? parseInt(versionNumber!) : undefined;
|
||||
}, [version_number_prop, versionNumber]);
|
||||
const versionNumber = useMemo(() => {
|
||||
if (versionNumberProp === null) return undefined;
|
||||
return versionNumberProp || versionNumberFromParams
|
||||
? parseInt(versionNumberFromParams!)
|
||||
: undefined;
|
||||
}, [versionNumberProp, versionNumberFromParams]);
|
||||
|
||||
const options = useMemo(() => {
|
||||
return metricsQueryKeys.metricsGetMetric(id!, version_number);
|
||||
}, [id, version_number]);
|
||||
return metricsQueryKeys.metricsGetMetric(id!, versionNumber);
|
||||
}, [id, versionNumber]);
|
||||
|
||||
const queryFn = useMemoizedFn(async () => {
|
||||
const result = await getMetric({ id: id!, password, version_number });
|
||||
const result = await getMetric({ id: id!, password, version_number: versionNumber });
|
||||
const oldMetric = queryClient.getQueryData(options.queryKey);
|
||||
const updatedMetric = upgradeMetricToIMetric(result, oldMetric || null);
|
||||
setOriginalMetric(updatedMetric);
|
||||
|
@ -108,32 +113,38 @@ export const useGetMetricsList = (
|
|||
*/
|
||||
export const useGetMetricData = ({
|
||||
id,
|
||||
version_number: version_number_prop
|
||||
versionNumber: versionNumberProp
|
||||
}: {
|
||||
id: string | undefined;
|
||||
version_number?: number;
|
||||
versionNumber?: number;
|
||||
}) => {
|
||||
const {
|
||||
isFetched: isFetchedMetric,
|
||||
error: errorMetric,
|
||||
data: fetchedMetricData
|
||||
} = useGetMetric({ id }, { select: (x) => x.id });
|
||||
const { versionNumber: versionNumberPathParam } = useParams() as {
|
||||
const { versionNumber: versionNumberPathParam, metricId: metricIdPathParam } = useParams() as {
|
||||
versionNumber: string | undefined;
|
||||
metricId: string | undefined;
|
||||
};
|
||||
const versionNumberQueryParam = useSearchParams().get('versionNumber');
|
||||
const versionNumber = versionNumberQueryParam || versionNumberPathParam;
|
||||
const versionNumberFromParams = metricIdPathParam
|
||||
? versionNumberQueryParam || versionNumberPathParam
|
||||
: undefined;
|
||||
|
||||
const version_number = useMemo(() => {
|
||||
return version_number_prop || versionNumber ? parseInt(versionNumber!) : undefined;
|
||||
}, [version_number_prop, versionNumber]);
|
||||
const versionNumber = useMemo(() => {
|
||||
if (versionNumberProp === null) return undefined;
|
||||
return versionNumberProp || versionNumberFromParams
|
||||
? parseInt(versionNumberFromParams!)
|
||||
: undefined;
|
||||
}, [versionNumberProp, versionNumberFromParams]);
|
||||
|
||||
const queryFn = useMemoizedFn(() => {
|
||||
return getMetricData({ id: id!, version_number });
|
||||
return getMetricData({ id: id!, version_number: versionNumber });
|
||||
});
|
||||
|
||||
return useQuery({
|
||||
...metricsQueryKeys.metricsGetData(id!, version_number),
|
||||
...metricsQueryKeys.metricsGetData(id!, versionNumber),
|
||||
queryFn,
|
||||
enabled: () => {
|
||||
return !!id && isFetchedMetric && !errorMetric && !!fetchedMetricData;
|
||||
|
|
|
@ -17,7 +17,7 @@ const dashboardGetList = (
|
|||
|
||||
const dashboardGetDashboard = (dashboardId: string, version_number?: number) =>
|
||||
queryOptions<BusterDashboardResponse>({
|
||||
queryKey: ['dashboard', 'get', dashboardId, version_number] as const,
|
||||
queryKey: ['dashboard', 'get', dashboardId, version_number || 'latest'] as const,
|
||||
staleTime: 10 * 1000
|
||||
});
|
||||
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
export default async function Page({ params }: { params: Promise<{ versionNumber: string }> }) {
|
||||
const { versionNumber } = await params;
|
||||
return <div>Version {versionNumber}</div>;
|
||||
import { DashboardViewDashboardController } from '@/controllers/DashboardController/DashboardViewDashboardController/DashboardViewDashboardController';
|
||||
|
||||
export default async function Page({
|
||||
params
|
||||
}: {
|
||||
params: Promise<{ versionNumber: string; dashboardId: string; chatId: string }>;
|
||||
}) {
|
||||
const { versionNumber, dashboardId, chatId } = await params;
|
||||
return <DashboardViewDashboardController dashboardId={dashboardId} chatId={chatId} readOnly />;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { MetricViewChart } from '@/controllers/MetricController/MetricViewChart';
|
||||
|
||||
export default async function MetricVersionPage({
|
||||
params
|
||||
}: {
|
||||
params: Promise<{ versionNumber: string }>;
|
||||
params: Promise<{ versionNumber: string; metricId: string }>;
|
||||
}) {
|
||||
const { versionNumber } = await params;
|
||||
const { versionNumber, metricId } = await params;
|
||||
|
||||
return <div>MetricVersionPage {versionNumber}</div>;
|
||||
return <MetricViewChart metricId={metricId} />;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import { DashboardViewDashboardController } from '@/controllers/DashboardController/DashboardViewDashboardController';
|
||||
|
||||
export default async function DashboardVersionPage({
|
||||
params
|
||||
}: {
|
||||
params: Promise<{ versionNumber: string }>;
|
||||
params: Promise<{ versionNumber: string; dashboardId: string }>;
|
||||
}) {
|
||||
const { versionNumber } = await params;
|
||||
return <div>DashboardVersionPage {versionNumber}</div>;
|
||||
const { versionNumber, dashboardId } = await params;
|
||||
return <DashboardViewDashboardController dashboardId={dashboardId} chatId={undefined} readOnly />;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import { MetricViewChart } from '@/controllers/MetricController/MetricViewChart';
|
||||
|
||||
export default async function MetricVersionPage({
|
||||
params
|
||||
}: {
|
||||
params: Promise<{ versionNumber: string }>;
|
||||
params: Promise<{ versionNumber: string; metricId: string }>;
|
||||
}) {
|
||||
const { versionNumber } = await params;
|
||||
return <div>MetricVersionPage {versionNumber}</div>;
|
||||
const { versionNumber, metricId } = await params;
|
||||
return <MetricViewChart metricId={metricId} />;
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ export const BusterResizeColumns: React.FC<ContainerProps> = ({
|
|||
|
||||
return (
|
||||
<SortableContext id={rowId} items={items} disabled={false}>
|
||||
<div ref={setNodeRef} className="relative h-full w-full">
|
||||
<div ref={setNodeRef} className="buster-resize-columns relative h-full w-full">
|
||||
<BusterDragColumnMarkers
|
||||
isDraggingIndex={columnMarkerColumnIndex}
|
||||
itemsLength={items.length}
|
||||
|
|
|
@ -18,12 +18,12 @@ import {
|
|||
import { arrayMove } from '@dnd-kit/sortable';
|
||||
import { BusterSortableOverlay } from './_BusterSortableOverlay';
|
||||
import { BusterResizeableGridRow } from './interfaces';
|
||||
import clsx from 'clsx';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { useMemoizedFn } from '@/hooks';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import { BusterResizeRows } from './BusterResizeRows';
|
||||
import { NUMBER_OF_COLUMNS, NEW_ROW_ID, MIN_ROW_HEIGHT, TOP_SASH_ID } from './helpers';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const measuringConfig = {
|
||||
droppable: {
|
||||
|
@ -331,7 +331,7 @@ export const BusterResizeableGrid: React.FC<{
|
|||
onDragCancel={onDragCancel}
|
||||
collisionDetection={collisionDetectionStrategy}
|
||||
sensors={sensors}>
|
||||
<div className={clsx('h-full w-full', 'buster-resizeable-grid', className)}>
|
||||
<div className={cn('buster-resizeable-grid h-full w-full', className)}>
|
||||
<BusterResizeRows
|
||||
rows={rows}
|
||||
className={className}
|
||||
|
|
|
@ -19,6 +19,7 @@ import type {
|
|||
} from '@/api/asset_interfaces';
|
||||
import { DashboardEmptyState } from './DashboardEmptyState';
|
||||
import { type useUpdateDashboardConfig } from '@/api/buster_rest/dashboards';
|
||||
import last from 'lodash/last';
|
||||
|
||||
const DEFAULT_EMPTY_ROWS: DashboardConfig['rows'] = [];
|
||||
const DEFAULT_EMPTY_METRICS: Record<string, BusterMetric> = {};
|
||||
|
@ -61,6 +62,12 @@ export const DashboardContentController: React.FC<{
|
|||
return {
|
||||
...row,
|
||||
items: row.items.map((item) => {
|
||||
const selectedMetric = metrics[item.id];
|
||||
const versionNumber =
|
||||
last(selectedMetric.versions)?.version_number === selectedMetric.version_number
|
||||
? undefined
|
||||
: selectedMetric.version_number;
|
||||
|
||||
return {
|
||||
...item,
|
||||
children: (
|
||||
|
@ -71,6 +78,7 @@ export const DashboardContentController: React.FC<{
|
|||
readOnly={readOnly}
|
||||
chatId={chatId}
|
||||
numberOfMetrics={numberOfMetrics}
|
||||
versionNumber={versionNumber}
|
||||
/>
|
||||
)
|
||||
};
|
||||
|
@ -104,6 +112,8 @@ export const DashboardContentController: React.FC<{
|
|||
}
|
||||
}, [dashboard?.id, remapMetrics]);
|
||||
|
||||
console.log(hasMetrics, dashboardRows, dashboard);
|
||||
|
||||
return (
|
||||
<div className="dashboard-content-controller">
|
||||
{hasMetrics && !!dashboardRows.length && !!dashboard ? (
|
||||
|
@ -118,11 +128,12 @@ export const DashboardContentController: React.FC<{
|
|||
draggingId && (
|
||||
<DashboardMetricItem
|
||||
metricId={draggingId}
|
||||
readOnly={false}
|
||||
readOnly={true}
|
||||
dashboardId={dashboard.id}
|
||||
isDragOverlay
|
||||
numberOfMetrics={numberOfMetrics}
|
||||
chatId={undefined}
|
||||
versionNumber={metrics[draggingId]?.version_number}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import { BusterChart } from '@/components/ui/charts/BusterChart';
|
|||
|
||||
const DashboardMetricItemBase: React.FC<{
|
||||
metricId: string;
|
||||
versionNumber: number | undefined;
|
||||
chatId: string | undefined;
|
||||
dashboardId: string;
|
||||
numberOfMetrics: number;
|
||||
|
@ -18,6 +19,7 @@ const DashboardMetricItemBase: React.FC<{
|
|||
}> = ({
|
||||
readOnly,
|
||||
dashboardId,
|
||||
versionNumber,
|
||||
className = '',
|
||||
metricId,
|
||||
isDragOverlay = false,
|
||||
|
@ -32,7 +34,7 @@ const DashboardMetricItemBase: React.FC<{
|
|||
initialAnimationEnded,
|
||||
setInitialAnimationEnded,
|
||||
isFetchedMetricData
|
||||
} = useDashboardMetric({ metricId });
|
||||
} = useDashboardMetric({ metricId, versionNumber });
|
||||
|
||||
const loadingMetricData = !!metric && !isFetchedMetricData;
|
||||
const chartOptions = metric?.chart_config;
|
||||
|
@ -69,8 +71,6 @@ const DashboardMetricItemBase: React.FC<{
|
|||
setInitialAnimationEnded(metricId);
|
||||
});
|
||||
|
||||
if (!chartOptions) return null;
|
||||
|
||||
return (
|
||||
<Card
|
||||
ref={conatinerRef}
|
||||
|
@ -96,7 +96,7 @@ const DashboardMetricItemBase: React.FC<{
|
|||
isTable ? '' : 'p-3',
|
||||
isDragOverlay ? 'pointer-events-none' : 'pointer-events-auto'
|
||||
)}>
|
||||
{renderChart && (
|
||||
{renderChart && chartOptions && (
|
||||
<BusterChart
|
||||
data={data}
|
||||
loading={loading}
|
||||
|
@ -115,5 +115,9 @@ const DashboardMetricItemBase: React.FC<{
|
|||
};
|
||||
|
||||
export const DashboardMetricItem = React.memo(DashboardMetricItemBase, (prev, next) => {
|
||||
return prev.metricId === next.metricId && prev.dashboardId === next.dashboardId;
|
||||
return (
|
||||
prev.metricId === next.metricId &&
|
||||
prev.dashboardId === next.dashboardId &&
|
||||
prev.versionNumber === next.versionNumber
|
||||
);
|
||||
});
|
||||
|
|
|
@ -3,9 +3,15 @@ import { useEffect, useMemo, useRef } from 'react';
|
|||
import { useInViewport } from '@/hooks';
|
||||
import { useGetMetric, useGetMetricData } from '@/api/buster_rest/metrics';
|
||||
|
||||
export const useDashboardMetric = ({ metricId }: { metricId: string }) => {
|
||||
export const useDashboardMetric = ({
|
||||
metricId,
|
||||
versionNumber
|
||||
}: {
|
||||
metricId: string;
|
||||
versionNumber: number | undefined;
|
||||
}) => {
|
||||
const { data: metric, isFetched: isMetricFetched } = useGetMetric(
|
||||
{ id: metricId },
|
||||
{ id: metricId, versionNumber },
|
||||
{
|
||||
select: ({
|
||||
name,
|
||||
|
@ -32,7 +38,7 @@ export const useDashboardMetric = ({ metricId }: { metricId: string }) => {
|
|||
data: metricData,
|
||||
isFetched: isFetchedMetricData,
|
||||
dataUpdatedAt: metricDataUpdatedAt
|
||||
} = useGetMetricData({ id: metricId });
|
||||
} = useGetMetricData({ id: metricId, versionNumber });
|
||||
const dashboard = useDashboardContentControllerContextSelector(({ dashboard }) => dashboard);
|
||||
const metricMetadata = useDashboardContentControllerContextSelector(
|
||||
({ metricMetadata }) => metricMetadata[metricId]
|
||||
|
|
|
@ -10,23 +10,24 @@ export const DashboardLayoutContainer: React.FC<{
|
|||
children: React.ReactNode;
|
||||
dashboardId: string;
|
||||
}> = ({ children, dashboardId }) => {
|
||||
const { data: permission } = useGetDashboard(
|
||||
{ id: dashboardId },
|
||||
{ select: (x) => x.permission }
|
||||
);
|
||||
const isEditor = canEdit(permission);
|
||||
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
{isEditor && <MemoizedAddToDashboardModal dashboardId={dashboardId} />}
|
||||
<MemoizedAddToDashboardModal dashboardId={dashboardId} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const MemoizedAddToDashboardModal = React.memo(({ dashboardId }: { dashboardId: string }) => {
|
||||
const { data: permission } = useGetDashboard(
|
||||
{ id: dashboardId },
|
||||
{ select: (x) => x.permission }
|
||||
);
|
||||
const isEditor = canEdit(permission);
|
||||
const { openAddContentModal, onCloseAddContentModal } = useDashboardContentStore();
|
||||
|
||||
if (!isEditor) return null;
|
||||
|
||||
return (
|
||||
<AddToDashboardModal
|
||||
open={openAddContentModal}
|
||||
|
|
Loading…
Reference in New Issue