start fixing dashboards

This commit is contained in:
Nate Kelley 2025-03-18 13:36:58 -06:00
parent 1ac8839aff
commit b47f586afa
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
12 changed files with 72 additions and 51 deletions

View File

@ -0,0 +1,15 @@
import { AppAssetCheckLayout } from '@/layouts/AppAssetCheckLayout';
export default async function EmbedMetricsLayout({
children,
params: { dashboardId }
}: {
children: React.ReactNode;
params: { dashboardId: string };
}) {
return (
<AppAssetCheckLayout type="dashboard" assetId={dashboardId}>
{children}
</AppAssetCheckLayout>
);
}

View File

@ -1,7 +1,11 @@
export default function EmbedDashboardsPage({ import { DashboardController } from '@/controllers/DashboardController';
params: { dashboardId }
}: { export default async function EmbedDashboardsPage(props: {
params: { dashboardId: string }; params: Promise<{ dashboardId: string }>;
}) { }) {
return <div>EmbedDashboardsPage {dashboardId}</div>; const params = await props.params;
const { dashboardId } = params;
return <DashboardController dashboardId={dashboardId} />;
} }

View File

@ -2,11 +2,13 @@ import { AppAssetCheckLayout } from '@/layouts/AppAssetCheckLayout';
export default async function EmbedMetricsLayout({ export default async function EmbedMetricsLayout({
children, children,
params: { metricId } params
}: { }: {
children: React.ReactNode; children: React.ReactNode;
params: { metricId: string }; params: Promise<{ metricId: string }>;
}) { }) {
const { metricId } = await params;
return ( return (
<AppAssetCheckLayout type="metric" assetId={metricId}> <AppAssetCheckLayout type="metric" assetId={metricId}>
{children} {children}

View File

@ -40,7 +40,6 @@ export interface BusterChartRenderComponentProps
| 'metricValueLabel' | 'metricValueLabel'
| 'id' | 'id'
| 'bordered' | 'bordered'
| 'editable'
| 'groupByMethod' | 'groupByMethod'
| 'error' | 'error'
| 'pieChartAxis' | 'pieChartAxis'

View File

@ -15,7 +15,7 @@ type ContainerProps = {
items: ResizeableGridDragItem[]; items: ResizeableGridDragItem[];
index: number; index: number;
columnSizes: number[] | undefined; columnSizes: number[] | undefined;
allowEdit?: boolean; readOnly?: boolean;
onRowLayoutChange: (layout: number[], rowId: string) => void; onRowLayoutChange: (layout: number[], rowId: string) => void;
fluid?: boolean; fluid?: boolean;
}; };
@ -25,15 +25,15 @@ export const BusterResizeColumns: React.FC<ContainerProps> = ({
onRowLayoutChange = () => {}, onRowLayoutChange = () => {},
index: rowIndex, index: rowIndex,
columnSizes, columnSizes,
allowEdit = true, readOnly = true,
items = [], items = [],
fluid = true fluid = true
}) => { }) => {
const { setNodeRef, isOver, active, over } = useSortable({ const { setNodeRef, isOver, active, over } = useSortable({
id: rowId, id: rowId,
disabled: !allowEdit disabled: readOnly
}); });
const mouse = useMouse({ moveThrottleMs: 50, disabled: !allowEdit || !over }); const mouse = useMouse({ moveThrottleMs: 50, disabled: readOnly || !over });
const [isDragginResizeColumn, setIsDraggingResizeColumn] = useState<number | null>(null); const [isDragginResizeColumn, setIsDraggingResizeColumn] = useState<number | null>(null);
const columnMarkerColumnIndex = useMemo( const columnMarkerColumnIndex = useMemo(
() => (typeof isDragginResizeColumn === 'number' ? isDragginResizeColumn + 1 : null), () => (typeof isDragginResizeColumn === 'number' ? isDragginResizeColumn + 1 : null),
@ -97,6 +97,7 @@ export const BusterResizeColumns: React.FC<ContainerProps> = ({
}, [activeDragId, items, active?.id]); }, [activeDragId, items, active?.id]);
const memoizedStyle = useMemo(() => { const memoizedStyle = useMemo(() => {
console.log(isOver);
return { return {
backgroundColor: isOver ? 'rgba(0, 0, 0, 0.25)' : undefined backgroundColor: isOver ? 'rgba(0, 0, 0, 0.25)' : undefined
}; };
@ -128,7 +129,7 @@ export const BusterResizeColumns: React.FC<ContainerProps> = ({
const sashRender = useMemoizedFn((index: number, active: boolean) => { const sashRender = useMemoizedFn((index: number, active: boolean) => {
return ( return (
<ColumnSash <ColumnSash
allowEdit={allowEdit && canResize} allowEdit={!readOnly && canResize}
isDraggingId={isDragginResizeColumn} isDraggingId={isDragginResizeColumn}
active={active} active={active}
index={index} index={index}
@ -154,7 +155,7 @@ export const BusterResizeColumns: React.FC<ContainerProps> = ({
autoSizeId="resize-column" autoSizeId="resize-column"
split="vertical" split="vertical"
sizes={sizes} sizes={sizes}
allowResize={allowEdit && canResize} allowResize={!readOnly && canResize}
onDragStart={onDragStart} onDragStart={onDragStart}
onDragEnd={onDragEnd} onDragEnd={onDragEnd}
sashRender={sashRender} sashRender={sashRender}
@ -176,7 +177,7 @@ export const BusterResizeColumns: React.FC<ContainerProps> = ({
!!over && insertPosition(item.id, index, mouse.clientX) === Position.Before !!over && insertPosition(item.id, index, mouse.clientX) === Position.Before
} }
/> />
<BusterSortableItemDragContainer itemId={item.id} allowEdit={allowEdit}> <BusterSortableItemDragContainer itemId={item.id} allowEdit={!readOnly}>
{item.children} {item.children}
</BusterSortableItemDragContainer> </BusterSortableItemDragContainer>
<DropzonePlaceholder <DropzonePlaceholder

View File

@ -13,9 +13,9 @@ import { cn } from '@/lib/classMerge';
export const BusterResizeRows: React.FC<{ export const BusterResizeRows: React.FC<{
rows: BusterResizeableGridRow[]; rows: BusterResizeableGridRow[];
className: string; className: string;
allowEdit?: boolean; readOnly?: boolean;
onRowLayoutChange: (rows: BusterResizeableGridRow[]) => void; onRowLayoutChange: (rows: BusterResizeableGridRow[]) => void;
}> = ({ allowEdit = true, rows, className, onRowLayoutChange }) => { }> = ({ readOnly = false, rows, className, onRowLayoutChange }) => {
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
const [isDraggingResizeId, setIsDraggingResizeId] = useState<number | null>(null); const [isDraggingResizeId, setIsDraggingResizeId] = useState<number | null>(null);
const [sizes, setSizes] = useState<number[]>(rows.map((r) => r.rowHeight ?? MIN_ROW_HEIGHT)); const [sizes, setSizes] = useState<number[]>(rows.map((r) => r.rowHeight ?? MIN_ROW_HEIGHT));
@ -69,7 +69,7 @@ export const BusterResizeRows: React.FC<{
active={false} active={false}
setIsDraggingResizeId={setIsDraggingResizeId} setIsDraggingResizeId={setIsDraggingResizeId}
onResize={handleResize} onResize={handleResize}
allowEdit={allowEdit} readOnly={readOnly}
/> />
{rows.map((row, index) => ( {rows.map((row, index) => (
@ -83,7 +83,7 @@ export const BusterResizeRows: React.FC<{
rowId={row.id} rowId={row.id}
items={row.items} items={row.items}
index={index} index={index}
allowEdit={allowEdit} readOnly={readOnly}
columnSizes={row.columnSizes} columnSizes={row.columnSizes}
onRowLayoutChange={onRowLayoutChangePreflight} onRowLayoutChange={onRowLayoutChangePreflight}
/> />
@ -95,13 +95,13 @@ export const BusterResizeRows: React.FC<{
active={isDraggingResizeId === index} active={isDraggingResizeId === index}
setIsDraggingResizeId={setIsDraggingResizeId} setIsDraggingResizeId={setIsDraggingResizeId}
onResize={handleResize} onResize={handleResize}
allowEdit={allowEdit} readOnly={readOnly}
hideDropzone={index === rows.length - 1} hideDropzone={index === rows.length - 1}
/> />
</div> </div>
))} ))}
{allowEdit && <BusterNewItemDropzone />} {!readOnly && <BusterNewItemDropzone />}
</div> </div>
); );
}; };
@ -112,15 +112,15 @@ const ResizeRowHandle: React.FC<{
sizes: number[]; sizes: number[];
setIsDraggingResizeId: (index: number | null) => void; setIsDraggingResizeId: (index: number | null) => void;
onResize: (index: number, size: number) => void; onResize: (index: number, size: number) => void;
allowEdit: boolean; readOnly: boolean;
active: boolean; active: boolean;
top?: boolean; //if true we will not use dragging, just dropzone top?: boolean; //if true we will not use dragging, just dropzone
hideDropzone?: boolean; hideDropzone?: boolean;
}> = React.memo( }> = React.memo(
({ hideDropzone, top, id, active, allowEdit, setIsDraggingResizeId, index, sizes, onResize }) => { ({ hideDropzone, top, id, active, readOnly, setIsDraggingResizeId, index, sizes, onResize }) => {
const { setNodeRef, isOver, over } = useDroppable({ const { setNodeRef, isOver, over } = useDroppable({
id: `${NEW_ROW_ID}_${id}}`, id: `${NEW_ROW_ID}_${id}}`,
disabled: !allowEdit, disabled: readOnly,
data: { id } data: { id }
}); });
const showDropzone = !!over?.id && !hideDropzone; const showDropzone = !!over?.id && !hideDropzone;
@ -158,14 +158,14 @@ const ResizeRowHandle: React.FC<{
}; };
}, [top]); }, [top]);
const showActive = (active || isDropzoneActive) && allowEdit; const showActive = (active || isDropzoneActive) && !readOnly;
return ( return (
<div className="relative"> <div className="relative">
<div <div
id={id} id={id}
className={cn( className={cn(
allowEdit && 'hover:bg-border cursor-row-resize', !readOnly && 'hover:bg-border cursor-row-resize',
showActive && 'bg-primary! z-10 opacity-100', showActive && 'bg-primary! z-10 opacity-100',
'h-[4px] w-full rounded-sm transition-colors duration-200 ease-in-out select-none', 'h-[4px] w-full rounded-sm transition-colors duration-200 ease-in-out select-none',
!top && 'dragger absolute' !top && 'dragger absolute'

View File

@ -44,9 +44,9 @@ export const BusterResizeableGrid: React.FC<{
onStartDrag?: (d: { id: string }) => void; onStartDrag?: (d: { id: string }) => void;
onEndDrag?: (d: { id: string }) => void; onEndDrag?: (d: { id: string }) => void;
overlayComponent?: React.ReactNode; overlayComponent?: React.ReactNode;
allowEdit?: boolean; readOnly?: boolean;
}> = ({ }> = ({
allowEdit = true, readOnly = true,
className = '', className = '',
overlayComponent, overlayComponent,
rows: serverRows, rows: serverRows,
@ -57,6 +57,8 @@ export const BusterResizeableGrid: React.FC<{
const [rows, setRows] = useState<BusterResizeableGridRow[]>(serverRows); const [rows, setRows] = useState<BusterResizeableGridRow[]>(serverRows);
const styleRef = useRef<HTMLStyleElement>(undefined); const styleRef = useRef<HTMLStyleElement>(undefined);
console.log(serverRows);
const onRowLayoutChangePreflight = useMemoizedFn((newLayout: BusterResizeableGridRow[]) => { const onRowLayoutChangePreflight = useMemoizedFn((newLayout: BusterResizeableGridRow[]) => {
const filteredRows = newRowPreflight(newLayout); const filteredRows = newRowPreflight(newLayout);
@ -335,12 +337,12 @@ export const BusterResizeableGrid: React.FC<{
<BusterResizeRows <BusterResizeRows
rows={rows} rows={rows}
className={className} className={className}
allowEdit={allowEdit} readOnly={readOnly}
onRowLayoutChange={onRowLayoutChangePreflight} onRowLayoutChange={onRowLayoutChangePreflight}
/> />
</div> </div>
{allowEdit && ( {!readOnly && (
<BusterSortableOverlay <BusterSortableOverlay
activeId={activeId} activeId={activeId}
overlayComponent={overlayComponent} overlayComponent={overlayComponent}

View File

@ -65,8 +65,7 @@ export const BusterSortableOverlay: React.FC<{
return ( return (
<DragOverlay <DragOverlay
dropAnimation={dropAnimationConfig} dropAnimation={dropAnimationConfig}
modifiers={[useSnapToCenter ? snapCenterToCursor : adjustTranslate]} modifiers={[useSnapToCenter ? snapCenterToCursor : adjustTranslate]}>
style={{}}>
{activeId && ( {activeId && (
<BusterSortableItemContent <BusterSortableItemContent
itemId={activeId} itemId={activeId}
@ -75,7 +74,6 @@ export const BusterSortableOverlay: React.FC<{
style={ style={
{ {
maxWidth: widthOfItem, maxWidth: widthOfItem,
// maxWidth: '320px',
height: '100%', height: '100%',
width: '100%', width: '100%',
'--scale': scale '--scale': scale

View File

@ -14,7 +14,7 @@ export const getSupabaseServerContext = async () => {
if (!userData.data?.user) { if (!userData.data?.user) {
const { session: anonSession } = await signInWithAnonymousUser(); const { session: anonSession } = await signInWithAnonymousUser();
return { return {
user: anonSession?.user, user: anonSession?.user || null,
accessToken: anonSession?.access_token, accessToken: anonSession?.access_token,
refreshToken: anonSession?.refresh_token, refreshToken: anonSession?.refresh_token,
expiresAt: anonSession?.expires_at expiresAt: anonSession?.expires_at

View File

@ -20,7 +20,7 @@ const DEFAULT_EMPTY_METRICS: Record<string, BusterMetric> = {};
const DEFAULT_EMPTY_CONFIG: DashboardConfig = {}; const DEFAULT_EMPTY_CONFIG: DashboardConfig = {};
export const DashboardContentController: React.FC<{ export const DashboardContentController: React.FC<{
allowEdit?: boolean; readOnly?: boolean;
metrics: BusterDashboardResponse['metrics'] | undefined; metrics: BusterDashboardResponse['metrics'] | undefined;
dashboard: BusterDashboardResponse['dashboard'] | undefined; dashboard: BusterDashboardResponse['dashboard'] | undefined;
onUpdateDashboardConfig: ReturnType<typeof useUpdateDashboardConfig>['mutateAsync']; onUpdateDashboardConfig: ReturnType<typeof useUpdateDashboardConfig>['mutateAsync'];
@ -29,7 +29,7 @@ export const DashboardContentController: React.FC<{
({ ({
onOpenAddContentModal, onOpenAddContentModal,
dashboard, dashboard,
allowEdit, readOnly = false,
metrics = DEFAULT_EMPTY_METRICS, metrics = DEFAULT_EMPTY_METRICS,
onUpdateDashboardConfig onUpdateDashboardConfig
}) => { }) => {
@ -79,7 +79,7 @@ export const DashboardContentController: React.FC<{
key={item.id} key={item.id}
metricId={item.id} metricId={item.id}
dashboardId={dashboard!.id} dashboardId={dashboard!.id}
allowEdit={allowEdit} readOnly={readOnly}
numberOfMetrics={numberOfMetrics} numberOfMetrics={numberOfMetrics}
/> />
) )
@ -87,7 +87,7 @@ export const DashboardContentController: React.FC<{
}) })
}; };
}); });
}, [rows]); }, [rows, readOnly, dashboard?.id]);
const onDragEnd = useMemoizedFn(() => { const onDragEnd = useMemoizedFn(() => {
setDraggingId(null); setDraggingId(null);
@ -109,7 +109,7 @@ export const DashboardContentController: React.FC<{
<DashboardContentControllerProvider dashboard={dashboard}> <DashboardContentControllerProvider dashboard={dashboard}>
<BusterResizeableGrid <BusterResizeableGrid
rows={dashboardRows} rows={dashboardRows}
allowEdit={allowEdit} readOnly={readOnly}
onRowLayoutChange={onRowLayoutChange} onRowLayoutChange={onRowLayoutChange}
onStartDrag={onStartDrag} onStartDrag={onStartDrag}
onEndDrag={onDragEnd} onEndDrag={onDragEnd}
@ -117,7 +117,7 @@ export const DashboardContentController: React.FC<{
draggingId && ( draggingId && (
<DashboardMetricItem <DashboardMetricItem
metricId={draggingId} metricId={draggingId}
allowEdit={false} readOnly={false}
dashboardId={dashboard.id} dashboardId={dashboard.id}
isDragOverlay isDragOverlay
numberOfMetrics={numberOfMetrics} numberOfMetrics={numberOfMetrics}

View File

@ -13,9 +13,9 @@ const DashboardMetricItemBase: React.FC<{
numberOfMetrics: number; numberOfMetrics: number;
className?: string; className?: string;
isDragOverlay?: boolean; isDragOverlay?: boolean;
allowEdit?: boolean; readOnly?: boolean;
}> = ({ }> = ({
allowEdit, readOnly,
dashboardId, dashboardId,
className = '', className = '',
metricId, metricId,
@ -74,10 +74,8 @@ const DashboardMetricItemBase: React.FC<{
return ( return (
<Card <Card
ref={conatinerRef} ref={conatinerRef}
className={`metric-item flex h-full w-full flex-col overflow-auto ${className}`} className={`metric-item flex h-full w-full flex-col overflow-auto ${className}`}>
// classNames={cardClassNamesMemoized} <CardHeader size="small" className="hover:bg-item-hover border-b">
>
<CardHeader size="small" className="hover:bg-item-hover">
<MetricTitle <MetricTitle
title={metric.title} title={metric.title}
timeFrame={metric.time_frame} timeFrame={metric.time_frame}
@ -85,7 +83,7 @@ const DashboardMetricItemBase: React.FC<{
isDragOverlay={isDragOverlay} isDragOverlay={isDragOverlay}
metricId={metricId} metricId={metricId}
dashboardId={dashboardId} dashboardId={dashboardId}
allowEdit={allowEdit} readOnly={readOnly}
description={metric.description} description={metric.description}
/> />
</CardHeader> </CardHeader>
@ -105,7 +103,7 @@ const DashboardMetricItemBase: React.FC<{
animate={!isDragOverlay && animate} animate={!isDragOverlay && animate}
animateLegend={false} animateLegend={false}
columnMetadata={metricData?.data_metadata?.column_metadata} columnMetadata={metricData?.data_metadata?.column_metadata}
editable={allowEdit} //this is really only to resize the columns of a table readOnly={true}
{...chartOptions} {...chartOptions}
/> />
)} )}

View File

@ -17,11 +17,11 @@ export const MetricTitle: React.FC<{
isDragOverlay: boolean; isDragOverlay: boolean;
metricId: string; metricId: string;
dashboardId: string; dashboardId: string;
allowEdit?: boolean; readOnly?: boolean;
}> = React.memo( }> = React.memo(
({ ({
metricId, metricId,
allowEdit = true, readOnly = true,
dashboardId, dashboardId,
title, title,
description, description,
@ -43,6 +43,8 @@ export const MetricTitle: React.FC<{
}; };
}, [title, useEllipsis]); }, [title, useEllipsis]);
console.log(readOnly, isDragOverlay);
return ( return (
<Link href={metricLink}> <Link href={metricLink}>
<div <div
@ -58,7 +60,7 @@ export const MetricTitle: React.FC<{
{`${title}`} {`${title}`}
</Title> </Title>
{isDragOverlay || !allowEdit ? ( {isDragOverlay || readOnly ? (
<></> <></>
) : ( ) : (
<ThreeDotMenu <ThreeDotMenu