diff --git a/web/src/components/features/layouts/AppVerticalCodeSplitter/AppVerticalCodeSplitter.tsx b/web/src/components/features/layouts/AppVerticalCodeSplitter/AppVerticalCodeSplitter.tsx index a634c5602..cfc54048a 100644 --- a/web/src/components/features/layouts/AppVerticalCodeSplitter/AppVerticalCodeSplitter.tsx +++ b/web/src/components/features/layouts/AppVerticalCodeSplitter/AppVerticalCodeSplitter.tsx @@ -7,7 +7,7 @@ import type { IDataResult } from '@/api/asset_interfaces'; export interface AppVerticalCodeSplitterProps { sql: string; setSQL: (sql: string) => void; - runSQLError: string | null; + runSQLError: string | undefined; onRunQuery: () => Promise; data: IDataResult; fetchingData: boolean; diff --git a/web/src/controllers/MetricController/MetricViewResults/MetricViewResultsController.tsx b/web/src/controllers/MetricController/MetricViewResults/MetricViewResultsController.tsx index 8f62ca53e..692a1ba91 100644 --- a/web/src/controllers/MetricController/MetricViewResults/MetricViewResultsController.tsx +++ b/web/src/controllers/MetricController/MetricViewResults/MetricViewResultsController.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import type { MetricViewProps } from '../config'; import { useMemoizedFn, useUnmount } from '@/hooks'; import { IDataResult } from '@/api/asset_interfaces'; @@ -18,8 +18,17 @@ export const MetricViewResults: React.FC = React.memo(({ metric ); const containerRef = React.useRef(null); - const { runSQL, resetRunSQLData, saveSQL, warnBeforeNavigating, setWarnBeforeNavigating } = - useMetricRunSQL(); + const { + runSQL, + resetRunSQLData, + saveSQL, + saveMetricError, + runSQLError, + warnBeforeNavigating, + setWarnBeforeNavigating, + isSavingMetric, + isRunningSQL + } = useMetricRunSQL(); const { data: metric } = useGetMetric({ id: metricId }, ({ sql, data_source_id }) => ({ sql, @@ -27,36 +36,37 @@ export const MetricViewResults: React.FC = React.memo(({ metric })); const { data: metricData } = useGetMetricData({ id: metricId }); - const [sql, setSQL] = React.useState(metric?.sql || ''); - const [fetchingData, setFetchingData] = React.useState(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 || fetchingData || sql === metric?.sql; - }, [sql, fetchingData, metric?.sql]); + return !sql || isRunningSQL || sql === metric?.sql; + }, [sql, isRunningSQL, metric?.sql]); const onRunQuery = useMemoizedFn(async () => { - setFetchingData(true); - const res = await runSQL({ - dataSourceId, - sql, - metricId - }); + try { + 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`]); + 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`]); + } } + } catch (error) { + // } - setFetchingData(false); }); const onSaveSQL = useMemoizedFn(async () => { @@ -90,13 +100,13 @@ export const MetricViewResults: React.FC = React.memo(({ metric autoSaveId={autoSaveId} sql={sql} setSQL={setSQL} - runSQLError={null} + runSQLError={runSQLError || saveMetricError} topHidden={!renderSecondary} onRunQuery={onRunQuery} onSaveSQL={onSaveSQL} data={data} disabledSave={disableSave} - fetchingData={fetchingData} + fetchingData={isRunningSQL || isSavingMetric} defaultLayout={defaultLayout} /> diff --git a/web/src/controllers/MetricController/MetricViewResults/useMetricRunSQL/useMetricRunSQL.ts b/web/src/controllers/MetricController/MetricViewResults/useMetricRunSQL/useMetricRunSQL.ts index 45e24cfca..f9391865c 100644 --- a/web/src/controllers/MetricController/MetricViewResults/useMetricRunSQL/useMetricRunSQL.ts +++ b/web/src/controllers/MetricController/MetricViewResults/useMetricRunSQL/useMetricRunSQL.ts @@ -14,8 +14,16 @@ export const useMetricRunSQL = () => { const queryClient = useQueryClient(); const getMetricMemoized = useGetMetricMemoized(); const { mutateAsync: updateMetricMutation } = useUpdateMetric(); - const { mutateAsync: saveMetric } = useSaveMetric(); - const { mutateAsync: runSQLMutation } = useRunSQLQuery(); + const { + mutateAsync: saveMetric, + error: saveMetricError, + isPending: isSavingMetric + } = useSaveMetric(); + const { + mutateAsync: runSQLMutation, + error: runSQLError, + isPending: isRunningSQL + } = useRunSQLQuery(); const { openSuccessNotification } = useBusterNotifications(); const [warnBeforeNavigating, setWarnBeforeNavigating] = useState(false); @@ -145,7 +153,7 @@ export const useMetricRunSQL = () => { const currentMetric = getMetricMemoized(metricId); const dataSourceId = dataSourceIdProp || currentMetric?.data_source_id; - if ((!ogConfigs || ogConfigs.sql !== sql) && dataSourceId) { + if (!ogConfigs || ogConfigs.sql !== sql) { try { await runSQL({ metricId, @@ -190,6 +198,10 @@ export const useMetricRunSQL = () => { resetRunSQLData, warnBeforeNavigating, setWarnBeforeNavigating, - saveSQL + saveSQL, + saveMetricError: saveMetricError?.message, + runSQLError: runSQLError?.message, + isSavingMetric, + isRunningSQL }; }; diff --git a/web/src/layouts/ChatLayout/FileContainer/FileContainer.tsx b/web/src/layouts/ChatLayout/FileContainer/FileContainer.tsx index f26510de0..e4bdd4dc2 100644 --- a/web/src/layouts/ChatLayout/FileContainer/FileContainer.tsx +++ b/web/src/layouts/ChatLayout/FileContainer/FileContainer.tsx @@ -6,7 +6,7 @@ import { AppPageLayout, AppSplitter, AppSplitterRef } from '@/components/ui/layo import { useChatLayoutContextSelector } from '../ChatLayoutContext'; import { createAutoSaveId } from '@/components/ui/layouts/AppSplitter/helper'; import Cookies from 'js-cookie'; -import { useDebounce, useMemoizedFn, useUpdateLayoutEffect } from '@/hooks'; +import { useDebounce, useMemoizedFn } from '@/hooks'; import { FileContainerSecondary } from './FileContainerSecondary'; interface FileContainerProps {