mirror of https://github.com/buster-so/buster.git
Remove some unecssary memo
This commit is contained in:
parent
991dd172f6
commit
2f324baa62
|
@ -9,105 +9,101 @@ import type { DropdownItems } from '../dropdown';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { PreparingYourRequestLoader } from '../charts/LoadingComponents';
|
import { PreparingYourRequestLoader } from '../charts/LoadingComponents';
|
||||||
|
|
||||||
export const MetricCard = React.memo(
|
export const MetricCard = React.forwardRef<
|
||||||
React.forwardRef<
|
HTMLDivElement,
|
||||||
HTMLDivElement,
|
{
|
||||||
|
className?: string;
|
||||||
|
metricId: string;
|
||||||
|
metricLink: string;
|
||||||
|
isDragOverlay: boolean;
|
||||||
|
readOnly: boolean;
|
||||||
|
metricData: BusterMetricData | undefined;
|
||||||
|
metric: Pick<BusterMetric, 'name' | 'time_frame' | 'chart_config' | 'description'> | undefined;
|
||||||
|
renderChart: boolean;
|
||||||
|
loading: boolean;
|
||||||
|
error: string | undefined;
|
||||||
|
animate: boolean;
|
||||||
|
onInitialAnimationEnd?: () => void;
|
||||||
|
attributes?: DraggableAttributes;
|
||||||
|
listeners?: DraggableSyntheticListeners;
|
||||||
|
threeDotMenuItems: DropdownItems;
|
||||||
|
}
|
||||||
|
>(
|
||||||
|
(
|
||||||
{
|
{
|
||||||
className?: string;
|
className = '',
|
||||||
metricId: string;
|
metricId,
|
||||||
metricLink: string;
|
metricLink,
|
||||||
isDragOverlay: boolean;
|
readOnly,
|
||||||
readOnly: boolean;
|
metricData,
|
||||||
metricData: BusterMetricData | undefined;
|
metric,
|
||||||
metric:
|
isDragOverlay,
|
||||||
| Pick<BusterMetric, 'name' | 'time_frame' | 'chart_config' | 'description'>
|
renderChart = true,
|
||||||
| undefined;
|
loading = false,
|
||||||
renderChart: boolean;
|
animate = true,
|
||||||
loading: boolean;
|
error,
|
||||||
error: string | undefined;
|
attributes,
|
||||||
animate: boolean;
|
listeners,
|
||||||
onInitialAnimationEnd?: () => void;
|
threeDotMenuItems,
|
||||||
attributes?: DraggableAttributes;
|
onInitialAnimationEnd
|
||||||
listeners?: DraggableSyntheticListeners;
|
},
|
||||||
threeDotMenuItems: DropdownItems;
|
ref
|
||||||
}
|
) => {
|
||||||
>(
|
const isTable = metric?.chart_config?.selectedChartType === 'table';
|
||||||
(
|
const chartOptions = metric?.chart_config;
|
||||||
{
|
const data = metricData?.data || null;
|
||||||
className = '',
|
const hideChart = isDragOverlay && data && data.length > 50;
|
||||||
metricId,
|
|
||||||
metricLink,
|
|
||||||
readOnly,
|
|
||||||
metricData,
|
|
||||||
metric,
|
|
||||||
isDragOverlay,
|
|
||||||
renderChart = true,
|
|
||||||
loading = false,
|
|
||||||
animate = true,
|
|
||||||
error,
|
|
||||||
attributes,
|
|
||||||
listeners,
|
|
||||||
threeDotMenuItems,
|
|
||||||
onInitialAnimationEnd
|
|
||||||
},
|
|
||||||
ref
|
|
||||||
) => {
|
|
||||||
const isTable = metric?.chart_config?.selectedChartType === 'table';
|
|
||||||
const chartOptions = metric?.chart_config;
|
|
||||||
const data = metricData?.data || null;
|
|
||||||
const hideChart = isDragOverlay && data && data.length > 50;
|
|
||||||
|
|
||||||
const content = () => {
|
const content = () => {
|
||||||
if (renderChart && chartOptions && !hideChart) {
|
if (renderChart && chartOptions && !hideChart) {
|
||||||
return (
|
return (
|
||||||
<BusterChartDynamic
|
<BusterChartDynamic
|
||||||
data={data}
|
data={data}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
error={error}
|
error={error}
|
||||||
onInitialAnimationEnd={onInitialAnimationEnd}
|
onInitialAnimationEnd={onInitialAnimationEnd}
|
||||||
animate={!isDragOverlay && animate}
|
animate={!isDragOverlay && animate}
|
||||||
animateLegend={false}
|
animateLegend={false}
|
||||||
columnMetadata={metricData?.data_metadata?.column_metadata}
|
columnMetadata={metricData?.data_metadata?.column_metadata}
|
||||||
readOnly={true}
|
readOnly={true}
|
||||||
{...chartOptions}
|
{...chartOptions}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <PreparingYourRequestLoader />;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
ref={ref}
|
||||||
|
className={cn('metric-item flex h-full w-full flex-col overflow-auto', className)}>
|
||||||
|
<Link className="swag flex" href={metricLink} prefetch {...attributes} {...listeners}>
|
||||||
|
<CardHeader
|
||||||
|
size="small"
|
||||||
|
data-testid={`metric-item-${metricId}`}
|
||||||
|
className="hover:bg-item-hover group relative min-h-13! w-full justify-center overflow-hidden border-b px-4 py-2">
|
||||||
|
<MetricTitle
|
||||||
|
name={metric?.name || ''}
|
||||||
|
timeFrame={metric?.time_frame}
|
||||||
|
metricLink={metricLink}
|
||||||
|
isDragOverlay={false}
|
||||||
|
readOnly={readOnly}
|
||||||
|
description={metric?.description}
|
||||||
|
threeDotMenuItems={threeDotMenuItems}
|
||||||
/>
|
/>
|
||||||
);
|
</CardHeader>
|
||||||
}
|
</Link>
|
||||||
|
|
||||||
return <PreparingYourRequestLoader />;
|
<div
|
||||||
};
|
className={cn(
|
||||||
|
'h-full w-full overflow-hidden bg-transparent',
|
||||||
return (
|
isTable ? '' : 'p-3',
|
||||||
<Card
|
isDragOverlay ? 'pointer-events-none' : 'pointer-events-auto'
|
||||||
ref={ref}
|
)}>
|
||||||
className={cn('metric-item flex h-full w-full flex-col overflow-auto', className)}>
|
{content()}
|
||||||
<Link className="swag flex" href={metricLink} prefetch {...attributes} {...listeners}>
|
</div>
|
||||||
<CardHeader
|
</Card>
|
||||||
size="small"
|
);
|
||||||
data-testid={`metric-item-${metricId}`}
|
}
|
||||||
className="hover:bg-item-hover group relative min-h-13! w-full justify-center overflow-hidden border-b px-4 py-2">
|
|
||||||
<MetricTitle
|
|
||||||
name={metric?.name || ''}
|
|
||||||
timeFrame={metric?.time_frame}
|
|
||||||
metricLink={metricLink}
|
|
||||||
isDragOverlay={false}
|
|
||||||
readOnly={readOnly}
|
|
||||||
description={metric?.description}
|
|
||||||
threeDotMenuItems={threeDotMenuItems}
|
|
||||||
/>
|
|
||||||
</CardHeader>
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className={cn(
|
|
||||||
'h-full w-full overflow-hidden bg-transparent',
|
|
||||||
isTable ? '' : 'p-3',
|
|
||||||
isDragOverlay ? 'pointer-events-none' : 'pointer-events-auto'
|
|
||||||
)}>
|
|
||||||
{content()}
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,37 +2,35 @@ import { cn } from '@/lib/classMerge';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Dropdown, type DropdownItems } from '../dropdown';
|
import { Dropdown, type DropdownItems } from '../dropdown';
|
||||||
|
|
||||||
export const MetricCardThreeMenuContainer = React.memo(
|
export const MetricCardThreeMenuContainer = ({
|
||||||
({
|
children,
|
||||||
children,
|
dropdownItems,
|
||||||
dropdownItems,
|
className
|
||||||
className
|
}: {
|
||||||
}: {
|
className?: string;
|
||||||
className?: string;
|
children: React.ReactNode;
|
||||||
children: React.ReactNode;
|
dropdownItems: DropdownItems;
|
||||||
dropdownItems: DropdownItems;
|
}) => {
|
||||||
}) => {
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}}
|
}}
|
||||||
className={cn(
|
className={cn(
|
||||||
// Use opacity and pointer-events instead of display:none to maintain positioning context
|
// Use opacity and pointer-events instead of display:none to maintain positioning context
|
||||||
'-mr-2 hidden group-hover:block',
|
'-mr-2 hidden group-hover:block',
|
||||||
'group-hover:pointer-events-auto',
|
'group-hover:pointer-events-auto',
|
||||||
isOpen && 'pointer-events-auto block',
|
isOpen && 'pointer-events-auto block',
|
||||||
className
|
className
|
||||||
)}>
|
)}>
|
||||||
<Dropdown items={dropdownItems} side="top" align="end" onOpenChange={setIsOpen}>
|
<Dropdown items={dropdownItems} side="top" align="end" onOpenChange={setIsOpen}>
|
||||||
{children}
|
{children}
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
);
|
|
||||||
|
|
||||||
MetricCardThreeMenuContainer.displayName = 'MetricCardThreeMenuContainer';
|
MetricCardThreeMenuContainer.displayName = 'MetricCardThreeMenuContainer';
|
||||||
|
|
|
@ -20,57 +20,55 @@ export const MetricTitle: React.FC<{
|
||||||
isDragOverlay: boolean;
|
isDragOverlay: boolean;
|
||||||
readOnly?: boolean;
|
readOnly?: boolean;
|
||||||
threeDotMenuItems: DropdownItems;
|
threeDotMenuItems: DropdownItems;
|
||||||
}> = React.memo(
|
}> = ({
|
||||||
({
|
readOnly = true,
|
||||||
readOnly = true,
|
name,
|
||||||
name,
|
description,
|
||||||
description,
|
isDragOverlay,
|
||||||
isDragOverlay,
|
metricLink,
|
||||||
metricLink,
|
timeFrame,
|
||||||
timeFrame,
|
threeDotMenuItems
|
||||||
threeDotMenuItems
|
}) => {
|
||||||
}) => {
|
const router = useRouter();
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
useMount(() => {
|
useMount(() => {
|
||||||
if (metricLink) router.prefetch(metricLink);
|
if (metricLink) router.prefetch(metricLink);
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="group flex h-full min-h-0 w-full flex-1 flex-nowrap space-x-0.5">
|
<div className="group flex h-full min-h-0 w-full flex-1 flex-nowrap space-x-0.5">
|
||||||
<div className={'flex h-full flex-1 cursor-pointer flex-col space-y-0.5 overflow-hidden'}>
|
<div className={'flex h-full flex-1 cursor-pointer flex-col space-y-0.5 overflow-hidden'}>
|
||||||
<div className="flex w-full justify-between space-x-0.5 overflow-hidden">
|
<div className="flex w-full justify-between space-x-0.5 overflow-hidden">
|
||||||
<Title
|
<Title
|
||||||
as="h4"
|
as="h4"
|
||||||
truncate
|
truncate
|
||||||
className="text-md! whitespace-nowrap"
|
className="text-md! whitespace-nowrap"
|
||||||
style={{ fontSize: '14px' }}>
|
style={{ fontSize: '14px' }}>
|
||||||
{`${name}`}
|
{`${name}`}
|
||||||
</Title>
|
</Title>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex w-full items-center overflow-hidden">
|
|
||||||
<Text
|
|
||||||
className={`w-full ${timeFrame || description ? 'visible' : 'hidden'}`}
|
|
||||||
size="sm"
|
|
||||||
variant="secondary"
|
|
||||||
truncate={true}>
|
|
||||||
{timeFrame || '_'}
|
|
||||||
|
|
||||||
{description && timeFrame && ' • '}
|
|
||||||
|
|
||||||
{description}
|
|
||||||
</Text>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isDragOverlay || readOnly ? null : (
|
<div className="flex w-full items-center overflow-hidden">
|
||||||
<MetricCardThreeMenuContainer dropdownItems={threeDotMenuItems}>
|
<Text
|
||||||
<Button variant="ghost" className="hover:bg-item-active" prefix={<DotsVertical />} />
|
className={`w-full ${timeFrame || description ? 'visible' : 'hidden'}`}
|
||||||
</MetricCardThreeMenuContainer>
|
size="sm"
|
||||||
)}
|
variant="secondary"
|
||||||
|
truncate={true}>
|
||||||
|
{timeFrame || '_'}
|
||||||
|
|
||||||
|
{description && timeFrame && ' • '}
|
||||||
|
|
||||||
|
{description}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
|
||||||
}
|
{isDragOverlay || readOnly ? null : (
|
||||||
);
|
<MetricCardThreeMenuContainer dropdownItems={threeDotMenuItems}>
|
||||||
|
<Button variant="ghost" className="hover:bg-item-active" prefix={<DotsVertical />} />
|
||||||
|
</MetricCardThreeMenuContainer>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
MetricTitle.displayName = 'MetricTitle';
|
MetricTitle.displayName = 'MetricTitle';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import React, { useMemo,useContext } from 'react';
|
import React, { useMemo, useContext } from 'react';
|
||||||
import { useMemoizedFn } from '@/hooks';
|
import { useMemoizedFn } from '@/hooks';
|
||||||
import { useDashboardMetric } from './useDashboardMetric';
|
import { useDashboardMetric } from './useDashboardMetric';
|
||||||
import { assetParamsToRoute } from '@/lib/assets';
|
import { assetParamsToRoute } from '@/lib/assets';
|
||||||
|
@ -47,10 +47,8 @@ const DashboardMetricItemBase: React.FC<{
|
||||||
const animate =
|
const animate =
|
||||||
!initialAnimationEnded && !isDragOverlay && dataLength < 125 && numberOfMetrics <= 30;
|
!initialAnimationEnded && !isDragOverlay && dataLength < 125 && numberOfMetrics <= 30;
|
||||||
|
|
||||||
const error: string | undefined = useMemo(
|
const error: string | undefined =
|
||||||
() => metric?.error || metricDataError?.message || metricError?.message || undefined,
|
metric?.error || metricDataError?.message || metricError?.message || undefined;
|
||||||
[metric?.error, metricDataError, metricError]
|
|
||||||
);
|
|
||||||
|
|
||||||
const metricLink = useMemo(() => {
|
const metricLink = useMemo(() => {
|
||||||
return assetParamsToRoute({
|
return assetParamsToRoute({
|
||||||
|
@ -92,4 +90,4 @@ const DashboardMetricItemBase: React.FC<{
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DashboardMetricItem = React.memo(DashboardMetricItemBase);
|
export const DashboardMetricItem = DashboardMetricItemBase;
|
||||||
|
|
Loading…
Reference in New Issue