buster/web/src/controllers/MetricController/MetricViewResults/MetricViewResultsController...

123 lines
3.5 KiB
TypeScript
Raw Normal View History

2025-04-02 01:04:19 +08:00
'use client';
2025-03-30 12:14:08 +08:00
import React, { useEffect, useMemo, useState } from 'react';
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';
2025-04-02 01:04:19 +08:00
export const MetricViewResults: React.FC<{ metricId: string }> = React.memo(({ metricId }) => {
2025-02-06 02:27:53 +08:00
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
2025-03-30 12:14:08 +08:00
const {
runSQL,
resetRunSQLData,
saveSQL,
saveMetricError,
runSQLError,
isSavingMetric,
isRunningSQL
} = useMetricRunSQL();
2025-02-06 02:27:53 +08:00
2025-04-08 11:35:47 +08:00
const { data: metric } = useGetMetric(
{ id: metricId },
{
select: ({ sql, data_source_id }) => ({
sql,
data_source_id
})
}
);
2025-04-12 02:43:19 +08:00
const { data: metricData, isFetched: isFetchedInitialData } = useGetMetricData(
{ id: metricId },
{ enabled: false }
);
2025-02-06 02:27:53 +08:00
2025-03-30 12:14:08 +08:00
const [sql, setSQL] = useState(metric?.sql || '');
2025-02-06 03:54:06 +08:00
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-30 12:14:08 +08:00
return !sql || isRunningSQL || sql === metric?.sql;
}, [sql, isRunningSQL, metric?.sql]);
2025-02-06 03:54:06 +08:00
2025-02-06 02:27:53 +08:00
const onRunQuery = useMemoizedFn(async () => {
2025-03-30 12:14:08 +08:00
try {
const res = await runSQL({
dataSourceId,
sql,
metricId
});
2025-02-06 03:54:06 +08:00
2025-04-05 02:25:06 +08:00
if (res && res.data && res.data.length > 0) {
const data = res.data;
const headerHeight = 28.1;
const heightOfRow = 28.1;
2025-04-05 02:25:06 +08:00
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;
2025-04-05 02:25:06 +08:00
appSplitterRef.current?.setSplitSizes(['auto', `${finalHeight}px`]);
2025-02-06 03:54:06 +08:00
}
2025-03-30 12:14:08 +08:00
} catch (error) {
//
2025-02-06 03:54:06 +08:00
}
});
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">
<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-03-30 12:14:08 +08:00
runSQLError={runSQLError || saveMetricError}
2025-02-06 02:27:53 +08:00
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}
2025-04-02 01:04:19 +08:00
fetchingData={isRunningSQL || isSavingMetric || !isFetchedInitialData}
2025-02-06 02:27:53 +08:00
defaultLayout={defaultLayout}
/>
</div>
);
});
MetricViewResults.displayName = 'MetricViewResults';