2025-02-06 03:54:06 +08:00
|
|
|
import React, { useEffect, useMemo } from 'react';
|
2025-02-06 02:27:53 +08:00
|
|
|
import type { MetricViewProps } from '../config';
|
2025-03-08 07:02:56 +08:00
|
|
|
import { useMemoizedFn, useUnmount } from '@/hooks';
|
2025-02-06 02:27:53 +08:00
|
|
|
import { IDataResult } from '@/api/asset_interfaces';
|
2025-03-28 05:58:17 +08:00
|
|
|
import { useMetricResultsLayout } from './useMetricResultsLayout';
|
2025-03-08 07:02:56 +08:00
|
|
|
import { useChatLayoutContextSelector } from '@/layouts/ChatLayout/ChatLayoutContext';
|
2025-03-01 03:05:32 +08:00
|
|
|
import { AppSplitterRef } from '@/components/ui/layouts';
|
|
|
|
import { AppVerticalCodeSplitter } from '@/components/features/layouts/AppVerticalCodeSplitter';
|
2025-03-13 12:55:49 +08:00
|
|
|
import { useMetricRunSQL } from './useMetricRunSQL';
|
2025-03-20 04:47:15 +08:00
|
|
|
import { useGetMetric, useGetMetricData } from '@/api/buster_rest/metrics';
|
2025-02-06 02:27:53 +08:00
|
|
|
|
|
|
|
const autoSaveId = 'metric-view-results';
|
|
|
|
|
|
|
|
export const MetricViewResults: React.FC<MetricViewProps> = React.memo(({ metricId }) => {
|
|
|
|
const appSplitterRef = React.useRef<AppSplitterRef>(null);
|
|
|
|
const selectedFileViewSecondary = useChatLayoutContextSelector(
|
|
|
|
(x) => x.selectedFileViewSecondary
|
|
|
|
);
|
2025-02-06 03:54:06 +08:00
|
|
|
const containerRef = React.useRef<HTMLDivElement>(null);
|
2025-03-13 12:55:49 +08:00
|
|
|
|
|
|
|
const { runSQL, resetRunSQLData, saveSQL, warnBeforeNavigating, setWarnBeforeNavigating } =
|
|
|
|
useMetricRunSQL();
|
2025-02-06 02:27:53 +08:00
|
|
|
|
2025-03-26 06:28:07 +08:00
|
|
|
const { data: metric } = useGetMetric({ id: metricId }, ({ sql, data_source_id }) => ({
|
|
|
|
sql,
|
|
|
|
data_source_id
|
|
|
|
}));
|
2025-03-20 04:47:15 +08:00
|
|
|
const { data: metricData } = useGetMetricData({ id: metricId });
|
2025-02-06 02:27:53 +08:00
|
|
|
|
2025-03-20 04:47:15 +08:00
|
|
|
const [sql, setSQL] = React.useState(metric?.sql || '');
|
2025-02-06 03:54:06 +08:00
|
|
|
const [fetchingData, setFetchingData] = React.useState(false);
|
|
|
|
|
2025-03-20 04:47:15 +08:00
|
|
|
const dataSourceId = metric?.data_source_id || '';
|
2025-02-14 13:52:07 +08:00
|
|
|
const data: IDataResult = metricData?.dataFromRerun || metricData?.data || null;
|
2025-02-06 02:27:53 +08:00
|
|
|
|
2025-02-06 03:54:06 +08:00
|
|
|
const disableSave = useMemo(() => {
|
2025-03-20 04:47:15 +08:00
|
|
|
return !sql || fetchingData || sql === metric?.sql;
|
|
|
|
}, [sql, fetchingData, metric?.sql]);
|
2025-02-06 03:54:06 +08:00
|
|
|
|
2025-02-06 02:27:53 +08:00
|
|
|
const onRunQuery = useMemoizedFn(async () => {
|
2025-02-06 03:54:06 +08:00
|
|
|
setFetchingData(true);
|
|
|
|
const res = await runSQL({
|
|
|
|
dataSourceId,
|
|
|
|
sql,
|
|
|
|
metricId
|
|
|
|
});
|
|
|
|
|
|
|
|
if (res) {
|
|
|
|
if (data && data.length > 0) {
|
|
|
|
const headerHeight = 50;
|
|
|
|
const heightOfRow = 36;
|
|
|
|
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);
|
|
|
|
appSplitterRef.current?.setSplitSizes(['auto', `${finalHeight}px`]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setFetchingData(false);
|
|
|
|
});
|
|
|
|
|
|
|
|
const onSaveSQL = useMemoizedFn(async () => {
|
|
|
|
await saveSQL({
|
|
|
|
metricId,
|
|
|
|
sql,
|
|
|
|
dataSourceId
|
|
|
|
});
|
2025-02-06 02:27:53 +08:00
|
|
|
});
|
|
|
|
|
2025-03-28 05:58:17 +08:00
|
|
|
const { defaultLayout, renderSecondary } = useMetricResultsLayout({
|
2025-02-06 02:27:53 +08:00
|
|
|
selectedFileViewSecondary,
|
|
|
|
appSplitterRef,
|
2025-03-28 05:58:17 +08:00
|
|
|
autoSaveId
|
2025-02-06 02:27:53 +08:00
|
|
|
});
|
|
|
|
|
2025-02-06 03:54:06 +08:00
|
|
|
useEffect(() => {
|
2025-03-20 04:47:15 +08:00
|
|
|
if (metric?.sql) {
|
|
|
|
setSQL(metric.sql);
|
2025-02-06 03:54:06 +08:00
|
|
|
}
|
2025-03-20 04:47:15 +08:00
|
|
|
}, [metric?.sql]);
|
2025-02-06 03:54:06 +08:00
|
|
|
|
|
|
|
useUnmount(() => {
|
|
|
|
resetRunSQLData({ metricId });
|
|
|
|
});
|
|
|
|
|
2025-02-06 02:27:53 +08:00
|
|
|
return (
|
2025-03-14 10:38:27 +08:00
|
|
|
<div ref={containerRef} className="h-full w-full p-5">
|
2025-02-28 03:57:45 +08:00
|
|
|
<AppVerticalCodeSplitter
|
2025-02-06 02:27:53 +08:00
|
|
|
ref={appSplitterRef}
|
|
|
|
autoSaveId={autoSaveId}
|
|
|
|
sql={sql}
|
2025-02-06 03:54:06 +08:00
|
|
|
setSQL={setSQL}
|
2025-02-06 02:27:53 +08:00
|
|
|
runSQLError={null}
|
|
|
|
topHidden={!renderSecondary}
|
|
|
|
onRunQuery={onRunQuery}
|
2025-02-06 03:54:06 +08:00
|
|
|
onSaveSQL={onSaveSQL}
|
2025-02-06 02:27:53 +08:00
|
|
|
data={data}
|
2025-02-06 03:54:06 +08:00
|
|
|
disabledSave={disableSave}
|
|
|
|
fetchingData={fetchingData}
|
2025-02-06 02:27:53 +08:00
|
|
|
defaultLayout={defaultLayout}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
MetricViewResults.displayName = 'MetricViewResults';
|