From 4eca05fb9c912a8c24b35ad94e131bfc7fdb52a9 Mon Sep 17 00:00:00 2001 From: Nate Kelley Date: Wed, 20 Aug 2025 15:01:37 -0600 Subject: [PATCH] relative app segmented --- apps/server/src/api/v2/reports/[id]/GET.ts | 8 +- .../api/buster_rest/reports/queryRequests.ts | 16 +-- .../reports/reportVersionNumber.ts | 4 +- .../src/api/buster_rest/reports/requests.ts | 4 +- apps/web-tss/src/api/query_keys/reports.ts | 4 +- .../popups/SaveResetFilePopupBase.tsx | 1 - .../ui/segmented/AppSegmented.stories.tsx | 66 --------- .../components/ui/segmented/AppSegmented.tsx | 126 ++++++++++++------ .../MetricContainerHeaderSegment.tsx | 78 +++++++++++ apps/web-tss/src/routeTree.gen.ts | 38 +++--- .../_app/_asset/metrics.$metricId.result.tsx | 6 - .../_app/_asset/metrics.$metricId.results.tsx | 6 + .../api/buster_rest/reports/queryRequests.ts | 16 +-- .../src/api/buster_rest/reports/requests.ts | 6 +- apps/web/src/api/query_keys/reports.ts | 4 +- 15 files changed, 216 insertions(+), 167 deletions(-) create mode 100644 apps/web-tss/src/layouts/AssetContainer/MetricAssetContainer/MetricContainerHeaderSegment.tsx delete mode 100644 apps/web-tss/src/routes/app/_app/_asset/metrics.$metricId.result.tsx create mode 100644 apps/web-tss/src/routes/app/_app/_asset/metrics.$metricId.results.tsx diff --git a/apps/server/src/api/v2/reports/[id]/GET.ts b/apps/server/src/api/v2/reports/[id]/GET.ts index 9953d4632..794ea21ff 100644 --- a/apps/server/src/api/v2/reports/[id]/GET.ts +++ b/apps/server/src/api/v2/reports/[id]/GET.ts @@ -1,5 +1,5 @@ import { type ReportElementsWithIds, getReport } from '@buster/database'; -import type { GetReportIndividualResponse, ReportElements } from '@buster/server-shared/reports'; +import type { GetReportResponse, ReportElements } from '@buster/server-shared/reports'; import { markdownToPlatejs } from '@buster/server-utils/report'; import { Hono } from 'hono'; import { HTTPException } from 'hono/http-exception'; @@ -8,7 +8,7 @@ import { standardErrorHandler } from '../../../../utils/response'; export async function getReportHandler( reportId: string, user: { id: string } -): Promise { +): Promise { const report = await getReport({ reportId, userId: user.id }); const platejsResult = await markdownToPlatejs(report.content); @@ -19,7 +19,7 @@ export async function getReportHandler( const content: ReportElementsWithIds = platejsResult.elements as ReportElementsWithIds; - const response: GetReportIndividualResponse = { + const response: GetReportResponse = { ...report, content, }; @@ -36,7 +36,7 @@ const app = new Hono() throw new HTTPException(404, { message: 'Report ID is required' }); } - const response: GetReportIndividualResponse = await getReportHandler(reportId, user); + const response: GetReportResponse = await getReportHandler(reportId, user); return c.json(response); }) .onError(standardErrorHandler); diff --git a/apps/web-tss/src/api/buster_rest/reports/queryRequests.ts b/apps/web-tss/src/api/buster_rest/reports/queryRequests.ts index 455185c2d..83a867f92 100644 --- a/apps/web-tss/src/api/buster_rest/reports/queryRequests.ts +++ b/apps/web-tss/src/api/buster_rest/reports/queryRequests.ts @@ -1,7 +1,4 @@ -import type { - GetReportIndividualResponse, - UpdateReportResponse, -} from '@buster/server-shared/reports'; +import type { GetReportResponse, UpdateReportResponse } from '@buster/server-shared/reports'; import { QueryClient, type UseQueryOptions, @@ -95,12 +92,9 @@ export const prefetchGetReport = async ( /** * Hook to get an individual report by ID */ -export const useGetReport = ( +export const useGetReport = ( { reportId, versionNumber }: { reportId: string | undefined; versionNumber?: number }, - options?: Omit< - UseQueryOptions, - 'queryKey' | 'queryFn' - > + options?: Omit, 'queryKey' | 'queryFn'> ) => { const queryFn = () => { return getReportById(reportId ?? ''); @@ -136,7 +130,7 @@ export const useUpdateReport = () => { UpdateReportResponse, RustApiError, Parameters[0], - { previousReport?: GetReportIndividualResponse } + { previousReport?: GetReportResponse } >({ mutationFn: updateReport, onMutate: async ({ reportId, ...data }) => { @@ -146,7 +140,7 @@ export const useUpdateReport = () => { }); // Snapshot the previous value - const previousReport = queryClient.getQueryData( + const previousReport = queryClient.getQueryData( reportsQueryKeys.reportsGetReport(reportId, 'LATEST').queryKey ); diff --git a/apps/web-tss/src/api/buster_rest/reports/reportVersionNumber.ts b/apps/web-tss/src/api/buster_rest/reports/reportVersionNumber.ts index 6a2acfa27..cb2f602d4 100644 --- a/apps/web-tss/src/api/buster_rest/reports/reportVersionNumber.ts +++ b/apps/web-tss/src/api/buster_rest/reports/reportVersionNumber.ts @@ -1,10 +1,10 @@ -import type { GetReportIndividualResponse } from '@buster/server-shared/reports'; +import type { GetReportResponse } from '@buster/server-shared/reports'; import { useQuery } from '@tanstack/react-query'; import { useSearch } from '@tanstack/react-router'; import { useMemo } from 'react'; import { reportsQueryKeys } from '@/api/query_keys/reports'; -const stableVersionDataSelector = (data: GetReportIndividualResponse) => data.version_number; +const stableVersionDataSelector = (data: GetReportResponse) => data.version_number; const stableVersionSearchSelector = (state: { report_version_number?: number | undefined }) => state.report_version_number; diff --git a/apps/web-tss/src/api/buster_rest/reports/requests.ts b/apps/web-tss/src/api/buster_rest/reports/requests.ts index 738db4b01..d5c818ddc 100644 --- a/apps/web-tss/src/api/buster_rest/reports/requests.ts +++ b/apps/web-tss/src/api/buster_rest/reports/requests.ts @@ -1,5 +1,5 @@ import type { - GetReportIndividualResponse, + GetReportResponse, GetReportsListRequest, GetReportsListResponse, UpdateReportRequest, @@ -21,7 +21,7 @@ export const getReportsList = async (params?: GetReportsListRequest) => { * Get an individual report by ID */ export const getReportById = async (reportId: string) => { - return mainApiV2.get(`/reports/${reportId}`).then((res) => res.data); + return mainApiV2.get(`/reports/${reportId}`).then((res) => res.data); }; /** diff --git a/apps/web-tss/src/api/query_keys/reports.ts b/apps/web-tss/src/api/query_keys/reports.ts index e4ecb5e1f..f8ff61fb2 100644 --- a/apps/web-tss/src/api/query_keys/reports.ts +++ b/apps/web-tss/src/api/query_keys/reports.ts @@ -1,5 +1,5 @@ import type { - GetReportIndividualResponse, + GetReportResponse, GetReportsListRequest, GetReportsListResponse, } from '@buster/server-shared/reports'; @@ -14,7 +14,7 @@ const reportsGetList = (filters?: GetReportsListRequest) => }); const reportsGetReport = (reportId: string, versionNumber: number | 'LATEST') => - queryOptions({ + queryOptions({ queryKey: ['reports', 'get', reportId, versionNumber || 'LATEST'] as const, staleTime: 60 * 1000, // 60 seconds }); diff --git a/apps/web-tss/src/components/features/popups/SaveResetFilePopupBase.tsx b/apps/web-tss/src/components/features/popups/SaveResetFilePopupBase.tsx index a8df60759..acc3acb84 100644 --- a/apps/web-tss/src/components/features/popups/SaveResetFilePopupBase.tsx +++ b/apps/web-tss/src/components/features/popups/SaveResetFilePopupBase.tsx @@ -2,7 +2,6 @@ import React from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; import { Button } from '@/components/ui/buttons'; import { Command, ReturnKey, TriangleWarning } from '@/components/ui/icons'; -import { PreventNavigation } from '@/components/ui/layouts/PreventNavigation'; import { PopupContainer, PopupSplitter } from '@/components/ui/popup'; import { Text } from '@/components/ui/typography'; diff --git a/apps/web-tss/src/components/ui/segmented/AppSegmented.stories.tsx b/apps/web-tss/src/components/ui/segmented/AppSegmented.stories.tsx index 570259e92..3cf591af5 100644 --- a/apps/web-tss/src/components/ui/segmented/AppSegmented.stories.tsx +++ b/apps/web-tss/src/components/ui/segmented/AppSegmented.stories.tsx @@ -2,7 +2,6 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import { useState } from 'react'; import { Checkbox } from '../checkbox'; import { Grid, PaintRoller, Star, Storage } from '../icons'; -import { PreventNavigation } from '../layouts/PreventNavigation'; import { AppSegmented } from './AppSegmented'; const meta: Meta = { @@ -130,68 +129,3 @@ export const WithOnlyIcons: Story = { ], }, }; - -export const WithPreventDefault: Story = { - args: { - options: [ - { - value: 'tab1', - icon: , - link: { - to: '/app/datasets', - }, - label: 'Tab 1', - tooltip: 'Tooltip 1', - }, - { - value: 'tab2', - icon: , - link: { - to: '/app/datasets', - }, - label: 'Tab 2', - tooltip: 'Tooltip 2', - }, - { - value: 'tab3', - icon: , - link: { - to: '/app/datasets', - }, - label: 'Tab 3', - tooltip: 'Tooltip 3', - }, - ], - }, - render: (args) => { - const [isDirty, setIsDirty] = useState(true); - - return ( -
- - -
- setIsDirty(checked === 'indeterminate' ? true : checked)} - /> -

{isDirty ? 'Dirty' : 'Clean'}

-
- - { - alert('ok'); - return Promise.resolve(); - }} - onCancel={() => { - alert('cancel'); - return Promise.resolve(); - }} - /> -
- ); - }, -}; diff --git a/apps/web-tss/src/components/ui/segmented/AppSegmented.tsx b/apps/web-tss/src/components/ui/segmented/AppSegmented.tsx index 5e3434b2c..bb7c4fa22 100644 --- a/apps/web-tss/src/components/ui/segmented/AppSegmented.tsx +++ b/apps/web-tss/src/components/ui/segmented/AppSegmented.tsx @@ -1,34 +1,50 @@ 'use client'; import * as Tabs from '@radix-ui/react-tabs'; -import { Link, useNavigate } from '@tanstack/react-router'; +import { + Link, + type LinkProps, + type RegisteredRouter, + type ValidateFromPath, + type ValidateLinkOptions, +} from '@tanstack/react-router'; import { cva } from 'class-variance-authority'; import { motion } from 'framer-motion'; import * as React from 'react'; import { useEffect, useLayoutEffect, useState, useTransition } from 'react'; import { useSize } from '@/hooks/useSize'; import { cn } from '@/lib/classMerge'; -import type { OptionsTo } from '@/types/routes'; import { Tooltip } from '../tooltip/Tooltip'; -export interface SegmentedItem { +export interface SegmentedItem< + T extends string | number = string, + TRouter extends RegisteredRouter = RegisteredRouter, + TOptions = unknown, + TFrom extends string = string, +> { value: T; label?: React.ReactNode; icon?: React.ReactNode; disabled?: boolean; tooltip?: string; - link?: OptionsTo; + link?: ValidateLinkOptions; } -export interface AppSegmentedProps { - options: SegmentedItem[]; +export interface AppSegmentedProps< + T extends string | number = string, + TRouter extends RegisteredRouter = RegisteredRouter, + TOptions = unknown, + TFrom extends string = string, +> { + options: SegmentedItem[]; value?: T; - onChange?: (value: SegmentedItem) => void; + onChange?: (value: SegmentedItem) => void; className?: string; size?: 'default' | 'large'; block?: boolean; type?: 'button' | 'track'; disabled?: boolean; + from?: ValidateFromPath; } const heightVariants = cva('h-6', { @@ -85,7 +101,7 @@ const triggerVariants = cva( } ); -const gliderVariants = cva('absolute border-border rounded border', { +const gliderVariants = cva('glider absolute border-border rounded border', { variants: { type: { button: 'bg-item-select', @@ -95,14 +111,26 @@ const gliderVariants = cva('absolute border-border rounded border', { }); // Create a type for the forwardRef component that includes displayName -type AppSegmentedComponent = (( - props: AppSegmentedProps & { ref?: React.ForwardedRef } +type AppSegmentedComponent = (< + T extends string | number = string, + TRouter extends RegisteredRouter = RegisteredRouter, + TOptions = unknown, + TFrom extends string = string, +>( + props: AppSegmentedProps & { + ref?: React.ForwardedRef; + } ) => React.ReactElement) & { displayName?: string; }; // Update the component definition to properly handle generics -export const AppSegmented: AppSegmentedComponent = (({ +export const AppSegmented: AppSegmentedComponent = (< + T extends string | number = string, + TRouter extends RegisteredRouter = RegisteredRouter, + TOptions = unknown, + TFrom extends string = string, +>({ options, type = 'track', value, @@ -110,7 +138,8 @@ export const AppSegmented: AppSegmentedComponent = () => { + from, +}: AppSegmentedProps) => { const rootRef = React.useRef(null); const elementSize = useSize(rootRef, 25); const tabRefs = React.useRef>(new Map()); @@ -120,7 +149,7 @@ export const AppSegmented: AppSegmentedComponent = ( { const item = options.find((item) => item.value === value); @@ -163,7 +192,6 @@ export const AppSegmented: AppSegmentedComponent = ( {isMeasured && ( @@ -197,12 +225,13 @@ export const AppSegmented: AppSegmentedComponent = ( ( } + item={item as SegmentedItem} selectedValue={selectedValue as string} size={size} block={block} tabRefs={tabRefs} handleTabClick={handleTabClick} + from={from} /> ))} @@ -212,34 +241,58 @@ export const AppSegmented: AppSegmentedComponent = ( { - item: SegmentedItem; +interface SegmentedTriggerProps< + T extends string = string, + TRouter extends RegisteredRouter = RegisteredRouter, + TOptions = unknown, + TFrom extends string = string, +> { + item: SegmentedItem; selectedValue: string; - size: AppSegmentedProps['size']; - block: AppSegmentedProps['block']; + size: AppSegmentedProps['size']; + block: AppSegmentedProps['block']; tabRefs: React.MutableRefObject>; handleTabClick: (value: string) => void; + from?: ValidateFromPath; } -function SegmentedTriggerComponent(props: SegmentedTriggerProps) { - const { item, selectedValue, size, block, tabRefs, handleTabClick } = props; +function SegmentedTriggerComponent< + T extends string = string, + TRouter extends RegisteredRouter = RegisteredRouter, + TOptions = unknown, + TFrom extends string = string, +>(props: SegmentedTriggerProps) { + const { item, selectedValue, size, block, tabRefs, handleTabClick, from } = props; const { tooltip, label, icon, disabled, value, link } = item; - const navigate = useNavigate(); - const LinkDiv = link ? Link : 'div'; - - const handleClick = async (e: React.MouseEvent) => { - if (link) { - e.preventDefault(); - handleTabClick(value); - // Wait for a short duration to allow the animation to complete - await new Promise((resolve) => setTimeout(resolve, 1)); - navigate(link); - } else { - handleTabClick(value); - } + const handleClick = (_e: React.MouseEvent) => { + handleTabClick(value); }; + const commonProps = { + onClick: handleClick, + 'data-testid': `segmented-trigger-${value}`, + }; + + const linkContent = ( + <> + {icon && {icon}} + {label && {label}} + + ); + + const linkDiv = link ? ( + + {linkContent} + + ) : ( +
{linkContent}
+ ); + return ( (props: SegmentedTr }) )} > - - {icon && {icon}} - {label && {label}} - + {linkDiv} ); diff --git a/apps/web-tss/src/layouts/AssetContainer/MetricAssetContainer/MetricContainerHeaderSegment.tsx b/apps/web-tss/src/layouts/AssetContainer/MetricAssetContainer/MetricContainerHeaderSegment.tsx new file mode 100644 index 000000000..f4da8be06 --- /dev/null +++ b/apps/web-tss/src/layouts/AssetContainer/MetricAssetContainer/MetricContainerHeaderSegment.tsx @@ -0,0 +1,78 @@ +import { type ParsedLocation, useLocation } from '@tanstack/react-router'; +import React, { useCallback, useMemo } from 'react'; +import { AppSegmented } from '@/components/ui/segmented'; +import { useIsMetricReadOnly } from '@/context/Metrics/useIsMetricReadOnly'; + +interface MetricContainerHeaderSegmentProps { + metricId: string; + metric_version_number: number | undefined; +} + +export const MetricContainerHeaderSegment: React.FC = React.memo( + (props) => { + const { metricId, metric_version_number } = props; + + const { isFetched, isError } = useIsMetricReadOnly({ + metricId, + }); + + if (!isFetched || isError) return null; + + return ; + } +); + +MetricContainerHeaderSegment.displayName = 'MetricContainerHeaderSegment'; + +type MetricView = 'chart' | 'results' | 'sql'; + +const MetricSegments: React.FC = React.memo(() => { + const location = useLocation({ + select: useCallback((location: ParsedLocation) => { + // Get the last value after a slash in the pathname + const pathSegments = location.pathname.split('/').filter(Boolean); + const lastSegment = pathSegments[pathSegments.length - 1] || ''; + return lastSegment; + }, []), + }); + + const selectedView: MetricView = useMemo(() => { + if (location === 'chart') return 'chart'; + if (location === 'results') return 'results'; + if (location === 'sql') return 'sql'; + return 'chart'; + }, [location]); + + return ( + + ); +}); + +MetricSegments.displayName = 'MetricSegments'; diff --git a/apps/web-tss/src/routeTree.gen.ts b/apps/web-tss/src/routeTree.gen.ts index 4f0752828..28d91ef1a 100644 --- a/apps/web-tss/src/routeTree.gen.ts +++ b/apps/web-tss/src/routeTree.gen.ts @@ -50,7 +50,7 @@ import { Route as AppAppAssetDashboardsDashboardIdIndexRouteImport } from './rou import { Route as AppAppAssetCollectionsCollectionIdIndexRouteImport } from './routes/app/_app/_asset/collections.$collectionId.index' import { Route as AppAppAssetChatsChatIdIndexRouteImport } from './routes/app/_app/_asset/chats.$chatId.index' import { Route as AppAppAssetMetricsMetricIdSqlRouteImport } from './routes/app/_app/_asset/metrics.$metricId.sql' -import { Route as AppAppAssetMetricsMetricIdResultRouteImport } from './routes/app/_app/_asset/metrics.$metricId.result' +import { Route as AppAppAssetMetricsMetricIdResultsRouteImport } from './routes/app/_app/_asset/metrics.$metricId.results' import { Route as AppAppAssetMetricsMetricIdChartRouteImport } from './routes/app/_app/_asset/metrics.$metricId.chart' import { Route as AppAppAssetReportsReportIdMetricsMetricIdRouteImport } from './routes/app/_app/_asset/reports.$reportId.metrics.$metricId' import { Route as AppAppAssetDashboardsDashboardIdMetricsMetricIdRouteImport } from './routes/app/_app/_asset/dashboards.$dashboardId.metrics.$metricId' @@ -286,10 +286,10 @@ const AppAppAssetMetricsMetricIdSqlRoute = path: '/sql', getParentRoute: () => AppAppAssetMetricsMetricIdRoute, } as any) -const AppAppAssetMetricsMetricIdResultRoute = - AppAppAssetMetricsMetricIdResultRouteImport.update({ - id: '/result', - path: '/result', +const AppAppAssetMetricsMetricIdResultsRoute = + AppAppAssetMetricsMetricIdResultsRouteImport.update({ + id: '/results', + path: '/results', getParentRoute: () => AppAppAssetMetricsMetricIdRoute, } as any) const AppAppAssetMetricsMetricIdChartRoute = @@ -464,7 +464,7 @@ export interface FileRoutesByFullPath { '/app/settings/datasources/add': typeof AppSettingsSettingsDatasourcesAddRoute '/app/settings/datasources/': typeof AppSettingsSettingsDatasourcesIndexRoute '/app/metrics/$metricId/chart': typeof AppAppAssetMetricsMetricIdChartRoute - '/app/metrics/$metricId/result': typeof AppAppAssetMetricsMetricIdResultRoute + '/app/metrics/$metricId/results': typeof AppAppAssetMetricsMetricIdResultsRoute '/app/metrics/$metricId/sql': typeof AppAppAssetMetricsMetricIdSqlRoute '/app/chats/$chatId': typeof AppAppAssetChatsChatIdIndexRoute '/app/collections/$collectionId': typeof AppAppAssetCollectionsCollectionIdIndexRoute @@ -522,7 +522,7 @@ export interface FileRoutesByTo { '/app/settings/datasources/add': typeof AppSettingsSettingsDatasourcesAddRoute '/app/settings/datasources': typeof AppSettingsSettingsDatasourcesIndexRoute '/app/metrics/$metricId/chart': typeof AppAppAssetMetricsMetricIdChartRoute - '/app/metrics/$metricId/result': typeof AppAppAssetMetricsMetricIdResultRoute + '/app/metrics/$metricId/results': typeof AppAppAssetMetricsMetricIdResultsRoute '/app/metrics/$metricId/sql': typeof AppAppAssetMetricsMetricIdSqlRoute '/app/chats/$chatId': typeof AppAppAssetChatsChatIdIndexRoute '/app/collections/$collectionId': typeof AppAppAssetCollectionsCollectionIdIndexRoute @@ -585,7 +585,7 @@ export interface FileRoutesById { '/app/_settings/settings/datasources/add': typeof AppSettingsSettingsDatasourcesAddRoute '/app/_settings/settings/datasources/': typeof AppSettingsSettingsDatasourcesIndexRoute '/app/_app/_asset/metrics/$metricId/chart': typeof AppAppAssetMetricsMetricIdChartRoute - '/app/_app/_asset/metrics/$metricId/result': typeof AppAppAssetMetricsMetricIdResultRoute + '/app/_app/_asset/metrics/$metricId/results': typeof AppAppAssetMetricsMetricIdResultsRoute '/app/_app/_asset/metrics/$metricId/sql': typeof AppAppAssetMetricsMetricIdSqlRoute '/app/_app/_asset/chats/$chatId/': typeof AppAppAssetChatsChatIdIndexRoute '/app/_app/_asset/collections/$collectionId/': typeof AppAppAssetCollectionsCollectionIdIndexRoute @@ -646,7 +646,7 @@ export interface FileRouteTypes { | '/app/settings/datasources/add' | '/app/settings/datasources/' | '/app/metrics/$metricId/chart' - | '/app/metrics/$metricId/result' + | '/app/metrics/$metricId/results' | '/app/metrics/$metricId/sql' | '/app/chats/$chatId' | '/app/collections/$collectionId' @@ -704,7 +704,7 @@ export interface FileRouteTypes { | '/app/settings/datasources/add' | '/app/settings/datasources' | '/app/metrics/$metricId/chart' - | '/app/metrics/$metricId/result' + | '/app/metrics/$metricId/results' | '/app/metrics/$metricId/sql' | '/app/chats/$chatId' | '/app/collections/$collectionId' @@ -766,7 +766,7 @@ export interface FileRouteTypes { | '/app/_settings/settings/datasources/add' | '/app/_settings/settings/datasources/' | '/app/_app/_asset/metrics/$metricId/chart' - | '/app/_app/_asset/metrics/$metricId/result' + | '/app/_app/_asset/metrics/$metricId/results' | '/app/_app/_asset/metrics/$metricId/sql' | '/app/_app/_asset/chats/$chatId/' | '/app/_app/_asset/collections/$collectionId/' @@ -1098,11 +1098,11 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AppAppAssetMetricsMetricIdSqlRouteImport parentRoute: typeof AppAppAssetMetricsMetricIdRoute } - '/app/_app/_asset/metrics/$metricId/result': { - id: '/app/_app/_asset/metrics/$metricId/result' - path: '/result' - fullPath: '/app/metrics/$metricId/result' - preLoaderRoute: typeof AppAppAssetMetricsMetricIdResultRouteImport + '/app/_app/_asset/metrics/$metricId/results': { + id: '/app/_app/_asset/metrics/$metricId/results' + path: '/results' + fullPath: '/app/metrics/$metricId/results' + preLoaderRoute: typeof AppAppAssetMetricsMetricIdResultsRouteImport parentRoute: typeof AppAppAssetMetricsMetricIdRoute } '/app/_app/_asset/metrics/$metricId/chart': { @@ -1261,15 +1261,15 @@ declare module '@tanstack/react-start/server' { interface AppAppAssetMetricsMetricIdRouteChildren { AppAppAssetMetricsMetricIdChartRoute: typeof AppAppAssetMetricsMetricIdChartRoute - AppAppAssetMetricsMetricIdResultRoute: typeof AppAppAssetMetricsMetricIdResultRoute + AppAppAssetMetricsMetricIdResultsRoute: typeof AppAppAssetMetricsMetricIdResultsRoute AppAppAssetMetricsMetricIdSqlRoute: typeof AppAppAssetMetricsMetricIdSqlRoute } const AppAppAssetMetricsMetricIdRouteChildren: AppAppAssetMetricsMetricIdRouteChildren = { AppAppAssetMetricsMetricIdChartRoute: AppAppAssetMetricsMetricIdChartRoute, - AppAppAssetMetricsMetricIdResultRoute: - AppAppAssetMetricsMetricIdResultRoute, + AppAppAssetMetricsMetricIdResultsRoute: + AppAppAssetMetricsMetricIdResultsRoute, AppAppAssetMetricsMetricIdSqlRoute: AppAppAssetMetricsMetricIdSqlRoute, } diff --git a/apps/web-tss/src/routes/app/_app/_asset/metrics.$metricId.result.tsx b/apps/web-tss/src/routes/app/_app/_asset/metrics.$metricId.result.tsx deleted file mode 100644 index 26744ec8e..000000000 --- a/apps/web-tss/src/routes/app/_app/_asset/metrics.$metricId.result.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import { createFileRoute } from '@tanstack/react-router'; -import * as metricChartServerAssetContext from '@/context/BusterAssets/metric-server/metricChartServerAssetContext'; - -export const Route = createFileRoute('/app/_app/_asset/metrics/$metricId/result')({ - ...metricChartServerAssetContext, -}); diff --git a/apps/web-tss/src/routes/app/_app/_asset/metrics.$metricId.results.tsx b/apps/web-tss/src/routes/app/_app/_asset/metrics.$metricId.results.tsx new file mode 100644 index 000000000..2be540a49 --- /dev/null +++ b/apps/web-tss/src/routes/app/_app/_asset/metrics.$metricId.results.tsx @@ -0,0 +1,6 @@ +import { createFileRoute } from '@tanstack/react-router'; +import * as metricResultsServerAssetContext from '@/context/BusterAssets/metric-server/metricResultsServerAssetContext'; + +export const Route = createFileRoute('/app/_app/_asset/metrics/$metricId/results')({ + ...metricResultsServerAssetContext, +}); diff --git a/apps/web/src/api/buster_rest/reports/queryRequests.ts b/apps/web/src/api/buster_rest/reports/queryRequests.ts index efe13197e..c1635680d 100644 --- a/apps/web/src/api/buster_rest/reports/queryRequests.ts +++ b/apps/web/src/api/buster_rest/reports/queryRequests.ts @@ -9,10 +9,7 @@ import { create } from 'mutative'; import { useMemoizedFn } from '@/hooks'; import { queryKeys } from '@/api/query_keys'; import type { RustApiError } from '../errors'; -import type { - GetReportIndividualResponse, - UpdateReportResponse -} from '@buster/server-shared/reports'; +import type { GetReportResponse, UpdateReportResponse } from '@buster/server-shared/reports'; import { getReportsList, getReportsList_server, @@ -86,12 +83,9 @@ export const prefetchGetReportsListClient = async ( /** * Hook to get an individual report by ID */ -export const useGetReport = ( +export const useGetReport = ( { reportId, versionNumber }: { reportId: string | undefined; versionNumber?: number }, - options?: Omit< - UseQueryOptions, - 'queryKey' | 'queryFn' - > + options?: Omit, 'queryKey' | 'queryFn'> ) => { const queryFn = useMemoizedFn(() => { return getReportById(reportId!); @@ -127,7 +121,7 @@ export const useUpdateReport = () => { UpdateReportResponse, RustApiError, Parameters[0], - { previousReport?: GetReportIndividualResponse } + { previousReport?: GetReportResponse } >({ mutationFn: updateReport, onMutate: async ({ reportId, ...data }) => { @@ -137,7 +131,7 @@ export const useUpdateReport = () => { }); // Snapshot the previous value - const previousReport = queryClient.getQueryData( + const previousReport = queryClient.getQueryData( queryKeys.reportsGetReport(reportId).queryKey ); diff --git a/apps/web/src/api/buster_rest/reports/requests.ts b/apps/web/src/api/buster_rest/reports/requests.ts index b5257470b..5f27ad189 100644 --- a/apps/web/src/api/buster_rest/reports/requests.ts +++ b/apps/web/src/api/buster_rest/reports/requests.ts @@ -4,7 +4,7 @@ import { BASE_URL_V2 } from '../config'; import type { GetReportsListRequest, GetReportsListResponse, - GetReportIndividualResponse, + GetReportResponse, UpdateReportRequest, UpdateReportResponse } from '@buster/server-shared/reports'; @@ -34,14 +34,14 @@ export const getReportsList_server = async (params?: Parameters { - return mainApiV2.get(`/reports/${reportId}`).then((res) => res.data); + return mainApiV2.get(`/reports/${reportId}`).then((res) => res.data); }; /** * Server-side version of getReportById */ export const getReportById_server = async (reportId: string) => { - return await serverFetch(`/reports/${reportId}`, { + return await serverFetch(`/reports/${reportId}`, { baseURL: BASE_URL_V2, method: 'GET' }); diff --git a/apps/web/src/api/query_keys/reports.ts b/apps/web/src/api/query_keys/reports.ts index e27124bb1..f2181702c 100644 --- a/apps/web/src/api/query_keys/reports.ts +++ b/apps/web/src/api/query_keys/reports.ts @@ -1,7 +1,7 @@ import { queryOptions } from '@tanstack/react-query'; import type { GetReportsListResponse, - GetReportIndividualResponse, + GetReportResponse, GetReportsListRequest } from '@buster/server-shared/reports'; @@ -14,7 +14,7 @@ const reportsGetList = (filters?: GetReportsListRequest) => }); const reportsGetReport = (reportId: string, versionNumber?: number | null) => - queryOptions({ + queryOptions({ queryKey: ['reports', 'get', reportId, versionNumber || 'INITIAL'] as const, staleTime: 60 * 1000 // 60 seconds });