fix secondary mount of sql editor

This commit is contained in:
Nate Kelley 2025-04-21 11:52:19 -06:00
parent 76f479f739
commit 2115c4de06
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
8 changed files with 118 additions and 115 deletions

View File

@ -1,7 +1,7 @@
import { MetricViewResults } from '@/controllers/MetricController/MetricViewResults';
import { MetricViewResultsController } from '@/controllers/MetricController/MetricViewResults';
export default async function ResultsPage({ params }: { params: Promise<{ metricId: string }> }) {
const { metricId } = await params;
return <MetricViewResults metricId={metricId} />;
return <MetricViewResultsController metricId={metricId} />;
}

View File

@ -1,7 +1,7 @@
import { MetricViewResults } from '@/controllers/MetricController/MetricViewResults';
import { MetricViewResultsController } from '@/controllers/MetricController/MetricViewResults';
export default async function ResultsPage({ params }: { params: Promise<{ metricId: string }> }) {
const { metricId } = await params;
return <MetricViewResults metricId={metricId} />;
return <MetricViewResultsController metricId={metricId} />;
}

View File

@ -3,6 +3,7 @@ import { AppSplitter, type AppSplitterRef } from '@/components/ui/layouts/AppSpl
import { SQLContainer } from './SQLContainer';
import { DataContainer } from './DataContainer';
import type { IDataResult } from '@/api/asset_interfaces';
import { useMount } from '@/hooks';
export interface AppVerticalCodeSplitterProps {
sql: string;

View File

@ -91,9 +91,11 @@ export const AppSplitter = React.memo(
}, [hasHidden, leftHidden, sizes]);
const memoizedLeftPaneStyle = useMemo(() => {
const isHidden = leftHidden || _sizes[0] === '0%'; //leftHidden || _sizes[0] === '0px' || _sizes[0] === 0 || _sizes[0] === '0%';
const isHidden = leftHidden;
const isEffectivelyHidden = _sizes[0] === '0px' || _sizes[0] === '0%';
return {
display: isHidden ? 'none' : undefined
display: isHidden ? 'none' : undefined,
overflow: isEffectivelyHidden ? 'hidden' : undefined
};
}, [leftHidden, _sizes[0]]);

View File

@ -4,7 +4,6 @@ import { BusterChart } from '@/components/ui/charts';
import { cn } from '@/lib/classMerge';
import React, { useMemo } from 'react';
import { METRIC_CHART_CONTAINER_ID } from './config';
import { useMount } from '@/hooks';
interface MetricViewChartContentProps {
className?: string;

View File

@ -1,7 +1,7 @@
'use client';
import React, { useEffect, useMemo, useState } from 'react';
import { useMemoizedFn, useUnmount } from '@/hooks';
import { useMemoizedFn, useMount, useUnmount } from '@/hooks';
import { IDataResult } from '@/api/asset_interfaces';
import { useMetricResultsLayout } from './useMetricResultsLayout';
import { useChatLayoutContextSelector } from '@/layouts/ChatLayout/ChatLayoutContext';
@ -12,111 +12,109 @@ import { useGetMetric, useGetMetricData } from '@/api/buster_rest/metrics';
const autoSaveId = 'metric-view-results';
export const MetricViewResults: React.FC<{ metricId: string }> = React.memo(({ metricId }) => {
const appSplitterRef = React.useRef<AppSplitterRef>(null);
const selectedFileViewSecondary = useChatLayoutContextSelector(
(x) => x.selectedFileViewSecondary
);
const containerRef = React.useRef<HTMLDivElement>(null);
export const MetricViewResultsController: React.FC<{ metricId: string }> = React.memo(
({ metricId }) => {
const appSplitterRef = React.useRef<AppSplitterRef>(null);
const selectedFileViewSecondary = useChatLayoutContextSelector(
(x) => x.selectedFileViewSecondary
);
const containerRef = React.useRef<HTMLDivElement>(null);
const {
runSQL,
resetRunSQLData,
saveSQL,
saveMetricError,
runSQLError,
isSavingMetric,
isRunningSQL
} = useMetricRunSQL();
const {
runSQL,
resetRunSQLData,
saveSQL,
saveMetricError,
runSQLError,
isSavingMetric,
isRunningSQL
} = useMetricRunSQL();
const { data: metric } = useGetMetric(
{ id: metricId },
{
select: ({ sql, data_source_id }) => ({
sql,
data_source_id
})
}
);
const { data: metricData, isFetched: isFetchedInitialData } = useGetMetricData(
{ id: metricId },
{ enabled: false }
);
const [sql, setSQL] = useState(metric?.sql || '');
const dataSourceId = metric?.data_source_id || '';
const data: IDataResult = metricData?.dataFromRerun || metricData?.data || null;
const disableSave = useMemo(() => {
return !sql || isRunningSQL || sql === metric?.sql;
}, [sql, isRunningSQL, metric?.sql]);
const onRunQuery = useMemoizedFn(async () => {
try {
const res = await runSQL({
dataSourceId,
sql,
metricId
});
if (res && res.data && res.data.length > 0) {
const data = res.data;
const headerHeight = 28.1;
const heightOfRow = 28.1;
const heightOfDataContainer = headerHeight + heightOfRow * (data.length || 0);
const containerHeight = containerRef.current?.clientHeight || 0;
const maxHeight = Math.floor(containerHeight * 0.6);
const finalHeight = Math.min(heightOfDataContainer, maxHeight) + 12;
appSplitterRef.current?.setSplitSizes(['auto', `${finalHeight}px`]);
const { data: metric } = useGetMetric(
{ id: metricId },
{
select: ({ sql, data_source_id }) => ({
sql,
data_source_id
})
}
} catch (error) {
//
}
});
);
const { data: metricData, isFetched: isFetchedInitialData } = useGetMetricData(
{ id: metricId },
{ enabled: false }
);
const onSaveSQL = useMemoizedFn(async () => {
await saveSQL({
metricId,
sql,
dataSourceId
const [sql, setSQL] = useState(metric?.sql || '');
const dataSourceId = metric?.data_source_id || '';
const data: IDataResult = metricData?.dataFromRerun || metricData?.data || null;
const disableSave = useMemo(() => {
return !sql || isRunningSQL || sql === metric?.sql;
}, [sql, isRunningSQL, metric?.sql]);
const onRunQuery = useMemoizedFn(async () => {
try {
const res = await runSQL({
dataSourceId,
sql,
metricId
});
if (res && res.data && res.data.length > 0) {
const data = res.data;
const headerHeight = 28.1;
const heightOfRow = 28.1;
const heightOfDataContainer = headerHeight + heightOfRow * (data.length || 0);
const containerHeight = containerRef.current?.clientHeight || 0;
const maxHeight = Math.floor(containerHeight * 0.6);
const finalHeight = Math.min(heightOfDataContainer, maxHeight) + 12;
appSplitterRef.current?.setSplitSizes(['auto', `${finalHeight}px`]);
}
} catch (error) {
//
}
});
});
const { defaultLayout, renderSecondary } = useMetricResultsLayout({
selectedFileViewSecondary,
appSplitterRef,
autoSaveId
});
const onSaveSQL = useMemoizedFn(async () => {
await saveSQL({
metricId,
sql,
dataSourceId
});
});
useEffect(() => {
if (metric?.sql) {
setSQL(metric.sql);
}
}, [metric?.sql]);
const { defaultLayout, renderSecondary } = useMetricResultsLayout({
selectedFileViewSecondary,
appSplitterRef,
autoSaveId
});
useUnmount(() => {
resetRunSQLData({ metricId });
});
useEffect(() => {
if (metric?.sql) {
setSQL(metric.sql);
}
}, [metric?.sql]);
return (
<div ref={containerRef} className="h-full w-full p-5">
<AppVerticalCodeSplitter
ref={appSplitterRef}
autoSaveId={autoSaveId}
sql={sql}
setSQL={setSQL}
runSQLError={runSQLError || saveMetricError}
topHidden={!renderSecondary}
onRunQuery={onRunQuery}
onSaveSQL={onSaveSQL}
data={data}
disabledSave={disableSave}
fetchingData={isRunningSQL || isSavingMetric || !isFetchedInitialData}
defaultLayout={defaultLayout}
/>
</div>
);
});
return (
<div ref={containerRef} className="h-full w-full p-5">
<AppVerticalCodeSplitter
ref={appSplitterRef}
autoSaveId={autoSaveId}
sql={sql}
setSQL={setSQL}
runSQLError={runSQLError || saveMetricError}
topHidden={!renderSecondary}
onRunQuery={onRunQuery}
onSaveSQL={onSaveSQL}
data={data}
disabledSave={disableSave}
fetchingData={isRunningSQL || isSavingMetric || !isFetchedInitialData}
defaultLayout={defaultLayout}
/>
</div>
);
}
);
MetricViewResults.displayName = 'MetricViewResults';
MetricViewResultsController.displayName = 'MetricViewResultsController';

View File

@ -120,7 +120,7 @@ const EditSQLButton = React.memo(({ metricId }: { metricId: string }) => {
const selectedFileViewSecondary = useChatLayoutContextSelector(
(x) => x.selectedFileViewSecondary
);
const onSetFileView = useChatLayoutContextSelector((x) => x.onSetFileView);
const onChangePage = useAppLayoutContextSelector((x) => x.onChangePage);
const chatId = useChatIndividualContextSelector((x) => x.chatId);
const metricVersionNumber = useChatLayoutContextSelector((x) => x.metricVersionNumber);
const editableSecondaryView: MetricFileViewSecondary = 'sql-edit';
@ -148,14 +148,21 @@ const EditSQLButton = React.memo(({ metricId }: { metricId: string }) => {
// onSetFileView({ secondaryView, fileView: 'results' });
// });
console.log('href', href);
const onClickButton = useMemoizedFn(() => {
onChangePage(href, { shallow: true });
});
return (
<Link href={href}>
<Link
href={href}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}>
<SelectableButton
tooltipText="SQL editor"
icon={<SquareCode />}
onClick={() => {}}
onClick={onClickButton}
selected={isSelectedView}
/>
</Link>

View File

@ -17,17 +17,13 @@ const VersionHistoryPanel = dynamic(
),
{ loading }
);
const MetricViewResults = dynamic(
() => import('@/controllers/MetricController/MetricViewResults').then((x) => x.MetricViewResults),
{ loading }
);
export const MetricSecondaryRecord: Record<
MetricFileViewSecondary,
React.FC<FileContainerSecondaryProps>
> = {
'chart-edit': ({ selectedFile }) => <MetricEditController metricId={selectedFile?.id || ''} />,
'sql-edit': ({ selectedFile }) => <MetricViewResults metricId={selectedFile?.id || ''} />,
'sql-edit': ({ selectedFile }) => <></>, //because this is a vertical splitter, we don't want to render the sql edit view in the secondary view because it is vertical
'version-history': ({ selectedFile }) => (
<VersionHistoryPanel assetId={selectedFile?.id || ''} type="metric" />
)