Compare commits

...

11 Commits

205 changed files with 1188 additions and 1114 deletions

View File

@@ -79,7 +79,6 @@
"eventemitter3": "5.0.1", "eventemitter3": "5.0.1",
"file-loader": "6.1.1", "file-loader": "6.1.1",
"fontfaceobserver": "2.3.0", "fontfaceobserver": "2.3.0",
"history": "4.10.1",
"html-webpack-plugin": "5.5.0", "html-webpack-plugin": "5.5.0",
"http-proxy-middleware": "3.0.3", "http-proxy-middleware": "3.0.3",
"i18next": "^21.6.12", "i18next": "^21.6.12",
@@ -115,8 +114,7 @@
"react-markdown": "8.0.7", "react-markdown": "8.0.7",
"react-query": "3.39.3", "react-query": "3.39.3",
"react-redux": "^7.2.2", "react-redux": "^7.2.2",
"react-router-dom": "^5.2.0", "react-router": "7.5.1",
"react-router-dom-v5-compat": "6.27.0",
"react-syntax-highlighter": "15.5.0", "react-syntax-highlighter": "15.5.0",
"react-use": "^17.3.2", "react-use": "^17.3.2",
"react-virtuoso": "4.0.3", "react-virtuoso": "4.0.3",
@@ -186,7 +184,7 @@
"@types/react-lottie": "1.2.10", "@types/react-lottie": "1.2.10",
"@types/react-redux": "^7.1.11", "@types/react-redux": "^7.1.11",
"@types/react-resizable": "3.0.3", "@types/react-resizable": "3.0.3",
"@types/react-router-dom": "^5.1.6", "@types/react-router": "^5.1.20",
"@types/react-syntax-highlighter": "15.5.7", "@types/react-syntax-highlighter": "15.5.7",
"@types/redux-mock-store": "1.0.4", "@types/redux-mock-store": "1.0.4",
"@types/styled-components": "^5.1.4", "@types/styled-components": "^5.1.4",

View File

@@ -5,15 +5,17 @@ import { FeatureKeys } from 'constants/features';
import { LOCALSTORAGE } from 'constants/localStorage'; import { LOCALSTORAGE } from 'constants/localStorage';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { useGetTenantLicense } from 'hooks/useGetTenantLicense'; import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
import history from 'lib/history'; import { useGlobalEventListener } from 'hooks/useGlobalEventListener';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { isEmpty } from 'lodash-es'; import { isEmpty } from 'lodash-es';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { ReactChild, useCallback, useEffect, useMemo, useState } from 'react'; import { ReactChild, useCallback, useEffect, useMemo, useState } from 'react';
import { useQuery } from 'react-query'; import { useQuery } from 'react-query';
import { matchPath, useLocation } from 'react-router-dom'; import { matchPath, useLocation } from 'react-router';
import { LicensePlatform, LicenseState } from 'types/api/licensesV3/getActive'; import { LicensePlatform, LicenseState } from 'types/api/licensesV3/getActive';
import { Organization } from 'types/api/user/getOrganization'; import { Organization } from 'types/api/user/getOrganization';
import { USER_ROLES } from 'types/roles'; import { USER_ROLES } from 'types/roles';
import { safeNavigateNoSameURLMemo } from 'utils/navigate';
import { routePermission } from 'utils/permission'; import { routePermission } from 'utils/permission';
import routes, { import routes, {
@@ -26,6 +28,10 @@ import routes, {
function PrivateRoute({ children }: PrivateRouteProps): JSX.Element { function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
const location = useLocation(); const location = useLocation();
const { safeNavigate } = useSafeNavigate();
const { safeNavigate: unsafeNavigate } = useSafeNavigate({
preventSameUrlNavigation: false,
});
const { pathname } = location; const { pathname } = location;
const { const {
org, org,
@@ -44,9 +50,13 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
() => () =>
new Map( new Map(
[...routes, LIST_LICENSES, SUPPORT_ROUTE].map((e) => { [...routes, LIST_LICENSES, SUPPORT_ROUTE].map((e) => {
const currentPath = matchPath(pathname, { const currentPath = matchPath(
path: e.path, {
}); // Temp: Hard type cast
path: e.path as string,
},
pathname,
);
return [currentPath === null ? null : 'current', e]; return [currentPath === null ? null : 'current', e];
}), }),
), ),
@@ -101,7 +111,7 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
// if the current route is allowed to be overriden by org onboarding then only do the same // if the current route is allowed to be overriden by org onboarding then only do the same
!ROUTES_NOT_TO_BE_OVERRIDEN.includes(pathname) !ROUTES_NOT_TO_BE_OVERRIDEN.includes(pathname)
) { ) {
history.push(ROUTES.ONBOARDING); safeNavigateNoSameURLMemo(ROUTES.ONBOARDING);
} }
} }
}, [ }, [
@@ -114,31 +124,37 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
pathname, pathname,
]); ]);
const navigateToWorkSpaceBlocked = (route: any): void => { const safeNavigateToWorkSpaceBlocked = useCallback(
const { path } = route; (route: any): void => {
const { path } = route;
const isRouteEnabledForWorkspaceBlockedState = const isRouteEnabledForWorkspaceBlockedState =
isAdmin && isAdmin &&
(path === ROUTES.ORG_SETTINGS || (path === ROUTES.ORG_SETTINGS ||
path === ROUTES.BILLING || path === ROUTES.BILLING ||
path === ROUTES.MY_SETTINGS); path === ROUTES.MY_SETTINGS);
if ( if (
path && path &&
path !== ROUTES.WORKSPACE_LOCKED && path !== ROUTES.WORKSPACE_LOCKED &&
!isRouteEnabledForWorkspaceBlockedState !isRouteEnabledForWorkspaceBlockedState
) { ) {
history.push(ROUTES.WORKSPACE_LOCKED); safeNavigateNoSameURLMemo(ROUTES.WORKSPACE_LOCKED);
} }
}; },
[isAdmin],
);
const navigateToWorkSpaceAccessRestricted = (route: any): void => { const safeNavigateToWorkSpaceAccessRestricted = useCallback(
const { path } = route; (route: any): void => {
const { path } = route;
if (path && path !== ROUTES.WORKSPACE_ACCESS_RESTRICTED) { if (path && path !== ROUTES.WORKSPACE_ACCESS_RESTRICTED) {
history.push(ROUTES.WORKSPACE_ACCESS_RESTRICTED); safeNavigateNoSameURLMemo(ROUTES.WORKSPACE_ACCESS_RESTRICTED);
} }
}; },
[],
);
useEffect(() => { useEffect(() => {
if (!isFetchingActiveLicenseV3 && activeLicenseV3) { if (!isFetchingActiveLicenseV3 && activeLicenseV3) {
@@ -157,10 +173,16 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
platform === LicensePlatform.CLOUD && platform === LicensePlatform.CLOUD &&
currentRoute currentRoute
) { ) {
navigateToWorkSpaceAccessRestricted(currentRoute); safeNavigateToWorkSpaceAccessRestricted(currentRoute);
} }
} }
}, [isFetchingActiveLicenseV3, activeLicenseV3, mapRoutes, pathname]); }, [
isFetchingActiveLicenseV3,
activeLicenseV3,
mapRoutes,
pathname,
safeNavigateToWorkSpaceAccessRestricted,
]);
useEffect(() => { useEffect(() => {
if (!isFetchingActiveLicenseV3) { if (!isFetchingActiveLicenseV3) {
@@ -172,7 +194,7 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
currentRoute && currentRoute &&
activeLicenseV3?.platform === LicensePlatform.CLOUD activeLicenseV3?.platform === LicensePlatform.CLOUD
) { ) {
navigateToWorkSpaceBlocked(currentRoute); safeNavigateToWorkSpaceBlocked(currentRoute);
} }
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -182,15 +204,16 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
activeLicenseV3?.platform, activeLicenseV3?.platform,
mapRoutes, mapRoutes,
pathname, pathname,
safeNavigateToWorkSpaceBlocked,
]); ]);
const navigateToWorkSpaceSuspended = (route: any): void => { const safeNavigateToWorkSpaceSuspended = useCallback((route: any): void => {
const { path } = route; const { path } = route;
if (path && path !== ROUTES.WORKSPACE_SUSPENDED) { if (path && path !== ROUTES.WORKSPACE_SUSPENDED) {
history.push(ROUTES.WORKSPACE_SUSPENDED); safeNavigateNoSameURLMemo(ROUTES.WORKSPACE_SUSPENDED);
} }
}; }, []);
useEffect(() => { useEffect(() => {
if (!isFetchingActiveLicenseV3 && activeLicenseV3) { if (!isFetchingActiveLicenseV3 && activeLicenseV3) {
@@ -203,10 +226,16 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
currentRoute && currentRoute &&
activeLicenseV3.platform === LicensePlatform.CLOUD activeLicenseV3.platform === LicensePlatform.CLOUD
) { ) {
navigateToWorkSpaceSuspended(currentRoute); safeNavigateToWorkSpaceSuspended(currentRoute);
} }
} }
}, [isFetchingActiveLicenseV3, activeLicenseV3, mapRoutes, pathname]); }, [
isFetchingActiveLicenseV3,
activeLicenseV3,
mapRoutes,
pathname,
safeNavigateToWorkSpaceSuspended,
]);
useEffect(() => { useEffect(() => {
if (org && org.length > 0 && org[0].id !== undefined) { if (org && org.length > 0 && org[0].id !== undefined) {
@@ -220,13 +249,13 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
currentRoute?.path === ROUTES.GET_STARTED && currentRoute?.path === ROUTES.GET_STARTED &&
featureFlags?.find((e) => e.name === FeatureKeys.ONBOARDING_V3)?.active featureFlags?.find((e) => e.name === FeatureKeys.ONBOARDING_V3)?.active
) { ) {
history.push(ROUTES.GET_STARTED_WITH_CLOUD); safeNavigateNoSameURLMemo(ROUTES.GET_STARTED_WITH_CLOUD);
} }
}, [currentRoute, featureFlags]); }, [currentRoute, featureFlags]);
// eslint-disable-next-line sonarjs/cognitive-complexity // eslint-disable-next-line sonarjs/cognitive-complexity
useEffect(() => { useEffect(() => {
// if it is an old route navigate to the new route // if it is an old route safeNavigate to the new route
if (isOldRoute) { if (isOldRoute) {
const redirectUrl = oldNewRoutesMapping[pathname]; const redirectUrl = oldNewRoutesMapping[pathname];
@@ -234,7 +263,8 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
...location, ...location,
pathname: redirectUrl, pathname: redirectUrl,
}; };
history.replace(newLocation);
safeNavigateNoSameURLMemo(newLocation, { replace: true });
return; return;
} }
// if the current route // if the current route
@@ -244,21 +274,21 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
if (isLoggedInState) { if (isLoggedInState) {
const route = routePermission[key]; const route = routePermission[key];
if (route && route.find((e) => e === user.role) === undefined) { if (route && route.find((e) => e === user.role) === undefined) {
history.push(ROUTES.UN_AUTHORIZED); safeNavigateNoSameURLMemo(ROUTES.UN_AUTHORIZED);
} }
} else { } else {
setLocalStorageApi(LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT, pathname); setLocalStorageApi(LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT, pathname);
history.push(ROUTES.LOGIN); safeNavigateNoSameURLMemo(ROUTES.LOGIN);
} }
} else if (isLoggedInState) { } else if (isLoggedInState) {
const fromPathname = getLocalStorageApi( const fromPathname = getLocalStorageApi(
LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT, LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT,
); );
if (fromPathname) { if (fromPathname) {
history.push(fromPathname); safeNavigateNoSameURLMemo(fromPathname);
setLocalStorageApi(LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT, ''); setLocalStorageApi(LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT, '');
} else if (pathname !== ROUTES.SOMETHING_WENT_WRONG) { } else if (pathname !== ROUTES.SOMETHING_WENT_WRONG) {
history.push(ROUTES.HOME); safeNavigateNoSameURLMemo(ROUTES.HOME);
} }
} else { } else {
// do nothing as the unauthenticated routes are LOGIN and SIGNUP and the LOGIN container takes care of routing to signup if // do nothing as the unauthenticated routes are LOGIN and SIGNUP and the LOGIN container takes care of routing to signup if
@@ -269,17 +299,45 @@ function PrivateRoute({ children }: PrivateRouteProps): JSX.Element {
LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT, LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT,
); );
if (fromPathname) { if (fromPathname) {
history.push(fromPathname); safeNavigateNoSameURLMemo(fromPathname);
setLocalStorageApi(LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT, ''); setLocalStorageApi(LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT, '');
} else { } else {
history.push(ROUTES.HOME); safeNavigateNoSameURLMemo(ROUTES.HOME);
} }
} else { } else {
setLocalStorageApi(LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT, pathname); setLocalStorageApi(LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT, pathname);
history.push(ROUTES.LOGIN); safeNavigateNoSameURLMemo(ROUTES.LOGIN);
} }
}, [isLoggedInState, pathname, user, isOldRoute, currentRoute, location]); }, [isLoggedInState, pathname, user, isOldRoute, currentRoute, location]);
// global event listener for NAVIGATE event
// This will provide access to useNavigation hook from outside of components
useGlobalEventListener(
'SAFE_NAVIGATE',
(event: CustomEvent) => {
const { to, options } = event.detail;
if (to) {
safeNavigate(to, options);
}
},
{
passive: true,
},
);
useGlobalEventListener(
'UNSAFE_NAVIGATE',
(event: CustomEvent) => {
const { to, options } = event.detail;
if (to) {
unsafeNavigate(to, options);
}
},
{
passive: true,
},
);
// NOTE: disabling this rule as there is no need to have div // NOTE: disabling this rule as there is no need to have div
// eslint-disable-next-line react/jsx-no-useless-fragment // eslint-disable-next-line react/jsx-no-useless-fragment
return <>{children}</>; return <>{children}</>;

View File

@@ -15,7 +15,6 @@ import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
import { LICENSE_PLAN_KEY } from 'hooks/useLicense'; import { LICENSE_PLAN_KEY } from 'hooks/useLicense';
import { NotificationProvider } from 'hooks/useNotifications'; import { NotificationProvider } from 'hooks/useNotifications';
import { ResourceProvider } from 'hooks/useResourceAttribute'; import { ResourceProvider } from 'hooks/useResourceAttribute';
import history from 'lib/history';
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
import posthog from 'posthog-js'; import posthog from 'posthog-js';
import AlertRuleProvider from 'providers/Alert'; import AlertRuleProvider from 'providers/Alert';
@@ -24,9 +23,9 @@ import { IUser } from 'providers/App/types';
import { DashboardProvider } from 'providers/Dashboard/Dashboard'; import { DashboardProvider } from 'providers/Dashboard/Dashboard';
import { QueryBuilderProvider } from 'providers/QueryBuilder'; import { QueryBuilderProvider } from 'providers/QueryBuilder';
import { Suspense, useCallback, useEffect, useState } from 'react'; import { Suspense, useCallback, useEffect, useState } from 'react';
import { Route, Router, Switch } from 'react-router-dom'; import { BrowserRouter, Route, Routes } from 'react-router';
import { CompatRouter } from 'react-router-dom-v5-compat';
import { extractDomain } from 'utils/app'; import { extractDomain } from 'utils/app';
import { safeNavigateNoSameURLMemo } from 'utils/navigate';
import { Home } from './pageComponents'; import { Home } from './pageComponents';
import PrivateRoute from './Private'; import PrivateRoute from './Private';
@@ -316,7 +315,7 @@ function App(): JSX.Element {
// this needs to be on top of data missing error because if there is an error, data will never be loaded and it will // this needs to be on top of data missing error because if there is an error, data will never be loaded and it will
// move to indefinitive loading // move to indefinitive loading
if (userFetchError && pathname !== ROUTES.SOMETHING_WENT_WRONG) { if (userFetchError && pathname !== ROUTES.SOMETHING_WENT_WRONG) {
history.replace(ROUTES.SOMETHING_WENT_WRONG); safeNavigateNoSameURLMemo(ROUTES.SOMETHING_WENT_WRONG);
} }
// if all of the data is not set then return a spinner, this is required because there is some gap between loading states and data setting // if all of the data is not set then return a spinner, this is required because there is some gap between loading states and data setting
@@ -328,40 +327,33 @@ function App(): JSX.Element {
return ( return (
<Sentry.ErrorBoundary fallback={<ErrorBoundaryFallback />}> <Sentry.ErrorBoundary fallback={<ErrorBoundaryFallback />}>
<ConfigProvider theme={themeConfig}> <ConfigProvider theme={themeConfig}>
<Router history={history}> <BrowserRouter>
<CompatRouter> <NotificationProvider>
<NotificationProvider> <PrivateRoute>
<PrivateRoute> <ResourceProvider>
<ResourceProvider> <QueryBuilderProvider>
<QueryBuilderProvider> <DashboardProvider>
<DashboardProvider> <KeyboardHotkeysProvider>
<KeyboardHotkeysProvider> <AlertRuleProvider>
<AlertRuleProvider> <AppLayout>
<AppLayout> <Suspense fallback={<Spinner size="large" tip="Loading..." />}>
<Suspense fallback={<Spinner size="large" tip="Loading..." />}> <Routes>
<Switch> {routes.map(({ path, element }) => (
{routes.map(({ path, component, exact }) => ( <Route key={`${path}`} path={path} element={element} />
<Route ))}
key={`${path}`} <Route path="/" element={<Home />} />
exact={exact} <Route path="*" element={<NotFound />} />
path={path} </Routes>
component={component} </Suspense>
/> </AppLayout>
))} </AlertRuleProvider>
<Route exact path="/" component={Home} /> </KeyboardHotkeysProvider>
<Route path="*" component={NotFound} /> </DashboardProvider>
</Switch> </QueryBuilderProvider>
</Suspense> </ResourceProvider>
</AppLayout> </PrivateRoute>
</AlertRuleProvider> </NotificationProvider>
</KeyboardHotkeysProvider> </BrowserRouter>
</DashboardProvider>
</QueryBuilderProvider>
</ResourceProvider>
</PrivateRoute>
</NotificationProvider>
</CompatRouter>
</Router>
</ConfigProvider> </ConfigProvider>
</Sentry.ErrorBoundary> </Sentry.ErrorBoundary>
); );

View File

@@ -1,6 +1,6 @@
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import MessagingQueues from 'pages/MessagingQueues'; import MessagingQueues from 'pages/MessagingQueues';
import { RouteProps } from 'react-router-dom'; import { RouteProps } from 'react-router';
import { import {
AlertHistory, AlertHistory,
@@ -65,443 +65,383 @@ import {
const routes: AppRoutes[] = [ const routes: AppRoutes[] = [
{ {
component: SignupPage,
path: ROUTES.SIGN_UP, path: ROUTES.SIGN_UP,
exact: true, element: <SignupPage />,
isPrivate: false, isPrivate: false,
key: 'SIGN_UP', key: 'SIGN_UP',
}, },
{ {
path: ROUTES.GET_STARTED, path: ROUTES.GET_STARTED,
exact: false, // exact: false
component: Onboarding, element: <Onboarding />,
isPrivate: true, isPrivate: true,
key: 'GET_STARTED', key: 'GET_STARTED',
}, },
{ {
path: ROUTES.GET_STARTED_WITH_CLOUD, path: ROUTES.GET_STARTED_WITH_CLOUD,
exact: false, // exact: false
component: OnboardingV2, element: <OnboardingV2 />,
isPrivate: true, isPrivate: true,
key: 'GET_STARTED_WITH_CLOUD', key: 'GET_STARTED_WITH_CLOUD',
}, },
{ {
path: ROUTES.HOME, path: ROUTES.HOME,
exact: true, element: <Home />,
component: Home,
isPrivate: true, isPrivate: true,
key: 'HOME', key: 'HOME',
}, },
{ {
path: ROUTES.ONBOARDING, path: ROUTES.ONBOARDING,
exact: false, // exact: false
component: OrgOnboarding, element: <OrgOnboarding />,
isPrivate: true, isPrivate: true,
key: 'ONBOARDING', key: 'ONBOARDING',
}, },
{ {
component: LogsIndexToFields,
path: ROUTES.LOGS_INDEX_FIELDS, path: ROUTES.LOGS_INDEX_FIELDS,
exact: true, element: <LogsIndexToFields />,
isPrivate: true, isPrivate: true,
key: 'LOGS_INDEX_FIELDS', key: 'LOGS_INDEX_FIELDS',
}, },
{ {
component: ServicesTablePage,
path: ROUTES.APPLICATION, path: ROUTES.APPLICATION,
exact: true, element: <ServicesTablePage />,
isPrivate: true, isPrivate: true,
key: 'APPLICATION', key: 'APPLICATION',
}, },
{ {
path: ROUTES.SERVICE_METRICS, path: ROUTES.SERVICE_METRICS,
exact: true, element: <ServiceMetricsPage />,
component: ServiceMetricsPage,
isPrivate: true, isPrivate: true,
key: 'SERVICE_METRICS', key: 'SERVICE_METRICS',
}, },
{ {
path: ROUTES.SERVICE_TOP_LEVEL_OPERATIONS, path: ROUTES.SERVICE_TOP_LEVEL_OPERATIONS,
exact: true, element: <ServiceTopLevelOperationsPage />,
component: ServiceTopLevelOperationsPage,
isPrivate: true, isPrivate: true,
key: 'SERVICE_TOP_LEVEL_OPERATIONS', key: 'SERVICE_TOP_LEVEL_OPERATIONS',
}, },
{ {
path: ROUTES.SERVICE_MAP, path: ROUTES.SERVICE_MAP,
component: ServiceMapPage, element: <ServiceMapPage />,
isPrivate: true, isPrivate: true,
exact: true,
key: 'SERVICE_MAP', key: 'SERVICE_MAP',
}, },
{ {
path: ROUTES.LOGS_SAVE_VIEWS, path: ROUTES.LOGS_SAVE_VIEWS,
component: LogsSaveViews, element: <LogsSaveViews />,
isPrivate: true, isPrivate: true,
exact: true,
key: 'LOGS_SAVE_VIEWS', key: 'LOGS_SAVE_VIEWS',
}, },
{ {
path: ROUTES.TRACE_DETAIL, path: ROUTES.TRACE_DETAIL,
exact: true, element: <TraceDetail />,
component: TraceDetail,
isPrivate: true, isPrivate: true,
key: 'TRACE_DETAIL', key: 'TRACE_DETAIL',
}, },
{ {
path: ROUTES.SETTINGS, path: ROUTES.SETTINGS,
exact: true, element: <SettingsPage />,
component: SettingsPage,
isPrivate: true, isPrivate: true,
key: 'SETTINGS', key: 'SETTINGS',
}, },
{ {
path: ROUTES.USAGE_EXPLORER, path: ROUTES.USAGE_EXPLORER,
exact: true, element: <UsageExplorerPage />,
component: UsageExplorerPage,
isPrivate: true, isPrivate: true,
key: 'USAGE_EXPLORER', key: 'USAGE_EXPLORER',
}, },
{ {
path: ROUTES.ALL_DASHBOARD, path: ROUTES.ALL_DASHBOARD,
exact: true, element: <DashboardPage />,
component: DashboardPage,
isPrivate: true, isPrivate: true,
key: 'ALL_DASHBOARD', key: 'ALL_DASHBOARD',
}, },
{ {
path: ROUTES.DASHBOARD, path: ROUTES.DASHBOARD,
exact: true, element: <NewDashboardPage />,
component: NewDashboardPage,
isPrivate: true, isPrivate: true,
key: 'DASHBOARD', key: 'DASHBOARD',
}, },
{ {
path: ROUTES.DASHBOARD_WIDGET, path: ROUTES.DASHBOARD_WIDGET,
exact: true, element: <DashboardWidget />,
component: DashboardWidget,
isPrivate: true, isPrivate: true,
key: 'DASHBOARD_WIDGET', key: 'DASHBOARD_WIDGET',
}, },
{ {
path: ROUTES.EDIT_ALERTS, path: ROUTES.EDIT_ALERTS,
exact: true, element: <EditRulesPage />,
component: EditRulesPage,
isPrivate: true, isPrivate: true,
key: 'EDIT_ALERTS', key: 'EDIT_ALERTS',
}, },
{ {
path: ROUTES.LIST_ALL_ALERT, path: ROUTES.LIST_ALL_ALERT,
exact: true, element: <ListAllALertsPage />,
component: ListAllALertsPage,
isPrivate: true, isPrivate: true,
key: 'LIST_ALL_ALERT', key: 'LIST_ALL_ALERT',
}, },
{ {
path: ROUTES.ALERTS_NEW, path: ROUTES.ALERTS_NEW,
exact: true, element: <CreateNewAlerts />,
component: CreateNewAlerts,
isPrivate: true, isPrivate: true,
key: 'ALERTS_NEW', key: 'ALERTS_NEW',
}, },
{ {
path: ROUTES.ALERT_HISTORY, path: ROUTES.ALERT_HISTORY,
exact: true, element: <AlertHistory />,
component: AlertHistory,
isPrivate: true, isPrivate: true,
key: 'ALERT_HISTORY', key: 'ALERT_HISTORY',
}, },
{ {
path: ROUTES.ALERT_OVERVIEW, path: ROUTES.ALERT_OVERVIEW,
exact: true, element: <AlertOverview />,
component: AlertOverview,
isPrivate: true, isPrivate: true,
key: 'ALERT_OVERVIEW', key: 'ALERT_OVERVIEW',
}, },
{ {
path: ROUTES.TRACE, path: ROUTES.TRACE,
exact: true, element: <TraceFilter />,
component: TraceFilter,
isPrivate: true, isPrivate: true,
key: 'TRACE', key: 'TRACE',
}, },
{ {
path: ROUTES.TRACES_EXPLORER, path: ROUTES.TRACES_EXPLORER,
exact: true, element: <TracesExplorer />,
component: TracesExplorer,
isPrivate: true, isPrivate: true,
key: 'TRACES_EXPLORER', key: 'TRACES_EXPLORER',
}, },
{ {
path: ROUTES.TRACES_SAVE_VIEWS, path: ROUTES.TRACES_SAVE_VIEWS,
exact: true, element: <TracesSaveViews />,
component: TracesSaveViews,
isPrivate: true, isPrivate: true,
key: 'TRACES_SAVE_VIEWS', key: 'TRACES_SAVE_VIEWS',
}, },
{ {
path: ROUTES.TRACES_FUNNELS, path: ROUTES.TRACES_FUNNELS,
exact: true, element: <TracesFunnels />,
component: TracesFunnels,
isPrivate: true, isPrivate: true,
key: 'TRACES_FUNNELS', key: 'TRACES_FUNNELS',
}, },
{ {
path: ROUTES.TRACES_FUNNELS_DETAIL, path: ROUTES.TRACES_FUNNELS_DETAIL,
exact: true, element: <TracesFunnelDetails />,
component: TracesFunnelDetails,
isPrivate: true, isPrivate: true,
key: 'TRACES_FUNNELS_DETAIL', key: 'TRACES_FUNNELS_DETAIL',
}, },
{ {
path: ROUTES.CHANNELS_NEW, path: ROUTES.CHANNELS_NEW,
exact: true, element: <CreateAlertChannelAlerts />,
component: CreateAlertChannelAlerts,
isPrivate: true, isPrivate: true,
key: 'CHANNELS_NEW', key: 'CHANNELS_NEW',
}, },
{ {
path: ROUTES.CHANNELS_EDIT, path: ROUTES.CHANNELS_EDIT,
exact: true, element: <EditAlertChannelsAlerts />,
component: EditAlertChannelsAlerts,
isPrivate: true, isPrivate: true,
key: 'CHANNELS_EDIT', key: 'CHANNELS_EDIT',
}, },
{ {
path: ROUTES.ALL_CHANNELS, path: ROUTES.ALL_CHANNELS,
exact: true, element: <AllAlertChannels />,
component: AllAlertChannels,
isPrivate: true, isPrivate: true,
key: 'ALL_CHANNELS', key: 'ALL_CHANNELS',
}, },
{ {
path: ROUTES.ALL_ERROR, path: ROUTES.ALL_ERROR,
exact: true, element: <AllErrors />,
isPrivate: true, isPrivate: true,
component: AllErrors,
key: 'ALL_ERROR', key: 'ALL_ERROR',
}, },
{ {
path: ROUTES.ERROR_DETAIL, path: ROUTES.ERROR_DETAIL,
exact: true, element: <ErrorDetails />,
component: ErrorDetails,
isPrivate: true, isPrivate: true,
key: 'ERROR_DETAIL', key: 'ERROR_DETAIL',
}, },
{ {
path: ROUTES.VERSION, path: ROUTES.VERSION,
exact: true, element: <StatusPage />,
component: StatusPage,
isPrivate: true, isPrivate: true,
key: 'VERSION', key: 'VERSION',
}, },
{ {
path: ROUTES.ORG_SETTINGS, path: ROUTES.ORG_SETTINGS,
exact: true, element: <OrganizationSettings />,
component: OrganizationSettings,
isPrivate: true, isPrivate: true,
key: 'ORG_SETTINGS', key: 'ORG_SETTINGS',
}, },
{ {
path: ROUTES.INGESTION_SETTINGS, path: ROUTES.INGESTION_SETTINGS,
exact: true, element: <IngestionSettings />,
component: IngestionSettings,
isPrivate: true, isPrivate: true,
key: 'INGESTION_SETTINGS', key: 'INGESTION_SETTINGS',
}, },
{ {
path: ROUTES.API_KEYS, path: ROUTES.API_KEYS,
exact: true, element: <APIKeys />,
component: APIKeys,
isPrivate: true, isPrivate: true,
key: 'API_KEYS', key: 'API_KEYS',
}, },
{ {
path: ROUTES.MY_SETTINGS, path: ROUTES.MY_SETTINGS,
exact: true, element: <MySettings />,
component: MySettings,
isPrivate: true, isPrivate: true,
key: 'MY_SETTINGS', key: 'MY_SETTINGS',
}, },
{ {
path: ROUTES.CUSTOM_DOMAIN_SETTINGS, path: ROUTES.CUSTOM_DOMAIN_SETTINGS,
exact: true, element: <CustomDomainSettings />,
component: CustomDomainSettings,
isPrivate: true, isPrivate: true,
key: 'CUSTOM_DOMAIN_SETTINGS', key: 'CUSTOM_DOMAIN_SETTINGS',
}, },
{ {
path: ROUTES.LOGS, path: ROUTES.LOGS,
exact: true, element: <Logs />,
component: Logs,
key: 'LOGS', key: 'LOGS',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.LOGS_EXPLORER, path: ROUTES.LOGS_EXPLORER,
exact: true, element: <LogsExplorer />,
component: LogsExplorer,
key: 'LOGS_EXPLORER', key: 'LOGS_EXPLORER',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.OLD_LOGS_EXPLORER, path: ROUTES.OLD_LOGS_EXPLORER,
exact: true, element: <OldLogsExplorer />,
component: OldLogsExplorer,
key: 'OLD_LOGS_EXPLORER', key: 'OLD_LOGS_EXPLORER',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.LIVE_LOGS, path: ROUTES.LIVE_LOGS,
exact: true, element: <LiveLogs />,
component: LiveLogs,
key: 'LIVE_LOGS', key: 'LIVE_LOGS',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.LOGS_PIPELINES, path: ROUTES.LOGS_PIPELINES,
exact: true, element: <PipelinePage />,
component: PipelinePage,
key: 'LOGS_PIPELINES', key: 'LOGS_PIPELINES',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.LOGIN, path: ROUTES.LOGIN,
exact: true, element: <Login />,
component: Login,
isPrivate: false, isPrivate: false,
key: 'LOGIN', key: 'LOGIN',
}, },
{ {
path: ROUTES.UN_AUTHORIZED, path: ROUTES.UN_AUTHORIZED,
exact: true, element: <UnAuthorized />,
component: UnAuthorized,
key: 'UN_AUTHORIZED', key: 'UN_AUTHORIZED',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.PASSWORD_RESET, path: ROUTES.PASSWORD_RESET,
exact: true, element: <PasswordReset />,
component: PasswordReset,
key: 'PASSWORD_RESET', key: 'PASSWORD_RESET',
isPrivate: false, isPrivate: false,
}, },
{ {
path: ROUTES.SOMETHING_WENT_WRONG, path: ROUTES.SOMETHING_WENT_WRONG,
exact: true, element: <SomethingWentWrong />,
component: SomethingWentWrong,
key: 'SOMETHING_WENT_WRONG', key: 'SOMETHING_WENT_WRONG',
isPrivate: false, isPrivate: false,
}, },
{ {
path: ROUTES.BILLING, path: ROUTES.BILLING,
exact: true, element: <BillingPage />,
component: BillingPage,
key: 'BILLING', key: 'BILLING',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.WORKSPACE_LOCKED, path: ROUTES.WORKSPACE_LOCKED,
exact: true, element: <WorkspaceBlocked />,
component: WorkspaceBlocked,
isPrivate: true, isPrivate: true,
key: 'WORKSPACE_LOCKED', key: 'WORKSPACE_LOCKED',
}, },
{ {
path: ROUTES.WORKSPACE_SUSPENDED, path: ROUTES.WORKSPACE_SUSPENDED,
exact: true, element: <WorkspaceSuspended />,
component: WorkspaceSuspended,
isPrivate: true, isPrivate: true,
key: 'WORKSPACE_SUSPENDED', key: 'WORKSPACE_SUSPENDED',
}, },
{ {
path: ROUTES.WORKSPACE_ACCESS_RESTRICTED, path: ROUTES.WORKSPACE_ACCESS_RESTRICTED,
exact: true, element: <WorkspaceAccessRestricted />,
component: WorkspaceAccessRestricted,
isPrivate: true, isPrivate: true,
key: 'WORKSPACE_ACCESS_RESTRICTED', key: 'WORKSPACE_ACCESS_RESTRICTED',
}, },
{ {
path: ROUTES.SHORTCUTS, path: ROUTES.SHORTCUTS,
exact: true, element: <ShortcutsPage />,
component: ShortcutsPage,
isPrivate: true, isPrivate: true,
key: 'SHORTCUTS', key: 'SHORTCUTS',
}, },
{ {
path: ROUTES.INTEGRATIONS, path: ROUTES.INTEGRATIONS,
exact: true, element: <InstalledIntegrations />,
component: InstalledIntegrations,
isPrivate: true, isPrivate: true,
key: 'INTEGRATIONS', key: 'INTEGRATIONS',
}, },
{ {
path: ROUTES.MESSAGING_QUEUES_KAFKA, path: ROUTES.MESSAGING_QUEUES_KAFKA,
exact: true, element: <MessagingQueues />,
component: MessagingQueues,
key: 'MESSAGING_QUEUES_KAFKA', key: 'MESSAGING_QUEUES_KAFKA',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.MESSAGING_QUEUES_CELERY_TASK, path: ROUTES.MESSAGING_QUEUES_CELERY_TASK,
exact: true, element: <MessagingQueues />,
component: MessagingQueues,
key: 'MESSAGING_QUEUES_CELERY_TASK', key: 'MESSAGING_QUEUES_CELERY_TASK',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.MESSAGING_QUEUES_OVERVIEW, path: ROUTES.MESSAGING_QUEUES_OVERVIEW,
exact: true, element: <MessagingQueues />,
component: MessagingQueues,
key: 'MESSAGING_QUEUES_OVERVIEW', key: 'MESSAGING_QUEUES_OVERVIEW',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL, path: ROUTES.MESSAGING_QUEUES_KAFKA_DETAIL,
exact: true, element: <MessagingQueues />,
component: MessagingQueues,
key: 'MESSAGING_QUEUES_KAFKA_DETAIL', key: 'MESSAGING_QUEUES_KAFKA_DETAIL',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.INFRASTRUCTURE_MONITORING_HOSTS, path: ROUTES.INFRASTRUCTURE_MONITORING_HOSTS,
exact: true, element: <InfrastructureMonitoring />,
component: InfrastructureMonitoring,
key: 'INFRASTRUCTURE_MONITORING_HOSTS', key: 'INFRASTRUCTURE_MONITORING_HOSTS',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.INFRASTRUCTURE_MONITORING_KUBERNETES, path: ROUTES.INFRASTRUCTURE_MONITORING_KUBERNETES,
exact: true, element: <InfrastructureMonitoring />,
component: InfrastructureMonitoring,
key: 'INFRASTRUCTURE_MONITORING_KUBERNETES', key: 'INFRASTRUCTURE_MONITORING_KUBERNETES',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.METRICS_EXPLORER, path: ROUTES.METRICS_EXPLORER,
exact: true, element: <MetricsExplorer />,
component: MetricsExplorer,
key: 'METRICS_EXPLORER', key: 'METRICS_EXPLORER',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.METRICS_EXPLORER_EXPLORER, path: ROUTES.METRICS_EXPLORER_EXPLORER,
exact: true, element: <MetricsExplorer />,
component: MetricsExplorer,
key: 'METRICS_EXPLORER_EXPLORER', key: 'METRICS_EXPLORER_EXPLORER',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.METRICS_EXPLORER_VIEWS, path: ROUTES.METRICS_EXPLORER_VIEWS,
exact: true, element: <MetricsExplorer />,
component: MetricsExplorer,
key: 'METRICS_EXPLORER_VIEWS', key: 'METRICS_EXPLORER_VIEWS',
isPrivate: true, isPrivate: true,
}, },
{ {
path: ROUTES.API_MONITORING, path: ROUTES.API_MONITORING,
exact: true, element: <ApiMonitoring />,
component: ApiMonitoring,
key: 'API_MONITORING', key: 'API_MONITORING',
isPrivate: true, isPrivate: true,
}, },
@@ -509,16 +449,14 @@ const routes: AppRoutes[] = [
export const SUPPORT_ROUTE: AppRoutes = { export const SUPPORT_ROUTE: AppRoutes = {
path: ROUTES.SUPPORT, path: ROUTES.SUPPORT,
exact: true, element: <SupportPage />,
component: SupportPage,
key: 'SUPPORT', key: 'SUPPORT',
isPrivate: true, isPrivate: true,
}; };
export const LIST_LICENSES: AppRoutes = { export const LIST_LICENSES: AppRoutes = {
path: ROUTES.LIST_LICENSES, path: ROUTES.LIST_LICENSES,
exact: true, element: <LicensePage />,
component: LicensePage,
isPrivate: true, isPrivate: true,
key: 'LIST_LICENSES', key: 'LIST_LICENSES',
}; };
@@ -549,9 +487,8 @@ export const ROUTES_NOT_TO_BE_OVERRIDEN: string[] = [
]; ];
export interface AppRoutes { export interface AppRoutes {
component: RouteProps['component']; element: RouteProps['element'];
path: RouteProps['path']; path: RouteProps['path'];
exact: RouteProps['exact'];
isPrivate: boolean; isPrivate: boolean;
key: keyof typeof ROUTES; key: keyof typeof ROUTES;
} }

View File

@@ -1,7 +1,7 @@
import deleteLocalStorageKey from 'api/browser/localstorage/remove'; import deleteLocalStorageKey from 'api/browser/localstorage/remove';
import { LOCALSTORAGE } from 'constants/localStorage'; import { LOCALSTORAGE } from 'constants/localStorage';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import history from 'lib/history'; import { safeNavigateNoSameURLMemo } from 'utils/navigate';
export const Logout = (): void => { export const Logout = (): void => {
deleteLocalStorageKey(LOCALSTORAGE.AUTH_TOKEN); deleteLocalStorageKey(LOCALSTORAGE.AUTH_TOKEN);
@@ -23,5 +23,5 @@ export const Logout = (): void => {
window.Intercom('shutdown'); window.Intercom('shutdown');
} }
history.push(ROUTES.LOGIN); safeNavigateNoSameURLMemo(ROUTES.LOGIN);
}; };

View File

@@ -8,8 +8,9 @@ import {
import { useCeleryFilterOptions } from 'components/CeleryTask/useCeleryFilterOptions'; import { useCeleryFilterOptions } from 'components/CeleryTask/useCeleryFilterOptions';
import { SelectMaxTagPlaceholder } from 'components/MessagingQueues/MQCommon/MQCommon'; import { SelectMaxTagPlaceholder } from 'components/MessagingQueues/MQCommon/MQCommon';
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import { useHistory, useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
interface SelectOptionConfig { interface SelectOptionConfig {
placeholder: string; placeholder: string;
@@ -27,7 +28,7 @@ function FilterSelect({
); );
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
const history = useHistory(); const { safeNavigate } = useSafeNavigate();
const location = useLocation(); const location = useLocation();
return ( return (
@@ -55,7 +56,13 @@ function FilterSelect({
} }
onChange={(value): void => { onChange={(value): void => {
handleSearch(''); handleSearch('');
setQueryParamsFromOptions(value, urlQuery, history, location, queryParam); setQueryParamsFromOptions(
value,
urlQuery,
safeNavigate,
location,
queryParam,
);
}} }}
/> />
); );

View File

@@ -3,8 +3,9 @@ import './CeleryTaskConfigOptions.styles.scss';
import { Select, Spin, Typography } from 'antd'; import { Select, Spin, Typography } from 'antd';
import { SelectMaxTagPlaceholder } from 'components/MessagingQueues/MQCommon/MQCommon'; import { SelectMaxTagPlaceholder } from 'components/MessagingQueues/MQCommon/MQCommon';
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import { useHistory, useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { import {
getValuesFromQueryParams, getValuesFromQueryParams,
@@ -16,7 +17,7 @@ function CeleryTaskConfigOptions(): JSX.Element {
const { handleSearch, isFetching, options } = useCeleryFilterOptions( const { handleSearch, isFetching, options } = useCeleryFilterOptions(
'celery.task_name', 'celery.task_name',
); );
const history = useHistory(); const { safeNavigate } = useSafeNavigate();
const location = useLocation(); const location = useLocation();
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
@@ -52,7 +53,7 @@ function CeleryTaskConfigOptions(): JSX.Element {
setQueryParamsFromOptions( setQueryParamsFromOptions(
value, value,
urlQuery, urlQuery,
history, safeNavigate,
location, location,
QueryParams.taskName, QueryParams.taskName,
); );

View File

@@ -7,12 +7,13 @@ import { ViewMenuAction } from 'container/GridCardLayout/config';
import GridCard from 'container/GridCardLayout/GridCard'; import GridCard from 'container/GridCardLayout/GridCard';
import { Card } from 'container/GridCardLayout/styles'; import { Card } from 'container/GridCardLayout/styles';
import { useIsDarkMode } from 'hooks/useDarkMode'; import { useIsDarkMode } from 'hooks/useDarkMode';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import { isEmpty } from 'lodash-es'; import { isEmpty } from 'lodash-es';
import { getStartAndEndTimesInMilliseconds } from 'pages/MessagingQueues/MessagingQueuesUtils'; import { getStartAndEndTimesInMilliseconds } from 'pages/MessagingQueues/MessagingQueuesUtils';
import { useCallback, useMemo, useState } from 'react'; import { useCallback, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { useHistory, useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { UpdateTimeInterval } from 'store/actions'; import { UpdateTimeInterval } from 'store/actions';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { Widgets } from 'types/api/dashboard/getAll'; import { Widgets } from 'types/api/dashboard/getAll';
@@ -49,7 +50,7 @@ function CeleryTaskBar({
queryEnabled: boolean; queryEnabled: boolean;
checkIfDataExists?: (isDataAvailable: boolean) => void; checkIfDataExists?: (isDataAvailable: boolean) => void;
}): JSX.Element { }): JSX.Element {
const history = useHistory(); const { safeNavigate } = useSafeNavigate();
const { pathname } = useLocation(); const { pathname } = useLocation();
const dispatch = useDispatch(); const dispatch = useDispatch();
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
@@ -67,13 +68,13 @@ function CeleryTaskBar({
urlQuery.set(QueryParams.startTime, startTimestamp.toString()); urlQuery.set(QueryParams.startTime, startTimestamp.toString());
urlQuery.set(QueryParams.endTime, endTimestamp.toString()); urlQuery.set(QueryParams.endTime, endTimestamp.toString());
const generatedUrl = `${pathname}?${urlQuery.toString()}`; const generatedUrl = `${pathname}?${urlQuery.toString()}`;
history.push(generatedUrl); safeNavigate(generatedUrl);
if (startTimestamp !== endTimestamp) { if (startTimestamp !== endTimestamp) {
dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp])); dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp]));
} }
}, },
[dispatch, history, pathname, urlQuery], [dispatch, pathname, urlQuery, safeNavigate],
); );
const [barState, setBarState] = useState<CeleryTaskState>(CeleryTaskState.All); const [barState, setBarState] = useState<CeleryTaskState>(CeleryTaskState.All);

View File

@@ -5,12 +5,13 @@ import { ViewMenuAction } from 'container/GridCardLayout/config';
import GridCard from 'container/GridCardLayout/GridCard'; import GridCard from 'container/GridCardLayout/GridCard';
import { Card } from 'container/GridCardLayout/styles'; import { Card } from 'container/GridCardLayout/styles';
import { useIsDarkMode } from 'hooks/useDarkMode'; import { useIsDarkMode } from 'hooks/useDarkMode';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import { RowData } from 'lib/query/createTableColumnsFromQuery'; import { RowData } from 'lib/query/createTableColumnsFromQuery';
import { getStartAndEndTimesInMilliseconds } from 'pages/MessagingQueues/MessagingQueuesUtils'; import { getStartAndEndTimesInMilliseconds } from 'pages/MessagingQueues/MessagingQueuesUtils';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useHistory, useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { UpdateTimeInterval } from 'store/actions'; import { UpdateTimeInterval } from 'store/actions';
import { Widgets } from 'types/api/dashboard/getAll'; import { Widgets } from 'types/api/dashboard/getAll';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange'; import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
@@ -53,7 +54,7 @@ function CeleryTaskGraph({
checkIfDataExists?: (isDataAvailable: boolean) => void; checkIfDataExists?: (isDataAvailable: boolean) => void;
analyticsEvent?: string; analyticsEvent?: string;
}): JSX.Element { }): JSX.Element {
const history = useHistory(); const { safeNavigate } = useSafeNavigate();
const { pathname } = useLocation(); const { pathname } = useLocation();
const dispatch = useDispatch(); const dispatch = useDispatch();
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
@@ -82,13 +83,13 @@ function CeleryTaskGraph({
urlQuery.set(QueryParams.startTime, startTimestamp.toString()); urlQuery.set(QueryParams.startTime, startTimestamp.toString());
urlQuery.set(QueryParams.endTime, endTimestamp.toString()); urlQuery.set(QueryParams.endTime, endTimestamp.toString());
const generatedUrl = `${pathname}?${urlQuery.toString()}`; const generatedUrl = `${pathname}?${urlQuery.toString()}`;
history.push(generatedUrl); safeNavigate(generatedUrl);
if (startTimestamp !== endTimestamp) { if (startTimestamp !== endTimestamp) {
dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp])); dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp]));
} }
}, },
[dispatch, history, pathname, urlQuery], [dispatch, pathname, urlQuery, safeNavigate],
); );
return ( return (

View File

@@ -10,12 +10,13 @@ import { Card } from 'container/GridCardLayout/styles';
import { Button } from 'container/MetricsApplication/Tabs/styles'; import { Button } from 'container/MetricsApplication/Tabs/styles';
import { useGraphClickHandler } from 'container/MetricsApplication/Tabs/util'; import { useGraphClickHandler } from 'container/MetricsApplication/Tabs/util';
import { useIsDarkMode } from 'hooks/useDarkMode'; import { useIsDarkMode } from 'hooks/useDarkMode';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import { OnClickPluginOpts } from 'lib/uPlotLib/plugins/onClickPlugin'; import { OnClickPluginOpts } from 'lib/uPlotLib/plugins/onClickPlugin';
import { getStartAndEndTimesInMilliseconds } from 'pages/MessagingQueues/MessagingQueuesUtils'; import { getStartAndEndTimesInMilliseconds } from 'pages/MessagingQueues/MessagingQueuesUtils';
import { useCallback, useMemo, useState } from 'react'; import { useCallback, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { useHistory, useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { UpdateTimeInterval } from 'store/actions'; import { UpdateTimeInterval } from 'store/actions';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { DataSource } from 'types/common/queryBuilder'; import { DataSource } from 'types/common/queryBuilder';
@@ -47,7 +48,7 @@ function CeleryTaskLatencyGraph({
queryEnabled: boolean; queryEnabled: boolean;
checkIfDataExists?: (isDataAvailable: boolean) => void; checkIfDataExists?: (isDataAvailable: boolean) => void;
}): JSX.Element { }): JSX.Element {
const history = useHistory(); const { safeNavigate } = useSafeNavigate();
const { pathname } = useLocation(); const { pathname } = useLocation();
const dispatch = useDispatch(); const dispatch = useDispatch();
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
@@ -79,13 +80,13 @@ function CeleryTaskLatencyGraph({
urlQuery.set(QueryParams.startTime, startTimestamp.toString()); urlQuery.set(QueryParams.startTime, startTimestamp.toString());
urlQuery.set(QueryParams.endTime, endTimestamp.toString()); urlQuery.set(QueryParams.endTime, endTimestamp.toString());
const generatedUrl = `${pathname}?${urlQuery.toString()}`; const generatedUrl = `${pathname}?${urlQuery.toString()}`;
history.push(generatedUrl); safeNavigate(generatedUrl);
if (startTimestamp !== endTimestamp) { if (startTimestamp !== endTimestamp) {
dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp])); dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp]));
} }
}, },
[dispatch, history, pathname, urlQuery], [dispatch, pathname, urlQuery, safeNavigate],
); );
const selectedFilters = useMemo( const selectedFilters = useMemo(

View File

@@ -1,6 +1,6 @@
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
import { History, Location } from 'history';
import getRenderer from 'lib/uPlotLib/utils/getRenderer'; import getRenderer from 'lib/uPlotLib/utils/getRenderer';
import type { Location, NavigateFunction } from 'react-router';
import { Widgets } from 'types/api/dashboard/getAll'; import { Widgets } from 'types/api/dashboard/getAll';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData'; import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
@@ -17,13 +17,13 @@ export function getValuesFromQueryParams(
export function setQueryParamsFromOptions( export function setQueryParamsFromOptions(
value: string[], value: string[],
urlQuery: URLSearchParams, urlQuery: URLSearchParams,
history: History<unknown>, safeNavigate: NavigateFunction,
location: Location<unknown>, location: Location<unknown>,
queryParams: QueryParams, queryParams: QueryParams,
): void { ): void {
urlQuery.set(queryParams, value.join(',')); urlQuery.set(queryParams, value.join(','));
const generatedUrl = `${location.pathname}?${urlQuery.toString()}`; const generatedUrl = `${location.pathname}?${urlQuery.toString()}`;
history.replace(generatedUrl); safeNavigate(generatedUrl, { replace: true });
} }
export function getFiltersFromQueryParams( export function getFiltersFromQueryParams(

View File

@@ -6,7 +6,7 @@ import { useNotifications } from 'hooks/useNotifications';
import { CreditCard, X } from 'lucide-react'; import { CreditCard, X } from 'lucide-react';
import { useState } from 'react'; import { useState } from 'react';
import { useMutation } from 'react-query'; import { useMutation } from 'react-query';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { ErrorResponse, SuccessResponse } from 'types/api'; import { ErrorResponse, SuccessResponse } from 'types/api';
import { CheckoutSuccessPayloadProps } from 'types/api/billing/checkout'; import { CheckoutSuccessPayloadProps } from 'types/api/billing/checkout';

View File

@@ -26,7 +26,7 @@ import {
useMemo, useMemo,
useState, useState,
} from 'react'; } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { popupContainer } from 'utils/selectPopupContainer'; import { popupContainer } from 'utils/selectPopupContainer';
import CustomTimePickerPopoverContent from './CustomTimePickerPopoverContent'; import CustomTimePickerPopoverContent from './CustomTimePickerPopoverContent';

View File

@@ -14,7 +14,7 @@ import {
import { Clock, PenLine } from 'lucide-react'; import { Clock, PenLine } from 'lucide-react';
import { useTimezone } from 'providers/Timezone'; import { useTimezone } from 'providers/Timezone';
import { Dispatch, SetStateAction, useMemo } from 'react'; import { Dispatch, SetStateAction, useMemo } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import RangePickerModal from './RangePickerModal'; import RangePickerModal from './RangePickerModal';
import TimezonePicker from './TimezonePicker'; import TimezonePicker from './TimezonePicker';

View File

@@ -194,7 +194,7 @@ function ExplorerCard({
showSearch showSearch
placeholder="Select a view" placeholder="Select a view"
dropdownStyle={DropDownOverlay} dropdownStyle={DropDownOverlay}
dropdownMatchSelectWidth={false} popupMatchSelectWidth={false}
optionLabelProp="value" optionLabelProp="value"
value={viewName || undefined} value={viewName || undefined}
> >

View File

@@ -13,7 +13,7 @@ import { CreditCard, HelpCircle, X } from 'lucide-react';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import { useMutation } from 'react-query'; import { useMutation } from 'react-query';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { ErrorResponse, SuccessResponse } from 'types/api'; import { ErrorResponse, SuccessResponse } from 'types/api';
import { CheckoutSuccessPayloadProps } from 'types/api/billing/checkout'; import { CheckoutSuccessPayloadProps } from 'types/api/billing/checkout';

View File

@@ -1,16 +1,16 @@
import { ComponentType, lazy, LazyExoticComponent } from 'react'; import { ComponentType, lazy, LazyExoticComponent } from 'react';
import { lazyRetry } from 'utils/lazyWithRetries'; import { lazyRetry } from 'utils/lazyWithRetries';
function Loadable(importPath: {
(): LoadableProps;
}): LazyExoticComponent<LazyComponent> {
return lazy(() => lazyRetry(() => importPath()));
}
type LazyComponent = ComponentType<Record<string, unknown>>; type LazyComponent = ComponentType<Record<string, unknown>>;
type LoadableProps = Promise<{ type LoadableProps = Promise<{
default: LazyComponent; default: LazyComponent;
}>; }>;
function Loadable(importPath: {
(): LoadableProps;
}): LazyExoticComponent<LazyComponent> {
return lazy(() => lazyRetry(() => importPath()));
}
export default Loadable; export default Loadable;

View File

@@ -15,15 +15,15 @@ import {
import { OnboardingStatusResponse } from 'api/messagingQueues/onboarding/getOnboardingStatus'; import { OnboardingStatusResponse } from 'api/messagingQueues/onboarding/getOnboardingStatus';
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { History } from 'history';
import { useGetTenantLicense } from 'hooks/useGetTenantLicense'; import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { Bolt, Check, OctagonAlert, X } from 'lucide-react'; import { Bolt, Check, OctagonAlert, X } from 'lucide-react';
import { import {
KAFKA_SETUP_DOC_LINK, KAFKA_SETUP_DOC_LINK,
MessagingQueueHealthCheckService, MessagingQueueHealthCheckService,
} from 'pages/MessagingQueues/MessagingQueuesUtils'; } from 'pages/MessagingQueues/MessagingQueuesUtils';
import { ReactNode, useEffect, useState } from 'react'; import { ReactNode, useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom'; import type { NavigateFunction } from 'react-router';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
interface AttributeCheckListProps { interface AttributeCheckListProps {
@@ -46,7 +46,7 @@ export enum AttributesFilters {
function ErrorTitleAndKey({ function ErrorTitleAndKey({
title, title,
parentTitle, parentTitle,
history, safeNavigate,
isCloudUserVal, isCloudUserVal,
errorMsg, errorMsg,
isLeaf, isLeaf,
@@ -54,7 +54,7 @@ function ErrorTitleAndKey({
title: string; title: string;
parentTitle: string; parentTitle: string;
isCloudUserVal: boolean; isCloudUserVal: boolean;
history: History<unknown>; safeNavigate: NavigateFunction;
errorMsg?: string; errorMsg?: string;
isLeaf?: boolean; isLeaf?: boolean;
}): TreeDataNode { }): TreeDataNode {
@@ -76,7 +76,7 @@ function ErrorTitleAndKey({
} }
if (isCloudUserVal && !!link) { if (isCloudUserVal && !!link) {
history.push(link); safeNavigate(link);
} else { } else {
window.open(KAFKA_SETUP_DOC_LINK, '_blank'); window.open(KAFKA_SETUP_DOC_LINK, '_blank');
} }
@@ -146,7 +146,7 @@ function generateTreeDataNodes(
response: OnboardingStatusResponse['data'], response: OnboardingStatusResponse['data'],
parentTitle: string, parentTitle: string,
isCloudUserVal: boolean, isCloudUserVal: boolean,
history: History<unknown>, safeNavigate: NavigateFunction,
): TreeDataNode[] { ): TreeDataNode[] {
return response return response
.map((item) => { .map((item) => {
@@ -159,7 +159,7 @@ function generateTreeDataNodes(
title: item.attribute, title: item.attribute,
errorMsg: item.error_message || '', errorMsg: item.error_message || '',
parentTitle, parentTitle,
history, safeNavigate,
isCloudUserVal, isCloudUserVal,
}); });
} }
@@ -182,7 +182,7 @@ function AttributeCheckList({
setFilter(value); setFilter(value);
}; };
const { isCloudUser: isCloudUserVal } = useGetTenantLicense(); const { isCloudUser: isCloudUserVal } = useGetTenantLicense();
const history = useHistory(); const { safeNavigate } = useSafeNavigate();
useEffect(() => { useEffect(() => {
const filteredData = onboardingStatusResponses.map((response) => { const filteredData = onboardingStatusResponses.map((response) => {
@@ -192,7 +192,7 @@ function AttributeCheckList({
errorMsg: response.errorMsg, errorMsg: response.errorMsg,
isLeaf: true, isLeaf: true,
parentTitle: response.title, parentTitle: response.title,
history, safeNavigate,
isCloudUserVal, isCloudUserVal,
}); });
} }
@@ -210,7 +210,7 @@ function AttributeCheckList({
filteredData, filteredData,
response.title, response.title,
isCloudUserVal, isCloudUserVal,
history, safeNavigate,
), ),
}; };
}); });

View File

@@ -1,4 +1,4 @@
import { Link } from 'react-router-dom'; import { Link } from 'react-router';
import styled from 'styled-components'; import styled from 'styled-components';
export const Button = styled(Link)` export const Button = styled(Link)`

View File

@@ -1,4 +1,5 @@
import { Tabs, TabsProps } from 'antd'; import { Tabs, TabsProps } from 'antd';
import { safeNavigateNoSameURLMemo } from 'utils/navigate';
import { RouteTabProps } from './types'; import { RouteTabProps } from './types';
@@ -6,7 +7,6 @@ function RouteTab({
routes, routes,
activeKey, activeKey,
onChangeHandler, onChangeHandler,
history,
...rest ...rest
}: RouteTabProps & TabsProps): JSX.Element { }: RouteTabProps & TabsProps): JSX.Element {
const onChange = (activeRoute: string): void => { const onChange = (activeRoute: string): void => {
@@ -17,7 +17,7 @@ function RouteTab({
const selectedRoute = routes.find((e) => e.key === activeRoute); const selectedRoute = routes.find((e) => e.key === activeRoute);
if (selectedRoute) { if (selectedRoute) {
history.push(selectedRoute.route); safeNavigateNoSameURLMemo(selectedRoute.route);
} }
}; };

View File

@@ -1,5 +1,5 @@
import { TabsProps } from 'antd'; import { TabsProps } from 'antd';
import { History } from 'history'; // import type { NavigateFunction } from 'react-router';
export type TabRoutes = { export type TabRoutes = {
name: React.ReactNode; name: React.ReactNode;
@@ -12,5 +12,5 @@ export interface RouteTabProps {
routes: TabRoutes[]; routes: TabRoutes[];
activeKey: TabsProps['activeKey']; activeKey: TabsProps['activeKey'];
onChangeHandler?: (key: string) => void; onChangeHandler?: (key: string) => void;
history: History<unknown>; // safeNavigate: NavigateFunction;
} }

View File

@@ -7,7 +7,7 @@ import ROUTES from 'constants/routes';
import { useIsDarkMode } from 'hooks/useDarkMode'; import { useIsDarkMode } from 'hooks/useDarkMode';
import { DraftingCompass } from 'lucide-react'; import { DraftingCompass } from 'lucide-react';
import React from 'react'; import React from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router';
type Props = { type Props = {
children: React.ReactNode; children: React.ReactNode;

View File

@@ -3,10 +3,10 @@ import './TopContributorsCard.styles.scss';
import { Color } from '@signozhq/design-tokens'; import { Color } from '@signozhq/design-tokens';
import { Button } from 'antd'; import { Button } from 'antd';
import { useIsDarkMode } from 'hooks/useDarkMode'; import { useIsDarkMode } from 'hooks/useDarkMode';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { ArrowRight } from 'lucide-react'; import { ArrowRight } from 'lucide-react';
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import TopContributorsContent from './TopContributorsContent'; import TopContributorsContent from './TopContributorsContent';
import { TopContributorsCardProps } from './types'; import { TopContributorsCardProps } from './types';
@@ -17,6 +17,7 @@ function TopContributorsCard({
totalCurrentTriggers, totalCurrentTriggers,
}: TopContributorsCardProps): JSX.Element { }: TopContributorsCardProps): JSX.Element {
const { search } = useLocation(); const { search } = useLocation();
const { safeNavigate } = useSafeNavigate();
const searchParams = useMemo(() => new URLSearchParams(search), [search]); const searchParams = useMemo(() => new URLSearchParams(search), [search]);
const viewAllTopContributorsParam = searchParams.get('viewAllTopContributors'); const viewAllTopContributorsParam = searchParams.get('viewAllTopContributors');
@@ -43,7 +44,7 @@ function TopContributorsCard({
return newState; return newState;
}); });
history.push({ search: searchParams.toString() }); safeNavigate({ search: searchParams.toString() });
}; };
return ( return (

View File

@@ -3,8 +3,8 @@ import Uplot from 'components/Uplot';
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
import { useIsDarkMode } from 'hooks/useDarkMode'; import { useIsDarkMode } from 'hooks/useDarkMode';
import { useResizeObserver } from 'hooks/useDimensions'; import { useResizeObserver } from 'hooks/useDimensions';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import history from 'lib/history';
import heatmapPlugin from 'lib/uPlotLib/plugins/heatmapPlugin'; import heatmapPlugin from 'lib/uPlotLib/plugins/heatmapPlugin';
import timelinePlugin from 'lib/uPlotLib/plugins/timelinePlugin'; import timelinePlugin from 'lib/uPlotLib/plugins/timelinePlugin';
import { uPlotXAxisValuesFormat } from 'lib/uPlotLib/utils/constants'; import { uPlotXAxisValuesFormat } from 'lib/uPlotLib/utils/constants';
@@ -28,6 +28,8 @@ function HorizontalTimelineGraph({
isDarkMode: boolean; isDarkMode: boolean;
data: AlertRuleTimelineGraphResponse[]; data: AlertRuleTimelineGraphResponse[];
}): JSX.Element { }): JSX.Element {
const { safeNavigate } = useSafeNavigate();
const transformedData: AlignedData = useMemo(() => { const transformedData: AlignedData = useMemo(() => {
if (!data?.length) { if (!data?.length) {
return [[], []]; return [[], []];
@@ -102,7 +104,7 @@ function HorizontalTimelineGraph({
urlQuery.set(QueryParams.startTime, startTimestamp.toString()); urlQuery.set(QueryParams.startTime, startTimestamp.toString());
urlQuery.set(QueryParams.endTime, endTimestamp.toString()); urlQuery.set(QueryParams.endTime, endTimestamp.toString());
history.push({ safeNavigate({
search: urlQuery.toString(), search: urlQuery.toString(),
}); });
} }
@@ -131,6 +133,7 @@ function HorizontalTimelineGraph({
urlQuery, urlQuery,
dispatch, dispatch,
timezone.value, timezone.value,
safeNavigate,
], ],
); );
return <Uplot data={transformedData} options={options} />; return <Uplot data={transformedData} options={options} />;

View File

@@ -2,11 +2,11 @@ import './TabsAndFilters.styles.scss';
import { Color } from '@signozhq/design-tokens'; import { Color } from '@signozhq/design-tokens';
import { TimelineFilter, TimelineTab } from 'container/AlertHistory/types'; import { TimelineFilter, TimelineTab } from 'container/AlertHistory/types';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { Info } from 'lucide-react'; import { Info } from 'lucide-react';
import Tabs2 from 'periscope/components/Tabs2'; import Tabs2 from 'periscope/components/Tabs2';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
function ComingSoon(): JSX.Element { function ComingSoon(): JSX.Element {
return ( return (
@@ -41,6 +41,8 @@ function TimelineTabs(): JSX.Element {
function TimelineFilters(): JSX.Element { function TimelineFilters(): JSX.Element {
const { search } = useLocation(); const { search } = useLocation();
const { safeNavigate } = useSafeNavigate();
const searchParams = useMemo(() => new URLSearchParams(search), [search]); const searchParams = useMemo(() => new URLSearchParams(search), [search]);
const initialSelectedTab = useMemo( const initialSelectedTab = useMemo(
@@ -50,7 +52,7 @@ function TimelineFilters(): JSX.Element {
const handleFilter = (value: TimelineFilter): void => { const handleFilter = (value: TimelineFilter): void => {
searchParams.set('timelineFilter', value); searchParams.set('timelineFilter', value);
history.push({ search: searchParams.toString() }); safeNavigate({ search: searchParams.toString() });
}; };
const tabs = [ const tabs = [

View File

@@ -5,11 +5,11 @@ import { ResizeTable } from 'components/ResizeTable';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import useComponentPermission from 'hooks/useComponentPermission'; import useComponentPermission from 'hooks/useComponentPermission';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { generatePath } from 'react-router-dom'; import { generatePath } from 'react-router';
import { Channels, PayloadProps } from 'types/api/channels/getAll'; import { Channels, PayloadProps } from 'types/api/channels/getAll';
import Delete from './Delete'; import Delete from './Delete';
@@ -17,17 +17,22 @@ import Delete from './Delete';
function AlertChannels({ allChannels }: AlertChannelsProps): JSX.Element { function AlertChannels({ allChannels }: AlertChannelsProps): JSX.Element {
const { t } = useTranslation(['channels']); const { t } = useTranslation(['channels']);
const { notifications } = useNotifications(); const { notifications } = useNotifications();
const { safeNavigate } = useSafeNavigate();
const [channels, setChannels] = useState<Channels[]>(allChannels); const [channels, setChannels] = useState<Channels[]>(allChannels);
const { user } = useAppContext(); const { user } = useAppContext();
const [action] = useComponentPermission(['new_alert_action'], user.role); const [action] = useComponentPermission(['new_alert_action'], user.role);
const onClickEditHandler = useCallback((id: string) => { const onClickEditHandler = useCallback(
history.replace( (id: string) => {
generatePath(ROUTES.CHANNELS_EDIT, { safeNavigate(
id, generatePath(ROUTES.CHANNELS_EDIT, {
}), id,
); }),
}, []); { replace: true },
);
},
[safeNavigate],
);
const columns: ColumnsType<Channels> = [ const columns: ColumnsType<Channels> = [
{ {

View File

@@ -7,7 +7,7 @@ import TextToolTip from 'components/TextToolTip';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import useComponentPermission from 'hooks/useComponentPermission'; import useComponentPermission from 'hooks/useComponentPermission';
import useFetch from 'hooks/useFetch'; import useFetch from 'hooks/useFetch';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { isUndefined } from 'lodash-es'; import { isUndefined } from 'lodash-es';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useCallback, useEffect } from 'react'; import { useCallback, useEffect } from 'react';
@@ -21,13 +21,14 @@ const { Paragraph } = Typography;
function AlertChannels(): JSX.Element { function AlertChannels(): JSX.Element {
const { t } = useTranslation(['channels']); const { t } = useTranslation(['channels']);
const { user } = useAppContext(); const { user } = useAppContext();
const { safeNavigate } = useSafeNavigate();
const [addNewChannelPermission] = useComponentPermission( const [addNewChannelPermission] = useComponentPermission(
['add_new_channel'], ['add_new_channel'],
user.role, user.role,
); );
const onToggleHandler = useCallback(() => { const onToggleHandler = useCallback(() => {
history.push(ROUTES.CHANNELS_NEW); safeNavigate(ROUTES.CHANNELS_NEW);
}, []); }, [safeNavigate]);
const { loading, payload, error, errorMessage } = useFetch(getAll); const { loading, payload, error, errorMessage } = useFetch(getAll);

View File

@@ -21,17 +21,17 @@ import ROUTES from 'constants/routes';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import useResourceAttribute from 'hooks/useResourceAttribute'; import useResourceAttribute from 'hooks/useResourceAttribute';
import { convertRawQueriesToTraceSelectedTags } from 'hooks/useResourceAttribute/utils'; import { convertRawQueriesToTraceSelectedTags } from 'hooks/useResourceAttribute/utils';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { TimestampInput } from 'hooks/useTimezoneFormatter/useTimezoneFormatter'; import { TimestampInput } from 'hooks/useTimezoneFormatter/useTimezoneFormatter';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import createQueryParams from 'lib/createQueryParams'; import createQueryParams from 'lib/createQueryParams';
import history from 'lib/history';
import { isUndefined } from 'lodash-es'; import { isUndefined } from 'lodash-es';
import { useTimezone } from 'providers/Timezone'; import { useTimezone } from 'providers/Timezone';
import { useCallback, useEffect, useMemo, useRef } from 'react'; import { useCallback, useEffect, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useQueries } from 'react-query'; import { useQueries } from 'react-query';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { Link, useLocation } from 'react-router-dom'; import { Link, useLocation } from 'react-router';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { ErrorResponse, SuccessResponse } from 'types/api'; import { ErrorResponse, SuccessResponse } from 'types/api';
import { Exception, PayloadProps } from 'types/api/errors/getAll'; import { Exception, PayloadProps } from 'types/api/errors/getAll';
@@ -66,6 +66,7 @@ function AllErrors(): JSX.Element {
(state) => state.globalTime, (state) => state.globalTime,
); );
const { pathname } = useLocation(); const { pathname } = useLocation();
const { safeNavigate } = useSafeNavigate();
const params = useUrlQuery(); const params = useUrlQuery();
const { t } = useTranslation(['common']); const { t } = useTranslation(['common']);
const { const {
@@ -202,7 +203,9 @@ function AllErrors(): JSX.Element {
queryParams.serviceName = serviceFilterValue; queryParams.serviceName = serviceFilterValue;
} }
history.replace(`${pathname}?${createQueryParams(queryParams)}`); safeNavigate(`${pathname}?${createQueryParams(queryParams)}`, {
replace: true,
});
confirm(); confirm();
}, },
[ [
@@ -213,6 +216,7 @@ function AllErrors(): JSX.Element {
getUpdatedServiceName, getUpdatedServiceName,
pathname, pathname,
updatedOrder, updatedOrder,
safeNavigate,
], ],
); );
@@ -414,7 +418,7 @@ function AllErrors(): JSX.Element {
serviceName: getFilterString(params.get(urlKey.serviceName)), serviceName: getFilterString(params.get(urlKey.serviceName)),
exceptionType: getFilterString(params.get(urlKey.exceptionType)), exceptionType: getFilterString(params.get(urlKey.exceptionType)),
}); });
history.replace( safeNavigate(
`${pathname}?${createQueryParams({ `${pathname}?${createQueryParams({
order: updatedOrder, order: updatedOrder,
offset: (current - 1) * pageSize, offset: (current - 1) * pageSize,
@@ -423,10 +427,11 @@ function AllErrors(): JSX.Element {
exceptionType, exceptionType,
serviceName, serviceName,
})}`, })}`,
{ replace: true },
); );
} }
}, },
[pathname], [pathname, safeNavigate],
); );
const logEventCalledRef = useRef(false); const logEventCalledRef = useRef(false);

View File

@@ -25,7 +25,7 @@ import dayjs from 'dayjs';
import { useIsDarkMode } from 'hooks/useDarkMode'; import { useIsDarkMode } from 'hooks/useDarkMode';
import { useGetTenantLicense } from 'hooks/useGetTenantLicense'; import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { isNull } from 'lodash-es'; import { isNull } from 'lodash-es';
import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback'; import ErrorBoundaryFallback from 'pages/ErrorBoundaryFallback/ErrorBoundaryFallback';
import { INTEGRATION_TYPES } from 'pages/Integrations/utils'; import { INTEGRATION_TYPES } from 'pages/Integrations/utils';
@@ -42,7 +42,7 @@ import { Helmet } from 'react-helmet-async';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useMutation, useQueries } from 'react-query'; import { useMutation, useQueries } from 'react-query';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { Dispatch } from 'redux'; import { Dispatch } from 'redux';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import { import {
@@ -121,6 +121,7 @@ function AppLayout(props: AppLayoutProps): JSX.Element {
}); });
const isDarkMode = useIsDarkMode(); const isDarkMode = useIsDarkMode();
const { safeNavigate } = useSafeNavigate();
const { pathname } = useLocation(); const { pathname } = useLocation();
const { t } = useTranslation(['titles']); const { t } = useTranslation(['titles']);
@@ -319,9 +320,9 @@ function AppLayout(props: AppLayoutProps): JSX.Element {
const handleUpgrade = useCallback((): void => { const handleUpgrade = useCallback((): void => {
if (user.role === USER_ROLES.ADMIN) { if (user.role === USER_ROLES.ADMIN) {
history.push(ROUTES.BILLING); safeNavigate(ROUTES.BILLING);
} }
}, [user.role]); }, [user.role, safeNavigate]);
const handleFailedPayment = useCallback((): void => { const handleFailedPayment = useCallback((): void => {
manageCreditCard({ manageCreditCard({

View File

@@ -3,7 +3,7 @@ import './Header.styles.scss';
import Breadcrumb from 'antd/es/breadcrumb'; import Breadcrumb from 'antd/es/breadcrumb';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { Blocks, LifeBuoy } from 'lucide-react'; import { Blocks, LifeBuoy } from 'lucide-react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router';
function Header(): JSX.Element { function Header(): JSX.Element {
return ( return (

View File

@@ -5,10 +5,10 @@ import { Button, Select, Skeleton } from 'antd';
import { SelectProps } from 'antd/lib'; import { SelectProps } from 'antd/lib';
import logEvent from 'api/common/logEvent'; import logEvent from 'api/common/logEvent';
import { useAwsAccounts } from 'hooks/integration/aws/useAwsAccounts'; import { useAwsAccounts } from 'hooks/integration/aws/useAwsAccounts';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import { Check, ChevronDown } from 'lucide-react'; import { Check, ChevronDown } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom-v5-compat';
import { CloudAccount } from '../../ServicesSection/types'; import { CloudAccount } from '../../ServicesSection/types';
import AccountSettingsModal from './AccountSettingsModal'; import AccountSettingsModal from './AccountSettingsModal';
@@ -140,7 +140,7 @@ function AccountActionsRenderer({
function AccountActions(): JSX.Element { function AccountActions(): JSX.Element {
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
const navigate = useNavigate(); const { safeNavigate } = useSafeNavigate();
const { data: accounts, isLoading } = useAwsAccounts(); const { data: accounts, isLoading } = useAwsAccounts();
const initialAccount = useMemo( const initialAccount = useMemo(
@@ -162,7 +162,7 @@ function AccountActions(): JSX.Element {
setActiveAccount(initialAccount); setActiveAccount(initialAccount);
const latestUrlQuery = new URLSearchParams(window.location.search); const latestUrlQuery = new URLSearchParams(window.location.search);
latestUrlQuery.set('cloudAccountId', initialAccount.cloud_account_id); latestUrlQuery.set('cloudAccountId', initialAccount.cloud_account_id);
navigate({ search: latestUrlQuery.toString() }); safeNavigate({ search: latestUrlQuery.toString() });
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [initialAccount]); }, [initialAccount]);
@@ -216,7 +216,7 @@ function AccountActions(): JSX.Element {
if (accounts) { if (accounts) {
setActiveAccount(getAccountById(accounts, value)); setActiveAccount(getAccountById(accounts, value));
urlQuery.set('cloudAccountId', value); urlQuery.set('cloudAccountId', value);
navigate({ search: urlQuery.toString() }); safeNavigate({ search: urlQuery.toString() });
} }
}} }}
onIntegrationModalOpen={startAccountConnectionAttempt} onIntegrationModalOpen={startAccountConnectionAttempt}

View File

@@ -7,8 +7,8 @@ import {
getRegionPreviewText, getRegionPreviewText,
useAccountSettingsModal, useAccountSettingsModal,
} from 'hooks/integration/aws/useAccountSettingsModal'; } from 'hooks/integration/aws/useAccountSettingsModal';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import history from 'lib/history';
import { Dispatch, SetStateAction, useCallback } from 'react'; import { Dispatch, SetStateAction, useCallback } from 'react';
import { useQueryClient } from 'react-query'; import { useQueryClient } from 'react-query';
@@ -45,12 +45,13 @@ function AccountSettingsModal({
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
const { safeNavigate } = useSafeNavigate();
const handleRemoveIntegrationAccountSuccess = (): void => { const handleRemoveIntegrationAccountSuccess = (): void => {
queryClient.invalidateQueries([REACT_QUERY_KEY.AWS_ACCOUNTS]); queryClient.invalidateQueries([REACT_QUERY_KEY.AWS_ACCOUNTS]);
urlQuery.delete('cloudAccountId'); urlQuery.delete('cloudAccountId');
handleClose(); handleClose();
history.replace({ search: urlQuery.toString() }); safeNavigate({ search: urlQuery.toString() });
logEvent('AWS Integration: Account removed', { logEvent('AWS Integration: Account removed', {
id: account?.id, id: account?.id,

View File

@@ -1,4 +1,4 @@
import { Link } from 'react-router-dom'; import { Link } from 'react-router';
import { ServiceData } from './types'; import { ServiceData } from './types';

View File

@@ -1,8 +1,8 @@
import Spinner from 'components/Spinner'; import Spinner from 'components/Spinner';
import { useGetAccountServices } from 'hooks/integration/aws/useGetAccountServices'; import { useGetAccountServices } from 'hooks/integration/aws/useGetAccountServices';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import { useCallback, useEffect, useMemo } from 'react'; import { useCallback, useEffect, useMemo } from 'react';
import { useNavigate } from 'react-router-dom-v5-compat';
import ServiceItem from './ServiceItem'; import ServiceItem from './ServiceItem';
@@ -16,7 +16,7 @@ function ServicesList({
filter, filter,
}: ServicesListProps): JSX.Element { }: ServicesListProps): JSX.Element {
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
const navigate = useNavigate(); const { safeNavigate } = useSafeNavigate();
const { data: services = [], isLoading } = useGetAccountServices( const { data: services = [], isLoading } = useGetAccountServices(
cloudAccountId, cloudAccountId,
); );
@@ -26,9 +26,9 @@ function ServicesList({
(serviceId: string): void => { (serviceId: string): void => {
const latestUrlQuery = new URLSearchParams(window.location.search); const latestUrlQuery = new URLSearchParams(window.location.search);
latestUrlQuery.set('service', serviceId); latestUrlQuery.set('service', serviceId);
navigate({ search: latestUrlQuery.toString() }); safeNavigate({ search: latestUrlQuery.toString() });
}, },
[navigate], [safeNavigate],
); );
const filteredServices = useMemo(() => { const filteredServices = useMemo(() => {

View File

@@ -1,5 +1,5 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router';
function LinkContainer({ children, href }: LinkContainerProps): JSX.Element { function LinkContainer({ children, href }: LinkContainerProps): JSX.Element {
const isInternalLink = href.startsWith('/'); const isInternalLink = href.startsWith('/');

View File

@@ -15,7 +15,7 @@ import logEvent from 'api/common/logEvent';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import FormAlertChannels from 'container/FormAlertChannels'; import FormAlertChannels from 'container/FormAlertChannels';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { useCallback, useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@@ -86,6 +86,7 @@ function CreateAlertChannels({
const [savingState, setSavingState] = useState<boolean>(false); const [savingState, setSavingState] = useState<boolean>(false);
const [testingState, setTestingState] = useState<boolean>(false); const [testingState, setTestingState] = useState<boolean>(false);
const { notifications } = useNotifications(); const { notifications } = useNotifications();
const { safeNavigate } = useSafeNavigate();
const [type, setType] = useState<ChannelType>(preType); const [type, setType] = useState<ChannelType>(preType);
const onTypeChangeHandler = useCallback( const onTypeChangeHandler = useCallback(
@@ -143,7 +144,7 @@ function CreateAlertChannels({
message: 'Success', message: 'Success',
description: t('channel_creation_done'), description: t('channel_creation_done'),
}); });
history.replace(ROUTES.ALL_CHANNELS); safeNavigate(ROUTES.ALL_CHANNELS, { replace: true });
return { status: 'success', statusMessage: t('channel_creation_done') }; return { status: 'success', statusMessage: t('channel_creation_done') };
} }
notifications.error({ notifications.error({
@@ -163,7 +164,7 @@ function CreateAlertChannels({
} finally { } finally {
setSavingState(false); setSavingState(false);
} }
}, [prepareSlackRequest, t, notifications]); }, [prepareSlackRequest, t, notifications, safeNavigate]);
const prepareWebhookRequest = useCallback(() => { const prepareWebhookRequest = useCallback(() => {
// initial api request without auth params // initial api request without auth params
@@ -210,7 +211,7 @@ function CreateAlertChannels({
message: 'Success', message: 'Success',
description: t('channel_creation_done'), description: t('channel_creation_done'),
}); });
history.replace(ROUTES.ALL_CHANNELS); safeNavigate(ROUTES.ALL_CHANNELS, { replace: true });
return { status: 'success', statusMessage: t('channel_creation_done') }; return { status: 'success', statusMessage: t('channel_creation_done') };
} }
notifications.error({ notifications.error({
@@ -230,7 +231,7 @@ function CreateAlertChannels({
} finally { } finally {
setSavingState(false); setSavingState(false);
} }
}, [prepareWebhookRequest, t, notifications]); }, [prepareWebhookRequest, t, notifications, safeNavigate]);
const preparePagerRequest = useCallback(() => { const preparePagerRequest = useCallback(() => {
const validationError = ValidatePagerChannel(selectedConfig as PagerChannel); const validationError = ValidatePagerChannel(selectedConfig as PagerChannel);
@@ -271,7 +272,7 @@ function CreateAlertChannels({
message: 'Success', message: 'Success',
description: t('channel_creation_done'), description: t('channel_creation_done'),
}); });
history.replace(ROUTES.ALL_CHANNELS); safeNavigate(ROUTES.ALL_CHANNELS, { replace: true });
return { status: 'success', statusMessage: t('channel_creation_done') }; return { status: 'success', statusMessage: t('channel_creation_done') };
} }
notifications.error({ notifications.error({
@@ -297,7 +298,7 @@ function CreateAlertChannels({
} finally { } finally {
setSavingState(false); setSavingState(false);
} }
}, [t, notifications, preparePagerRequest]); }, [t, notifications, preparePagerRequest, safeNavigate]);
const prepareOpsgenieRequest = useCallback( const prepareOpsgenieRequest = useCallback(
() => ({ () => ({
@@ -322,7 +323,7 @@ function CreateAlertChannels({
message: 'Success', message: 'Success',
description: t('channel_creation_done'), description: t('channel_creation_done'),
}); });
history.replace(ROUTES.ALL_CHANNELS); safeNavigate(ROUTES.ALL_CHANNELS, { replace: true });
return { status: 'success', statusMessage: t('channel_creation_done') }; return { status: 'success', statusMessage: t('channel_creation_done') };
} }
notifications.error({ notifications.error({
@@ -342,7 +343,7 @@ function CreateAlertChannels({
} finally { } finally {
setSavingState(false); setSavingState(false);
} }
}, [prepareOpsgenieRequest, t, notifications]); }, [prepareOpsgenieRequest, t, notifications, safeNavigate]);
const prepareEmailRequest = useCallback( const prepareEmailRequest = useCallback(
() => ({ () => ({
@@ -365,7 +366,7 @@ function CreateAlertChannels({
message: 'Success', message: 'Success',
description: t('channel_creation_done'), description: t('channel_creation_done'),
}); });
history.replace(ROUTES.ALL_CHANNELS); safeNavigate(ROUTES.ALL_CHANNELS, { replace: true });
return { status: 'success', statusMessage: t('channel_creation_done') }; return { status: 'success', statusMessage: t('channel_creation_done') };
} }
notifications.error({ notifications.error({
@@ -385,7 +386,7 @@ function CreateAlertChannels({
} finally { } finally {
setSavingState(false); setSavingState(false);
} }
}, [prepareEmailRequest, t, notifications]); }, [prepareEmailRequest, t, notifications, safeNavigate]);
const prepareMsTeamsRequest = useCallback( const prepareMsTeamsRequest = useCallback(
() => ({ () => ({
@@ -409,7 +410,7 @@ function CreateAlertChannels({
message: 'Success', message: 'Success',
description: t('channel_creation_done'), description: t('channel_creation_done'),
}); });
history.replace(ROUTES.ALL_CHANNELS); safeNavigate(ROUTES.ALL_CHANNELS, { replace: true });
return { status: 'success', statusMessage: t('channel_creation_done') }; return { status: 'success', statusMessage: t('channel_creation_done') };
} }
notifications.error({ notifications.error({
@@ -429,7 +430,7 @@ function CreateAlertChannels({
} finally { } finally {
setSavingState(false); setSavingState(false);
} }
}, [prepareMsTeamsRequest, t, notifications]); }, [prepareMsTeamsRequest, t, notifications, safeNavigate]);
const onSaveHandler = useCallback( const onSaveHandler = useCallback(
async (value: ChannelType) => { async (value: ChannelType) => {

View File

@@ -4,9 +4,9 @@ import { ENTITY_VERSION_V4 } from 'constants/app';
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
import FormAlertRules, { AlertDetectionTypes } from 'container/FormAlertRules'; import FormAlertRules, { AlertDetectionTypes } from 'container/FormAlertRules';
import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam'; import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { AlertTypes } from 'types/api/alerts/alertTypes'; import { AlertTypes } from 'types/api/alerts/alertTypes';
import { AlertDef } from 'types/api/alerts/def'; import { AlertDef } from 'types/api/alerts/def';
@@ -24,6 +24,7 @@ function CreateRules(): JSX.Element {
const [initValues, setInitValues] = useState<AlertDef | null>(null); const [initValues, setInitValues] = useState<AlertDef | null>(null);
const location = useLocation(); const location = useLocation();
const { safeNavigate } = useSafeNavigate();
const queryParams = new URLSearchParams(location.search); const queryParams = new URLSearchParams(location.search);
const alertTypeFromURL = queryParams.get(QueryParams.ruleType); const alertTypeFromURL = queryParams.get(QueryParams.ruleType);
const version = queryParams.get('version'); const version = queryParams.get('version');
@@ -96,7 +97,7 @@ function CreateRules(): JSX.Element {
} }
const generatedUrl = `${location.pathname}?${queryParams.toString()}`; const generatedUrl = `${location.pathname}?${queryParams.toString()}`;
history.replace(generatedUrl); safeNavigate(generatedUrl, { replace: true });
}; };
useEffect(() => { useEffect(() => {

View File

@@ -25,10 +25,10 @@ import {
} from 'container/CreateAlertChannels/config'; } from 'container/CreateAlertChannels/config';
import FormAlertChannels from 'container/FormAlertChannels'; import FormAlertChannels from 'container/FormAlertChannels';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { useCallback, useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router';
function EditAlertChannels({ function EditAlertChannels({
initialValue, initialValue,
@@ -52,7 +52,9 @@ function EditAlertChannels({
const [savingState, setSavingState] = useState<boolean>(false); const [savingState, setSavingState] = useState<boolean>(false);
const [testingState, setTestingState] = useState<boolean>(false); const [testingState, setTestingState] = useState<boolean>(false);
const { notifications } = useNotifications(); const { notifications } = useNotifications();
const { id } = useParams<{ id: string }>(); const { safeNavigate } = useSafeNavigate();
// Temp: Hard type casting for string | undefined
const { id } = useParams() as { id: string };
const [type, setType] = useState<ChannelType>( const [type, setType] = useState<ChannelType>(
initialValue?.type ? (initialValue.type as ChannelType) : ChannelType.Slack, initialValue?.type ? (initialValue.type as ChannelType) : ChannelType.Slack,
@@ -101,7 +103,7 @@ function EditAlertChannels({
description: t('channel_edit_done'), description: t('channel_edit_done'),
}); });
history.replace(ROUTES.ALL_CHANNELS); safeNavigate(ROUTES.ALL_CHANNELS, { replace: true });
return { status: 'success', statusMessage: t('channel_edit_done') }; return { status: 'success', statusMessage: t('channel_edit_done') };
} }
notifications.error({ notifications.error({
@@ -113,7 +115,7 @@ function EditAlertChannels({
status: 'failed', status: 'failed',
statusMessage: response.error || t('channel_edit_failed'), statusMessage: response.error || t('channel_edit_failed'),
}; };
}, [prepareSlackRequest, t, notifications, selectedConfig]); }, [prepareSlackRequest, t, notifications, selectedConfig, safeNavigate]);
const prepareWebhookRequest = useCallback(() => { const prepareWebhookRequest = useCallback(() => {
const { name, username, password } = selectedConfig; const { name, username, password } = selectedConfig;
@@ -158,7 +160,7 @@ function EditAlertChannels({
description: t('channel_edit_done'), description: t('channel_edit_done'),
}); });
history.replace(ROUTES.ALL_CHANNELS); safeNavigate(ROUTES.ALL_CHANNELS, { replace: true });
return { status: 'success', statusMessage: t('channel_edit_done') }; return { status: 'success', statusMessage: t('channel_edit_done') };
} }
showError(response.error || t('channel_edit_failed')); showError(response.error || t('channel_edit_failed'));
@@ -168,7 +170,7 @@ function EditAlertChannels({
status: 'failed', status: 'failed',
statusMessage: response.error || t('channel_edit_failed'), statusMessage: response.error || t('channel_edit_failed'),
}; };
}, [prepareWebhookRequest, t, notifications, selectedConfig]); }, [prepareWebhookRequest, t, notifications, selectedConfig, safeNavigate]);
const prepareEmailRequest = useCallback( const prepareEmailRequest = useCallback(
() => ({ () => ({
@@ -191,7 +193,7 @@ function EditAlertChannels({
message: 'Success', message: 'Success',
description: t('channel_edit_done'), description: t('channel_edit_done'),
}); });
history.replace(ROUTES.ALL_CHANNELS); safeNavigate(ROUTES.ALL_CHANNELS, { replace: true });
return { status: 'success', statusMessage: t('channel_edit_done') }; return { status: 'success', statusMessage: t('channel_edit_done') };
} }
notifications.error({ notifications.error({
@@ -204,7 +206,7 @@ function EditAlertChannels({
status: 'failed', status: 'failed',
statusMessage: response.error || t('channel_edit_failed'), statusMessage: response.error || t('channel_edit_failed'),
}; };
}, [prepareEmailRequest, t, notifications]); }, [prepareEmailRequest, t, notifications, safeNavigate]);
const preparePagerRequest = useCallback( const preparePagerRequest = useCallback(
() => ({ () => ({
@@ -245,7 +247,7 @@ function EditAlertChannels({
description: t('channel_edit_done'), description: t('channel_edit_done'),
}); });
history.replace(ROUTES.ALL_CHANNELS); safeNavigate(ROUTES.ALL_CHANNELS, { replace: true });
return { status: 'success', statusMessage: t('channel_edit_done') }; return { status: 'success', statusMessage: t('channel_edit_done') };
} }
notifications.error({ notifications.error({
@@ -258,7 +260,7 @@ function EditAlertChannels({
status: 'failed', status: 'failed',
statusMessage: response.error || t('channel_edit_failed'), statusMessage: response.error || t('channel_edit_failed'),
}; };
}, [preparePagerRequest, notifications, selectedConfig, t]); }, [preparePagerRequest, notifications, selectedConfig, t, safeNavigate]);
const prepareOpsgenieRequest = useCallback( const prepareOpsgenieRequest = useCallback(
() => ({ () => ({
@@ -293,7 +295,7 @@ function EditAlertChannels({
description: t('channel_edit_done'), description: t('channel_edit_done'),
}); });
history.replace(ROUTES.ALL_CHANNELS); safeNavigate(ROUTES.ALL_CHANNELS, { replace: true });
return { status: 'success', statusMessage: t('channel_edit_done') }; return { status: 'success', statusMessage: t('channel_edit_done') };
} }
notifications.error({ notifications.error({
@@ -306,7 +308,7 @@ function EditAlertChannels({
status: 'failed', status: 'failed',
statusMessage: response.error || t('channel_edit_failed'), statusMessage: response.error || t('channel_edit_failed'),
}; };
}, [prepareOpsgenieRequest, t, notifications, selectedConfig]); }, [prepareOpsgenieRequest, t, notifications, selectedConfig, safeNavigate]);
const prepareMsTeamsRequest = useCallback( const prepareMsTeamsRequest = useCallback(
() => ({ () => ({
@@ -340,7 +342,7 @@ function EditAlertChannels({
description: t('channel_edit_done'), description: t('channel_edit_done'),
}); });
history.replace(ROUTES.ALL_CHANNELS); safeNavigate(ROUTES.ALL_CHANNELS, { replace: true });
return { status: 'success', statusMessage: t('channel_edit_done') }; return { status: 'success', statusMessage: t('channel_edit_done') };
} }
notifications.error({ notifications.error({
@@ -353,7 +355,7 @@ function EditAlertChannels({
status: 'failed', status: 'failed',
statusMessage: response.error || t('channel_edit_failed'), statusMessage: response.error || t('channel_edit_failed'),
}; };
}, [prepareMsTeamsRequest, t, notifications, selectedConfig]); }, [prepareMsTeamsRequest, t, notifications, selectedConfig, safeNavigate]);
const onSaveHandler = useCallback( const onSaveHandler = useCallback(
async (value: ChannelType) => { async (value: ChannelType) => {

View File

@@ -8,15 +8,15 @@ import { ResizeTable } from 'components/ResizeTable';
import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats'; import { DATE_TIME_FORMATS } from 'constants/dateTimeFormats';
import { getNanoSeconds } from 'container/AllError/utils'; import { getNanoSeconds } from 'container/AllError/utils';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import createQueryParams from 'lib/createQueryParams'; import createQueryParams from 'lib/createQueryParams';
import history from 'lib/history';
import { isUndefined } from 'lodash-es'; import { isUndefined } from 'lodash-es';
import { urlKey } from 'pages/ErrorDetails/utils'; import { urlKey } from 'pages/ErrorDetails/utils';
import { useTimezone } from 'providers/Timezone'; import { useTimezone } from 'providers/Timezone';
import { useEffect, useMemo, useRef, useState } from 'react'; import { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useQuery } from 'react-query'; import { useQuery } from 'react-query';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { PayloadProps as GetByErrorTypeAndServicePayload } from 'types/api/errors/getByErrorTypeAndService'; import { PayloadProps as GetByErrorTypeAndServicePayload } from 'types/api/errors/getByErrorTypeAndService';
import { keyToExclude } from './config'; import { keyToExclude } from './config';
@@ -77,6 +77,7 @@ function ErrorDetails(props: ErrorDetailsProps): JSX.Element {
); );
const { notifications } = useNotifications(); const { notifications } = useNotifications();
const { safeNavigate } = useSafeNavigate();
const onClickErrorIdHandler = async ( const onClickErrorIdHandler = async (
id: string, id: string,
@@ -96,7 +97,9 @@ function ErrorDetails(props: ErrorDetailsProps): JSX.Element {
errorId: id, errorId: id,
}; };
history.replace(`${pathname}?${createQueryParams(queryParams)}`); safeNavigate(`${pathname}?${createQueryParams(queryParams)}`, {
replace: true,
});
} catch (error) { } catch (error) {
notifications.error({ notifications.error({
message: t('something_went_wrong'), message: t('something_went_wrong'),
@@ -118,7 +121,7 @@ function ErrorDetails(props: ErrorDetailsProps): JSX.Element {
traceId: errorDetail.traceID, traceId: errorDetail.traceID,
exceptionId: errorDetail?.errorId, exceptionId: errorDetail?.errorId,
}); });
history.push(`/trace/${errorDetail.traceID}?spanId=${errorDetail.spanID}`); safeNavigate(`/trace/${errorDetail.traceID}?spanId=${errorDetail.spanID}`);
}; };
const logEventCalledRef = useRef(false); const logEventCalledRef = useRef(false);

View File

@@ -39,6 +39,7 @@ import { useIsDarkMode } from 'hooks/useDarkMode';
import useErrorNotification from 'hooks/useErrorNotification'; import useErrorNotification from 'hooks/useErrorNotification';
import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange'; import { useHandleExplorerTabChange } from 'hooks/useHandleExplorerTabChange';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { mapCompositeQueryFromQuery } from 'lib/newQueryBuilder/queryBuilderMappers/mapCompositeQueryFromQuery'; import { mapCompositeQueryFromQuery } from 'lib/newQueryBuilder/queryBuilderMappers/mapCompositeQueryFromQuery';
import { cloneDeep, isEqual, omit } from 'lodash-es'; import { cloneDeep, isEqual, omit } from 'lodash-es';
import { import {
@@ -60,7 +61,6 @@ import {
useRef, useRef,
useState, useState,
} from 'react'; } from 'react';
import { useHistory } from 'react-router-dom';
import { Dashboard } from 'types/api/dashboard/getAll'; import { Dashboard } from 'types/api/dashboard/getAll';
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { Query } from 'types/api/queryBuilder/queryBuilderData';
@@ -96,7 +96,7 @@ function ExplorerOptions({
const [newViewName, setNewViewName] = useState<string>(''); const [newViewName, setNewViewName] = useState<string>('');
const [color, setColor] = useState(Color.BG_SIENNA_500); const [color, setColor] = useState(Color.BG_SIENNA_500);
const { notifications } = useNotifications(); const { notifications } = useNotifications();
const history = useHistory(); const { safeNavigate } = useSafeNavigate();
const ref = useRef<RefSelectProps>(null); const ref = useRef<RefSelectProps>(null);
const isDarkMode = useIsDarkMode(); const isDarkMode = useIsDarkMode();
const isLogsExplorer = sourcepage === DataSource.LOGS; const isLogsExplorer = sourcepage === DataSource.LOGS;
@@ -181,13 +181,13 @@ function ExplorerOptions({
const stringifiedQuery = handleConditionalQueryModification(); const stringifiedQuery = handleConditionalQueryModification();
history.push( safeNavigate(
`${ROUTES.ALERTS_NEW}?${QueryParams.compositeQuery}=${encodeURIComponent( `${ROUTES.ALERTS_NEW}?${QueryParams.compositeQuery}=${encodeURIComponent(
stringifiedQuery, stringifiedQuery,
)}`, )}`,
); );
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [handleConditionalQueryModification, history]); }, [handleConditionalQueryModification, safeNavigate]);
const onCancel = (value: boolean) => (): void => { const onCancel = (value: boolean) => (): void => {
onModalToggle(value); onModalToggle(value);
@@ -461,7 +461,7 @@ function ExplorerOptions({
: defaultLogsSelectedColumns, : defaultLogsSelectedColumns,
}); });
history.replace(DATASOURCE_VS_ROUTES[sourcepage]); safeNavigate(DATASOURCE_VS_ROUTES[sourcepage], { replace: true });
}; };
const isQueryUpdated = isStagedQueryUpdated( const isQueryUpdated = isStagedQueryUpdated(

View File

@@ -9,7 +9,7 @@ import {
SlackChannel, SlackChannel,
WebhookChannel, WebhookChannel,
} from 'container/CreateAlertChannels/config'; } from 'container/CreateAlertChannels/config';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { Dispatch, ReactElement, SetStateAction } from 'react'; import { Dispatch, ReactElement, SetStateAction } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@@ -35,6 +35,7 @@ function FormAlertChannels({
editing = false, editing = false,
}: FormAlertChannelsProps): JSX.Element { }: FormAlertChannelsProps): JSX.Element {
const { t } = useTranslation('channels'); const { t } = useTranslation('channels');
const { safeNavigate } = useSafeNavigate();
const renderSettings = (): ReactElement | null => { const renderSettings = (): ReactElement | null => {
switch (type) { switch (type) {
@@ -147,7 +148,7 @@ function FormAlertChannels({
</Button> </Button>
<Button <Button
onClick={(): void => { onClick={(): void => {
history.replace(ROUTES.SETTINGS); safeNavigate(ROUTES.SETTINGS);
}} }}
> >
{t('button_return')} {t('button_return')}

View File

@@ -18,10 +18,10 @@ import {
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange'; import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
import { useIsDarkMode } from 'hooks/useDarkMode'; import { useIsDarkMode } from 'hooks/useDarkMode';
import { useResizeObserver } from 'hooks/useDimensions'; import { useResizeObserver } from 'hooks/useDimensions';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import GetMinMax from 'lib/getMinMax'; import GetMinMax from 'lib/getMinMax';
import getTimeString from 'lib/getTimeString'; import getTimeString from 'lib/getTimeString';
import history from 'lib/history';
import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions'; import { getUPlotChartOptions } from 'lib/uPlotLib/getUplotChartOptions';
import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData'; import { getUPlotChartData } from 'lib/uPlotLib/utils/getUplotChartData';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
@@ -29,7 +29,7 @@ import { useTimezone } from 'providers/Timezone';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { UpdateTimeInterval } from 'store/actions'; import { UpdateTimeInterval } from 'store/actions';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { AlertDef } from 'types/api/alerts/def'; import { AlertDef } from 'types/api/alerts/def';
@@ -85,6 +85,7 @@ function ChartPreview({
>((state) => state.globalTime); >((state) => state.globalTime);
const { featureFlags } = useAppContext(); const { featureFlags } = useAppContext();
const { safeNavigate } = useSafeNavigate();
const handleBackNavigation = (): void => { const handleBackNavigation = (): void => {
const searchParams = new URLSearchParams(window.location.search); const searchParams = new URLSearchParams(window.location.search);
@@ -200,9 +201,9 @@ function ChartPreview({
urlQuery.set(QueryParams.startTime, minTime.toString()); urlQuery.set(QueryParams.startTime, minTime.toString());
urlQuery.set(QueryParams.endTime, maxTime.toString()); urlQuery.set(QueryParams.endTime, maxTime.toString());
const generatedUrl = `${location.pathname}?${urlQuery.toString()}`; const generatedUrl = `${location.pathname}?${urlQuery.toString()}`;
history.push(generatedUrl); safeNavigate(generatedUrl);
}, },
[dispatch, location.pathname, urlQuery], [dispatch, location.pathname, urlQuery, safeNavigate],
); );
const { timezone } = useTimezone(); const { timezone } = useTimezone();

View File

@@ -29,7 +29,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useQueryClient } from 'react-query'; import { useQueryClient } from 'react-query';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { AlertTypes } from 'types/api/alerts/alertTypes'; import { AlertTypes } from 'types/api/alerts/alertTypes';
import { import {

View File

@@ -2,15 +2,16 @@
/* eslint-disable jsx-a11y/click-events-have-key-events */ /* eslint-disable jsx-a11y/click-events-have-key-events */
import './FullScreenHeader.styles.scss'; import './FullScreenHeader.styles.scss';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
export default function FullScreenHeader({ export default function FullScreenHeader({
overrideRoute, overrideRoute,
}: { }: {
overrideRoute?: string; overrideRoute?: string;
}): React.ReactElement { }): React.ReactElement {
const { safeNavigate } = useSafeNavigate();
const handleLogoClick = (): void => { const handleLogoClick = (): void => {
history.push(overrideRoute || '/'); safeNavigate(overrideRoute || '/');
}; };
return ( return (
<div className="full-screen-header-container"> <div className="full-screen-header-container">

View File

@@ -28,7 +28,7 @@ import GetMinMax from 'lib/getMinMax';
import { useDashboard } from 'providers/Dashboard/Dashboard'; import { useDashboard } from 'providers/Dashboard/Dashboard';
import { useCallback, useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { UpdateTimeInterval } from 'store/actions'; import { UpdateTimeInterval } from 'store/actions';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';

View File

@@ -25,7 +25,7 @@ import {
useRef, useRef,
useState, useState,
} from 'react'; } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { Dashboard } from 'types/api/dashboard/getAll'; import { Dashboard } from 'types/api/dashboard/getAll';
import { DataSource } from 'types/common/queryBuilder'; import { DataSource } from 'types/common/queryBuilder';
import { v4 } from 'uuid'; import { v4 } from 'uuid';

View File

@@ -34,7 +34,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { FullScreen, FullScreenHandle } from 'react-full-screen'; import { FullScreen, FullScreenHandle } from 'react-full-screen';
import { ItemCallback, Layout } from 'react-grid-layout'; import { ItemCallback, Layout } from 'react-grid-layout';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { UpdateTimeInterval } from 'store/actions'; import { UpdateTimeInterval } from 'store/actions';
import { Dashboard, Widgets } from 'types/api/dashboard/getAll'; import { Dashboard, Widgets } from 'types/api/dashboard/getAll';
import { ROLES, USER_ROLES } from 'types/roles'; import { ROLES, USER_ROLES } from 'types/roles';

View File

@@ -3,7 +3,7 @@ import { getYAxisFormattedValue } from 'components/Graph/yAxisConfig';
import ValueGraph from 'components/ValueGraph'; import ValueGraph from 'components/ValueGraph';
import { generateGridTitle } from 'container/GridPanelSwitch/utils'; import { generateGridTitle } from 'container/GridPanelSwitch/utils';
import { memo, useMemo } from 'react'; import { memo, useMemo } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { TitleContainer, ValueContainer } from './styles'; import { TitleContainer, ValueContainer } from './styles';
import { GridValueComponentProps } from './types'; import { GridValueComponentProps } from './types';

View File

@@ -3,14 +3,14 @@ import getAll from 'api/alerts/getAll';
import logEvent from 'api/common/logEvent'; import logEvent from 'api/common/logEvent';
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { mapQueryDataFromApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataFromApi'; import { mapQueryDataFromApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataFromApi';
import { ArrowRight, ArrowUpRight, Plus } from 'lucide-react'; import { ArrowRight, ArrowUpRight, Plus } from 'lucide-react';
import Card from 'periscope/components/Card/Card'; import Card from 'periscope/components/Card/Card';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useQuery } from 'react-query'; import { useQuery } from 'react-query';
import { Link, useLocation } from 'react-router-dom'; import { Link, useLocation } from 'react-router';
import { GettableAlert } from 'types/api/alerts/get'; import { GettableAlert } from 'types/api/alerts/get';
import { USER_ROLES } from 'types/roles'; import { USER_ROLES } from 'types/roles';
@@ -28,6 +28,7 @@ export default function AlertRules({
const location = useLocation(); const location = useLocation();
const params = new URLSearchParams(location.search); const params = new URLSearchParams(location.search);
const { safeNavigate } = useSafeNavigate();
// Fetch Alerts // Fetch Alerts
const { data: alerts, isError, isLoading } = useQuery('allAlerts', { const { data: alerts, isError, isLoading } = useQuery('allAlerts', {
@@ -131,7 +132,7 @@ export default function AlertRules({
params.set(QueryParams.ruleId, record.id.toString()); params.set(QueryParams.ruleId, record.id.toString());
history.push(`${ROUTES.ALERT_OVERVIEW}?${params.toString()}`); safeNavigate(`${ROUTES.ALERT_OVERVIEW}?${params.toString()}`);
}; };
const renderAlertRules = (): JSX.Element => ( const renderAlertRules = (): JSX.Element => (

View File

@@ -7,7 +7,7 @@ import { ArrowRight, ArrowUpRight, Plus } from 'lucide-react';
import Card from 'periscope/components/Card/Card'; import Card from 'periscope/components/Card/Card';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router';
import { Dashboard } from 'types/api/dashboard/getAll'; import { Dashboard } from 'types/api/dashboard/getAll';
import { USER_ROLES } from 'types/roles'; import { USER_ROLES } from 'types/roles';

View File

@@ -3,7 +3,7 @@ import { Button, Skeleton, Tag, Typography } from 'antd';
import logEvent from 'api/common/logEvent'; import logEvent from 'api/common/logEvent';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { useGetDeploymentsData } from 'hooks/CustomDomain/useGetDeploymentsData'; import { useGetDeploymentsData } from 'hooks/CustomDomain/useGetDeploymentsData';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { Globe, Link2 } from 'lucide-react'; import { Globe, Link2 } from 'lucide-react';
import Card from 'periscope/components/Card/Card'; import Card from 'periscope/components/Card/Card';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
@@ -20,6 +20,7 @@ function DataSourceInfo({
isLoading: boolean; isLoading: boolean;
}): JSX.Element { }): JSX.Element {
const { activeLicenseV3 } = useAppContext(); const { activeLicenseV3 } = useAppContext();
const { safeNavigate } = useSafeNavigate();
const notSendingData = !dataSentToSigNoz; const notSendingData = !dataSentToSigNoz;
@@ -91,7 +92,7 @@ function DataSourceInfo({
activeLicenseV3 && activeLicenseV3 &&
activeLicenseV3.platform === LicensePlatform.CLOUD activeLicenseV3.platform === LicensePlatform.CLOUD
) { ) {
history.push(ROUTES.GET_STARTED_WITH_CLOUD); safeNavigate(ROUTES.GET_STARTED_WITH_CLOUD);
} else { } else {
window?.open( window?.open(
DOCS_LINKS.ADD_DATA_SOURCE, DOCS_LINKS.ADD_DATA_SOURCE,
@@ -108,7 +109,7 @@ function DataSourceInfo({
activeLicenseV3 && activeLicenseV3 &&
activeLicenseV3.platform === LicensePlatform.CLOUD activeLicenseV3.platform === LicensePlatform.CLOUD
) { ) {
history.push(ROUTES.GET_STARTED_WITH_CLOUD); safeNavigate(ROUTES.GET_STARTED_WITH_CLOUD);
} else { } else {
window?.open( window?.open(
DOCS_LINKS.ADD_DATA_SOURCE, DOCS_LINKS.ADD_DATA_SOURCE,

View File

@@ -17,7 +17,7 @@ import { getHostListsQuery } from 'container/InfraMonitoringHosts/utils';
import { useGetHostList } from 'hooks/infraMonitoring/useGetHostList'; import { useGetHostList } from 'hooks/infraMonitoring/useGetHostList';
import { useGetK8sPodsList } from 'hooks/infraMonitoring/useGetK8sPodsList'; import { useGetK8sPodsList } from 'hooks/infraMonitoring/useGetK8sPodsList';
import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange'; import { useGetQueryRange } from 'hooks/queryBuilder/useGetQueryRange';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import cloneDeep from 'lodash-es/cloneDeep'; import cloneDeep from 'lodash-es/cloneDeep';
import { CompassIcon, DotIcon, HomeIcon, Plus, Wrench } from 'lucide-react'; import { CompassIcon, DotIcon, HomeIcon, Plus, Wrench } from 'lucide-react';
import { AnimatePresence } from 'motion/react'; import { AnimatePresence } from 'motion/react';
@@ -45,6 +45,7 @@ const homeInterval = 30 * 60 * 1000;
// eslint-disable-next-line sonarjs/cognitive-complexity // eslint-disable-next-line sonarjs/cognitive-complexity
export default function Home(): JSX.Element { export default function Home(): JSX.Element {
const { user } = useAppContext(); const { user } = useAppContext();
const { safeNavigate } = useSafeNavigate();
const [startTime, setStartTime] = useState<number | null>(null); const [startTime, setStartTime] = useState<number | null>(null);
const [endTime, setEndTime] = useState<number | null>(null); const [endTime, setEndTime] = useState<number | null>(null);
@@ -382,14 +383,14 @@ export default function Home(): JSX.Element {
logEvent('Homepage: Ingestion Active Explore clicked', { logEvent('Homepage: Ingestion Active Explore clicked', {
source: 'Logs', source: 'Logs',
}); });
history.push(ROUTES.LOGS_EXPLORER); safeNavigate(ROUTES.LOGS_EXPLORER);
}} }}
onKeyDown={(e): void => { onKeyDown={(e): void => {
if (e.key === 'Enter') { if (e.key === 'Enter') {
logEvent('Homepage: Ingestion Active Explore clicked', { logEvent('Homepage: Ingestion Active Explore clicked', {
source: 'Logs', source: 'Logs',
}); });
history.push(ROUTES.LOGS_EXPLORER); safeNavigate(ROUTES.LOGS_EXPLORER);
} }
}} }}
> >
@@ -423,14 +424,14 @@ export default function Home(): JSX.Element {
logEvent('Homepage: Ingestion Active Explore clicked', { logEvent('Homepage: Ingestion Active Explore clicked', {
source: 'Traces', source: 'Traces',
}); });
history.push(ROUTES.TRACES_EXPLORER); safeNavigate(ROUTES.TRACES_EXPLORER);
}} }}
onKeyDown={(e): void => { onKeyDown={(e): void => {
if (e.key === 'Enter') { if (e.key === 'Enter') {
logEvent('Homepage: Ingestion Active Explore clicked', { logEvent('Homepage: Ingestion Active Explore clicked', {
source: 'Traces', source: 'Traces',
}); });
history.push(ROUTES.TRACES_EXPLORER); safeNavigate(ROUTES.TRACES_EXPLORER);
} }
}} }}
> >
@@ -464,14 +465,14 @@ export default function Home(): JSX.Element {
logEvent('Homepage: Ingestion Active Explore clicked', { logEvent('Homepage: Ingestion Active Explore clicked', {
source: 'Metrics', source: 'Metrics',
}); });
history.push(ROUTES.INFRASTRUCTURE_MONITORING_HOSTS); safeNavigate(ROUTES.INFRASTRUCTURE_MONITORING_HOSTS);
}} }}
onKeyDown={(e): void => { onKeyDown={(e): void => {
if (e.key === 'Enter') { if (e.key === 'Enter') {
logEvent('Homepage: Ingestion Active Explore clicked', { logEvent('Homepage: Ingestion Active Explore clicked', {
source: 'Metrics', source: 'Metrics',
}); });
history.push(ROUTES.INFRASTRUCTURE_MONITORING_HOSTS); safeNavigate(ROUTES.INFRASTRUCTURE_MONITORING_HOSTS);
} }
}} }}
> >
@@ -518,7 +519,7 @@ export default function Home(): JSX.Element {
logEvent('Homepage: Explore clicked', { logEvent('Homepage: Explore clicked', {
source: 'Logs', source: 'Logs',
}); });
history.push(ROUTES.LOGS_EXPLORER); safeNavigate(ROUTES.LOGS_EXPLORER);
}} }}
> >
Open Logs Explorer Open Logs Explorer
@@ -532,7 +533,7 @@ export default function Home(): JSX.Element {
logEvent('Homepage: Explore clicked', { logEvent('Homepage: Explore clicked', {
source: 'Traces', source: 'Traces',
}); });
history.push(ROUTES.TRACES_EXPLORER); safeNavigate(ROUTES.TRACES_EXPLORER);
}} }}
> >
Open Traces Explorer Open Traces Explorer
@@ -573,7 +574,7 @@ export default function Home(): JSX.Element {
logEvent('Homepage: Explore clicked', { logEvent('Homepage: Explore clicked', {
source: 'Dashboards', source: 'Dashboards',
}); });
history.push(ROUTES.ALL_DASHBOARD); safeNavigate(ROUTES.ALL_DASHBOARD);
}} }}
> >
Create dashboard Create dashboard
@@ -615,7 +616,7 @@ export default function Home(): JSX.Element {
logEvent('Homepage: Explore clicked', { logEvent('Homepage: Explore clicked', {
source: 'Alerts', source: 'Alerts',
}); });
history.push(ROUTES.ALERTS_NEW); safeNavigate(ROUTES.ALERTS_NEW);
}} }}
> >
Create an alert Create an alert

View File

@@ -4,7 +4,7 @@ import './HomeChecklist.styles.scss';
import { Button } from 'antd'; import { Button } from 'antd';
import logEvent from 'api/common/logEvent'; import logEvent from 'api/common/logEvent';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { ArrowRight, ArrowRightToLine, BookOpenText } from 'lucide-react'; import { ArrowRight, ArrowRightToLine, BookOpenText } from 'lucide-react';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
@@ -41,6 +41,7 @@ function HomeChecklist({
const [whatsNextChecklistItems, setWhatsNextChecklistItems] = useState< const [whatsNextChecklistItems, setWhatsNextChecklistItems] = useState<
ChecklistItem[] ChecklistItem[]
>([]); >([]);
const { safeNavigate } = useSafeNavigate();
useEffect(() => { useEffect(() => {
setCompletedChecklistItems(checklistItems.filter((item) => item.completed)); setCompletedChecklistItems(checklistItems.filter((item) => item.completed));
@@ -92,12 +93,12 @@ function HomeChecklist({
}); });
if (item.toRoute !== ROUTES.GET_STARTED_WITH_CLOUD) { if (item.toRoute !== ROUTES.GET_STARTED_WITH_CLOUD) {
history.push(item.toRoute || ''); safeNavigate(item.toRoute || '');
} else if ( } else if (
activeLicenseV3 && activeLicenseV3 &&
activeLicenseV3.platform === LicensePlatform.CLOUD activeLicenseV3.platform === LicensePlatform.CLOUD
) { ) {
history.push(item.toRoute || ''); safeNavigate(item.toRoute || '');
} else { } else {
window?.open( window?.open(
item.docsLink || '', item.docsLink || '',

View File

@@ -14,7 +14,7 @@ import { SOURCEPAGE_VS_ROUTES } from 'pages/SaveView/constants';
import Card from 'periscope/components/Card/Card'; import Card from 'periscope/components/Card/Card';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router';
import { ViewProps } from 'types/api/saveViews/types'; import { ViewProps } from 'types/api/saveViews/types';
import { DataSource } from 'types/common/queryBuilder'; import { DataSource } from 'types/common/queryBuilder';
import { USER_ROLES } from 'types/roles'; import { USER_ROLES } from 'types/roles';

View File

@@ -11,7 +11,6 @@ import useGetTopLevelOperations from 'hooks/useGetTopLevelOperations';
import useResourceAttribute from 'hooks/useResourceAttribute'; import useResourceAttribute from 'hooks/useResourceAttribute';
import { convertRawQueriesToTraceSelectedTags } from 'hooks/useResourceAttribute/utils'; import { convertRawQueriesToTraceSelectedTags } from 'hooks/useResourceAttribute/utils';
import { useSafeNavigate } from 'hooks/useSafeNavigate'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import history from 'lib/history';
import { ArrowRight, ArrowUpRight } from 'lucide-react'; import { ArrowRight, ArrowUpRight } from 'lucide-react';
import Card from 'periscope/components/Card/Card'; import Card from 'periscope/components/Card/Card';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
@@ -19,7 +18,7 @@ import { IUser } from 'providers/App/types';
import { memo, useCallback, useEffect, useMemo, useState } from 'react'; import { memo, useCallback, useEffect, useMemo, useState } from 'react';
import { QueryKey } from 'react-query'; import { QueryKey } from 'react-query';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { Link } from 'react-router-dom'; import { Link } from 'react-router';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { import {
LicensePlatform, LicensePlatform,
@@ -29,6 +28,7 @@ import { ServicesList } from 'types/api/metrics/getService';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { Tags } from 'types/reducer/trace'; import { Tags } from 'types/reducer/trace';
import { USER_ROLES } from 'types/roles'; import { USER_ROLES } from 'types/roles';
import { safeNavigateNoSameURLMemo } from 'utils/navigate';
import { DOCS_LINKS } from '../constants'; import { DOCS_LINKS } from '../constants';
import { columns, TIME_PICKER_OPTIONS } from './constants'; import { columns, TIME_PICKER_OPTIONS } from './constants';
@@ -72,7 +72,7 @@ const EmptyState = memo(
activeLicenseV3 && activeLicenseV3 &&
activeLicenseV3.platform === LicensePlatform.CLOUD activeLicenseV3.platform === LicensePlatform.CLOUD
) { ) {
history.push(ROUTES.GET_STARTED_WITH_CLOUD); safeNavigateNoSameURLMemo(ROUTES.GET_STARTED_WITH_CLOUD);
} else { } else {
window?.open( window?.open(
DOCS_LINKS.ADD_DATA_SOURCE, DOCS_LINKS.ADD_DATA_SOURCE,

View File

@@ -3,13 +3,12 @@ import logEvent from 'api/common/logEvent';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { useQueryService } from 'hooks/useQueryService'; import { useQueryService } from 'hooks/useQueryService';
import { useSafeNavigate } from 'hooks/useSafeNavigate'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import history from 'lib/history';
import { ArrowRight, ArrowUpRight } from 'lucide-react'; import { ArrowRight, ArrowUpRight } from 'lucide-react';
import Card from 'periscope/components/Card/Card'; import Card from 'periscope/components/Card/Card';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { Link } from 'react-router-dom'; import { Link } from 'react-router';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { LicensePlatform } from 'types/api/licensesV3/getActive'; import { LicensePlatform } from 'types/api/licensesV3/getActive';
import { ServicesList } from 'types/api/metrics/getService'; import { ServicesList } from 'types/api/metrics/getService';
@@ -127,7 +126,7 @@ export default function ServiceTraces({
activeLicenseV3 && activeLicenseV3 &&
activeLicenseV3.platform === LicensePlatform.CLOUD activeLicenseV3.platform === LicensePlatform.CLOUD
) { ) {
history.push(ROUTES.GET_STARTED_WITH_CLOUD); safeNavigate(ROUTES.GET_STARTED_WITH_CLOUD);
} else { } else {
window?.open( window?.open(
DOCS_LINKS.ADD_DATA_SOURCE, DOCS_LINKS.ADD_DATA_SOURCE,
@@ -160,7 +159,7 @@ export default function ServiceTraces({
</div> </div>
</div> </div>
), ),
[user?.role, activeLicenseV3], [user?.role, activeLicenseV3, safeNavigate],
); );
const renderDashboardsList = useCallback( const renderDashboardsList = useCallback(

View File

@@ -5,7 +5,7 @@ import { Button, Divider, Typography } from 'antd';
import logEvent from 'api/common/logEvent'; import logEvent from 'api/common/logEvent';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import useComponentPermission from 'hooks/useComponentPermission'; import useComponentPermission from 'hooks/useComponentPermission';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
import { DataSource } from 'types/common/queryBuilder'; import { DataSource } from 'types/common/queryBuilder';
@@ -33,13 +33,14 @@ export function AlertsEmptyState(): JSX.Element {
['add_new_alert', 'action'], ['add_new_alert', 'action'],
user.role, user.role,
); );
const { safeNavigate } = useSafeNavigate();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const onClickNewAlertHandler = useCallback(() => { const onClickNewAlertHandler = useCallback(() => {
setLoading(false); setLoading(false);
history.push(ROUTES.ALERTS_NEW); safeNavigate(ROUTES.ALERTS_NEW);
}, []); }, [safeNavigate]);
return ( return (
<div className="alert-list-container"> <div className="alert-list-container">

View File

@@ -20,8 +20,8 @@ import useComponentPermission from 'hooks/useComponentPermission';
import useDebouncedFn from 'hooks/useDebouncedFunction'; import useDebouncedFn from 'hooks/useDebouncedFunction';
import useInterval from 'hooks/useInterval'; import useInterval from 'hooks/useInterval';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import history from 'lib/history';
import { mapQueryDataFromApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataFromApi'; import { mapQueryDataFromApi } from 'lib/newQueryBuilder/queryBuilderMappers/mapQueryDataFromApi';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
@@ -61,6 +61,7 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
const filteredData = filterAlerts(allAlertRules, value); const filteredData = filterAlerts(allAlertRules, value);
return filteredData || []; return filteredData || [];
}); });
const { safeNavigate } = useSafeNavigate();
// Type asuring // Type asuring
const sortingOrder: 'ascend' | 'descend' | null = const sortingOrder: 'ascend' | 'descend' | null =
@@ -102,7 +103,7 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
logEvent('Alert: New alert button clicked', { logEvent('Alert: New alert button clicked', {
number: allAlertRules?.length, number: allAlertRules?.length,
}); });
history.push(ROUTES.ALERTS_NEW); safeNavigate(ROUTES.ALERTS_NEW);
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
@@ -118,7 +119,7 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
params.set(QueryParams.ruleId, record.id.toString()); params.set(QueryParams.ruleId, record.id.toString());
setEditLoader(false); setEditLoader(false);
history.push(`${ROUTES.ALERT_OVERVIEW}?${params.toString()}`); safeNavigate(`${ROUTES.ALERT_OVERVIEW}?${params.toString()}`);
}; };
const onCloneHandler = ( const onCloneHandler = (
@@ -146,7 +147,7 @@ function ListAlert({ allAlertRules, refetch }: ListAlertProps): JSX.Element {
setTimeout(() => { setTimeout(() => {
const clonedAlert = refetchData.payload[refetchData.payload.length - 1]; const clonedAlert = refetchData.payload[refetchData.payload.length - 1];
params.set(QueryParams.ruleId, String(clonedAlert.id)); params.set(QueryParams.ruleId, String(clonedAlert.id));
history.push(`${ROUTES.EDIT_ALERTS}?${params.toString()}`); safeNavigate(`${ROUTES.EDIT_ALERTS}?${params.toString()}`);
}, 2000); }, 2000);
} }
if (status === 'error') { if (status === 'error') {

View File

@@ -75,7 +75,7 @@ import {
} from 'react'; } from 'react';
import { Layout } from 'react-grid-layout'; import { Layout } from 'react-grid-layout';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { generatePath } from 'react-router-dom'; import { generatePath } from 'react-router';
import { useCopyToClipboard } from 'react-use'; import { useCopyToClipboard } from 'react-use';
import { import {
Dashboard, Dashboard,

View File

@@ -25,7 +25,7 @@ import { ExternalLink, Github, MonitorDot, MoveRight, X } from 'lucide-react';
// See more: https://github.com/lucide-icons/lucide/issues/94 // See more: https://github.com/lucide-icons/lucide/issues/94
import { useState } from 'react'; import { useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { generatePath } from 'react-router-dom'; import { generatePath } from 'react-router';
import { DashboardData } from 'types/api/dashboard/getAll'; import { DashboardData } from 'types/api/dashboard/getAll';
function ImportJSON({ function ImportJSON({

View File

@@ -2,7 +2,7 @@ import { CloseCircleFilled } from '@ant-design/icons';
import { useMachine } from '@xstate/react'; import { useMachine } from '@xstate/react';
import { Button, Select } from 'antd'; import { Button, Select } from 'antd';
import { RefSelectProps } from 'antd/lib/select'; import { RefSelectProps } from 'antd/lib/select';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { filter, map } from 'lodash-es'; import { filter, map } from 'lodash-es';
import { import {
MutableRefObject, MutableRefObject,
@@ -11,6 +11,7 @@ import {
useRef, useRef,
useState, useState,
} from 'react'; } from 'react';
import { useLocation } from 'react-router';
import { Dashboard } from 'types/api/dashboard/getAll'; import { Dashboard } from 'types/api/dashboard/getAll';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
@@ -41,13 +42,15 @@ function SearchFilter({
const [selectedValues, setSelectedValues] = useState<string[]>([]); const [selectedValues, setSelectedValues] = useState<string[]>([]);
const [staging, setStaging] = useState<string[] | string[][] | unknown[]>([]); const [staging, setStaging] = useState<string[] | string[][] | unknown[]>([]);
const [queries, setQueries] = useState<IQueryStructure[]>([]); const [queries, setQueries] = useState<IQueryStructure[]>([]);
const { safeNavigate } = useSafeNavigate();
const { pathname, search } = useLocation();
useEffect(() => { useEffect(() => {
const searchQueryString = new URLSearchParams(history.location.search).get( const searchQueryString = new URLSearchParams(search).get('search');
'search',
);
if (searchQueryString) if (searchQueryString)
setQueries(convertURLQueryStringToQuery(searchQueryString) || []); setQueries(convertURLQueryStringToQuery(searchQueryString) || []);
// TODO: SMIT is this a bug no search in deps?
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
useEffect(() => { useEffect(() => {
filterDashboards(executeSearchQueries(queries, searchData)); filterDashboards(executeSearchQueries(queries, searchData));
@@ -56,15 +59,15 @@ function SearchFilter({
const updateURLWithQuery = useCallback( const updateURLWithQuery = useCallback(
(inputQueries?: IQueryStructure[]): void => { (inputQueries?: IQueryStructure[]): void => {
history.push({ safeNavigate({
pathname: history.location.pathname, pathname,
search: search:
inputQueries || queries inputQueries || queries
? `?search=${convertQueriesToURLQuery(inputQueries || queries)}` ? `?search=${convertQueriesToURLQuery(inputQueries || queries)}`
: '', : '',
}); });
}, },
[queries], [queries, pathname, safeNavigate],
); );
useEffect(() => { useEffect(() => {
@@ -149,8 +152,8 @@ function SearchFilter({
const clearQueries = (): void => { const clearQueries = (): void => {
setQueries([]); setQueries([]);
history.push({ safeNavigate({
pathname: history.location.pathname, pathname,
search: ``, search: ``,
}); });
}; };

View File

@@ -6,7 +6,7 @@ import { REACT_QUERY_KEY } from 'constants/reactQueryKeys';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { useDeleteDashboard } from 'hooks/dashboard/useDeleteDashboard'; import { useDeleteDashboard } from 'hooks/dashboard/useDeleteDashboard';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@@ -36,6 +36,7 @@ export function DeleteButton({
const isAuthor = user?.email === createdBy; const isAuthor = user?.email === createdBy;
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { safeNavigate } = useSafeNavigate();
const { notifications } = useNotifications(); const { notifications } = useNotifications();
@@ -68,7 +69,7 @@ export function DeleteButton({
}); });
queryClient.invalidateQueries([REACT_QUERY_KEY.GET_ALL_DASHBOARDS]); queryClient.invalidateQueries([REACT_QUERY_KEY.GET_ALL_DASHBOARDS]);
if (routeToListPage) { if (routeToListPage) {
history.replace(ROUTES.ALL_DASHBOARD); safeNavigate(ROUTES.ALL_DASHBOARD);
} }
destroy(); destroy();
}, },
@@ -86,6 +87,7 @@ export function DeleteButton({
t, t,
queryClient, queryClient,
routeToListPage, routeToListPage,
safeNavigate,
]); ]);
const getDeleteTooltipContent = (): string => { const getDeleteTooltipContent = (): string => {

View File

@@ -1,12 +1,13 @@
import { LockFilled } from '@ant-design/icons'; import { LockFilled } from '@ant-design/icons';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { Data } from '../DashboardsList'; import { Data } from '../DashboardsList';
import { TableLinkText } from './styles'; import { TableLinkText } from './styles';
function Name(name: Data['name'], data: Data): JSX.Element { function Name(name: Data['name'], data: Data): JSX.Element {
const { id: DashboardId, isLocked } = data; const { id: DashboardId, isLocked } = data;
const { safeNavigate } = useSafeNavigate();
const getLink = (): string => `${ROUTES.ALL_DASHBOARD}/${DashboardId}`; const getLink = (): string => `${ROUTES.ALL_DASHBOARD}/${DashboardId}`;
@@ -14,7 +15,7 @@ function Name(name: Data['name'], data: Data): JSX.Element {
if (event.metaKey || event.ctrlKey) { if (event.metaKey || event.ctrlKey) {
window.open(getLink(), '_blank'); window.open(getLink(), '_blank');
} else { } else {
history.push(getLink()); safeNavigate(getLink());
} }
}; };

View File

@@ -8,14 +8,14 @@ import {
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam'; import { useGetCompositeQueryParam } from 'hooks/queryBuilder/useGetCompositeQueryParam';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useHistory } from 'react-router-dom';
import { DataSource } from 'types/common/queryBuilder'; import { DataSource } from 'types/common/queryBuilder';
import { constructCompositeQuery } from '../constants'; import { constructCompositeQuery } from '../constants';
function BackButton(): JSX.Element { function BackButton(): JSX.Element {
const history = useHistory(); const { safeNavigate } = useSafeNavigate();
const { updateAllQueriesOperators } = useQueryBuilder(); const { updateAllQueriesOperators } = useQueryBuilder();
@@ -40,8 +40,8 @@ function BackButton(): JSX.Element {
const path = `${ROUTES.LOGS_EXPLORER}?${QueryParams.compositeQuery}=${JSONCompositeQuery}`; const path = `${ROUTES.LOGS_EXPLORER}?${QueryParams.compositeQuery}=${JSONCompositeQuery}`;
history.push(path); safeNavigate(path);
}, [history, compositeQuery, updateAllQueriesOperators]); }, [safeNavigate, compositeQuery, updateAllQueriesOperators]);
return ( return (
<Button icon={<ArrowLeftOutlined />} onClick={handleBack}> <Button icon={<ArrowLeftOutlined />} onClick={handleBack}>

View File

@@ -14,7 +14,7 @@ import { prepareQueryRangePayload } from 'lib/dashboard/prepareQueryRangePayload
import { useEventSource } from 'providers/EventSource'; import { useEventSource } from 'providers/EventSource';
import { useCallback, useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { ILog } from 'types/api/logs/log'; import { ILog } from 'types/api/logs/log';
import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { Query } from 'types/api/queryBuilder/queryBuilderData';

View File

@@ -14,7 +14,7 @@ import { ORDERBY_FILTERS } from 'container/QueryBuilder/filters/OrderByFilter/co
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { Virtuoso } from 'react-virtuoso'; import { Virtuoso } from 'react-virtuoso';
import { ILog } from 'types/api/logs/log'; import { ILog } from 'types/api/logs/log';
import { Query, TagFilter } from 'types/api/queryBuilder/queryBuilderData'; import { Query, TagFilter } from 'types/api/queryBuilder/queryBuilderData';

View File

@@ -15,13 +15,13 @@ import { OPERATORS } from 'constants/queryBuilder';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { FontSize, OptionsQuery } from 'container/OptionsMenu/types'; import { FontSize, OptionsQuery } from 'container/OptionsMenu/types';
import { useIsDarkMode } from 'hooks/useDarkMode'; import { useIsDarkMode } from 'hooks/useDarkMode';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { fieldSearchFilter } from 'lib/logs/fieldSearch'; import { fieldSearchFilter } from 'lib/logs/fieldSearch';
import { removeJSONStringifyQuotes } from 'lib/removeJSONStringifyQuotes'; import { removeJSONStringifyQuotes } from 'lib/removeJSONStringifyQuotes';
import { Pin } from 'lucide-react'; import { Pin } from 'lucide-react';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { generatePath } from 'react-router-dom'; import { generatePath } from 'react-router';
import { Dispatch } from 'redux'; import { Dispatch } from 'redux';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import { SET_DETAILED_LOG_DATA } from 'types/actions/logs'; import { SET_DETAILED_LOG_DATA } from 'types/actions/logs';
@@ -68,6 +68,7 @@ function TableView({
const [isfilterInLoading, setIsFilterInLoading] = useState<boolean>(false); const [isfilterInLoading, setIsFilterInLoading] = useState<boolean>(false);
const [isfilterOutLoading, setIsFilterOutLoading] = useState<boolean>(false); const [isfilterOutLoading, setIsFilterOutLoading] = useState<boolean>(false);
const isDarkMode = useIsDarkMode(); const isDarkMode = useIsDarkMode();
const { safeNavigate } = useSafeNavigate();
const [pinnedAttributes, setPinnedAttributes] = useState< const [pinnedAttributes, setPinnedAttributes] = useState<
Record<string, boolean> Record<string, boolean>
@@ -170,7 +171,7 @@ function TableView({
// open the trace in new tab // open the trace in new tab
window.open(route, '_blank'); window.open(route, '_blank');
} else { } else {
history.push(route); safeNavigate(route);
} }
} }
}; };

View File

@@ -14,7 +14,7 @@ import { isEmpty } from 'lodash-es';
import { ArrowDownToDot, ArrowUpFromDot, Ellipsis } from 'lucide-react'; import { ArrowDownToDot, ArrowUpFromDot, Ellipsis } from 'lucide-react';
import { useTimezone } from 'providers/Timezone'; import { useTimezone } from 'providers/Timezone';
import React, { useMemo, useState } from 'react'; import React, { useMemo, useState } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { FORBID_DOM_PURIFY_TAGS } from 'utils/app'; import { FORBID_DOM_PURIFY_TAGS } from 'utils/app';

View File

@@ -2,12 +2,12 @@ import LogDetail from 'components/LogDetail';
import { VIEW_TYPES } from 'components/LogDetail/constants'; import { VIEW_TYPES } from 'components/LogDetail/constants';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { getOldLogsOperatorFromNew } from 'hooks/logs/useActiveLog'; import { getOldLogsOperatorFromNew } from 'hooks/logs/useActiveLog';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { getGeneratedFilterQueryString } from 'lib/getGeneratedFilterQueryString'; import { getGeneratedFilterQueryString } from 'lib/getGeneratedFilterQueryString';
import getStep from 'lib/getStep'; import getStep from 'lib/getStep';
import { getIdConditions } from 'pages/Logs/utils'; import { getIdConditions } from 'pages/Logs/utils';
import { memo, useCallback } from 'react'; import { memo, useCallback } from 'react';
import { connect, useDispatch, useSelector } from 'react-redux'; import { connect, useDispatch, useSelector } from 'react-redux';
import { useHistory } from 'react-router-dom';
import { bindActionCreators, Dispatch } from 'redux'; import { bindActionCreators, Dispatch } from 'redux';
import { ThunkDispatch } from 'redux-thunk'; import { ThunkDispatch } from 'redux-thunk';
import { getLogs } from 'store/actions/logs/getLogs'; import { getLogs } from 'store/actions/logs/getLogs';
@@ -33,7 +33,7 @@ function LogDetailedView({
getLogs, getLogs,
getLogsAggregate, getLogsAggregate,
}: LogDetailedViewProps): JSX.Element { }: LogDetailedViewProps): JSX.Element {
const history = useHistory(); const { safeNavigate } = useSafeNavigate();
const { const {
detailedLog, detailedLog,
searchFilter: { queryString }, searchFilter: { queryString },
@@ -66,9 +66,11 @@ function LogDetailedView({
queryString, queryString,
); );
history.replace(`${ROUTES.OLD_LOGS_EXPLORER}?q=${updatedQueryString}`); safeNavigate(`${ROUTES.OLD_LOGS_EXPLORER}?q=${updatedQueryString}`, {
replace: true,
});
}, },
[history, queryString], [safeNavigate, queryString],
); );
const handleClickActionItem = useCallback( const handleClickActionItem = useCallback(

View File

@@ -8,12 +8,13 @@ import afterLogin from 'AppRoutes/utils';
import { LOCALSTORAGE } from 'constants/localStorage'; import { LOCALSTORAGE } from 'constants/localStorage';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useQuery } from 'react-query'; import { useQuery } from 'react-query';
import { PayloadProps as PrecheckResultType } from 'types/api/user/loginPrecheck'; import { PayloadProps as PrecheckResultType } from 'types/api/user/loginPrecheck';
import { safeNavigateNoSameURLMemo } from 'utils/navigate';
import { FormContainer, FormWrapper, Label, ParentContainer } from './styles'; import { FormContainer, FormWrapper, Label, ParentContainer } from './styles';
@@ -39,6 +40,7 @@ function Login({
const { t } = useTranslation(['login']); const { t } = useTranslation(['login']);
const [isLoading, setIsLoading] = useState<boolean>(false); const [isLoading, setIsLoading] = useState<boolean>(false);
const { user } = useAppContext(); const { user } = useAppContext();
const { safeNavigate } = useSafeNavigate();
const [precheckResult, setPrecheckResult] = useState<PrecheckResultType>({ const [precheckResult, setPrecheckResult] = useState<PrecheckResultType>({
sso: false, sso: false,
@@ -67,7 +69,7 @@ function Login({
const { setupCompleted } = getUserVersionResponse.data.payload; const { setupCompleted } = getUserVersionResponse.data.payload;
if (!setupCompleted) { if (!setupCompleted) {
// no org account registered yet, re-route user to sign up first // no org account registered yet, re-route user to sign up first
history.push(ROUTES.SIGN_UP); safeNavigateNoSameURLMemo(ROUTES.SIGN_UP);
} }
} }
}, [getUserVersionResponse]); }, [getUserVersionResponse]);
@@ -90,10 +92,10 @@ function Login({
LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT, LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT,
); );
if (fromPathname) { if (fromPathname) {
history.push(fromPathname); safeNavigateNoSameURLMemo(fromPathname);
setLocalStorageApi(LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT, ''); setLocalStorageApi(LOCALSTORAGE.UNAUTHENTICATED_ROUTE_HIT, '');
} else { } else {
history.push(ROUTES.APPLICATION); safeNavigateNoSameURLMemo(ROUTES.APPLICATION);
} }
} }
} }
@@ -287,7 +289,7 @@ function Login({
{t('prompt_if_admin')}{' '} {t('prompt_if_admin')}{' '}
<Typography.Link <Typography.Link
onClick={(): void => { onClick={(): void => {
history.push(ROUTES.SIGN_UP); safeNavigate(ROUTES.SIGN_UP);
}} }}
style={{ fontWeight: 700 }} style={{ fontWeight: 700 }}
> >

View File

@@ -4,15 +4,15 @@ import './LogsError.styles.scss';
import { Typography } from 'antd'; import { Typography } from 'antd';
import { useGetTenantLicense } from 'hooks/useGetTenantLicense'; import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { ArrowRight } from 'lucide-react'; import { ArrowRight } from 'lucide-react';
export default function LogsError(): JSX.Element { export default function LogsError(): JSX.Element {
const { isCloudUser: isCloudUserVal } = useGetTenantLicense(); const { isCloudUser: isCloudUserVal } = useGetTenantLicense();
const { safeNavigate } = useSafeNavigate();
const handleContactSupport = (): void => { const handleContactSupport = (): void => {
if (isCloudUserVal) { if (isCloudUserVal) {
history.push('/support'); safeNavigate('/support');
} else { } else {
window.open('https://signoz.io/slack', '_blank'); window.open('https://signoz.io/slack', '_blank');
} }

View File

@@ -9,7 +9,7 @@ import GetMinMax from 'lib/getMinMax';
import { colors } from 'lib/getRandomColor'; import { colors } from 'lib/getRandomColor';
import { memo, useCallback, useMemo } from 'react'; import { memo, useCallback, useMemo } from 'react';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { UpdateTimeInterval } from 'store/actions'; import { UpdateTimeInterval } from 'store/actions';
import { LogsExplorerChartProps } from './LogsExplorerChart.interfaces'; import { LogsExplorerChartProps } from './LogsExplorerChart.interfaces';

View File

@@ -1,7 +1,7 @@
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
import { getMinMax } from 'container/TopNav/AutoRefresh/config'; import { getMinMax } from 'container/TopNav/AutoRefresh/config';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import history from 'lib/history';
import { parseQuery } from 'lib/logql'; import { parseQuery } from 'lib/logql';
import isEqual from 'lodash-es/isEqual'; import isEqual from 'lodash-es/isEqual';
import { useCallback, useEffect } from 'react'; import { useCallback, useEffect } from 'react';
@@ -24,6 +24,7 @@ export function useSearchParser(): {
updateQueryString: (arg0: string) => void; updateQueryString: (arg0: string) => void;
} { } {
const dispatch = useDispatch<Dispatch<AppActions>>(); const dispatch = useDispatch<Dispatch<AppActions>>();
const { safeNavigate } = useSafeNavigate();
const { const {
searchFilter: { parsedQuery, queryString }, searchFilter: { parsedQuery, queryString },
order, order,
@@ -39,10 +40,16 @@ export function useSearchParser(): {
const updateQueryString = useCallback( const updateQueryString = useCallback(
(updatedQueryString: string) => { (updatedQueryString: string) => {
history.replace({ // Defaults to the current URL
pathname: history.location.pathname, safeNavigate(
search: `?${QueryParams.q}=${updatedQueryString}&${QueryParams.order}=${order}`, {
}); // No need to prepend '?'
search: `${QueryParams.q}=${updatedQueryString}&${QueryParams.order}=${order}`,
},
{
replace: true,
},
);
const globalTime = getMinMax(selectedTime, minTime, maxTime); const globalTime = getMinMax(selectedTime, minTime, maxTime);
@@ -64,7 +71,7 @@ export function useSearchParser(): {
}, },
// need to hide this warning as we don't want to update the query string on every change // need to hide this warning as we don't want to update the query string on every change
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
[dispatch, parsedQuery, selectedTime, queryString], [dispatch, parsedQuery, selectedTime, queryString, safeNavigate],
); );
useEffect(() => { useEffect(() => {

View File

@@ -13,16 +13,16 @@ import {
import { QueryHistoryState } from 'container/LiveLogs/types'; import { QueryHistoryState } from 'container/LiveLogs/types';
import LocalTopNav from 'container/LocalTopNav'; import LocalTopNav from 'container/LocalTopNav';
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder'; import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import { useQueryClient } from 'react-query'; import { useQueryClient } from 'react-query';
import { useHistory } from 'react-router-dom';
import { ErrorResponse, SuccessResponse } from 'types/api'; import { ErrorResponse, SuccessResponse } from 'types/api';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange'; import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { LiveButtonStyled } from './styles'; import { LiveButtonStyled } from './styles';
function LogsTopNav(): JSX.Element { function LogsTopNav(): JSX.Element {
const history = useHistory(); const { safeNavigate } = useSafeNavigate();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { stagedQuery, panelType } = useQueryBuilder(); const { stagedQuery, panelType } = useQueryBuilder();
@@ -65,8 +65,9 @@ function LogsTopNav(): JSX.Element {
const path = `${ROUTES.LIVE_LOGS}?${QueryParams.compositeQuery}=${JSONCompositeQuery}`; const path = `${ROUTES.LIVE_LOGS}?${QueryParams.compositeQuery}=${JSONCompositeQuery}`;
history.push(path, queryHistoryState); // TODO: SMIT Discuss with reviewer
}, [history, panelType, queryClient, stagedQuery]); safeNavigate(path, { state: queryHistoryState });
}, [safeNavigate, panelType, queryClient, stagedQuery]);
const liveButton = useMemo( const liveButton = useMemo(
() => ( () => (

View File

@@ -16,10 +16,9 @@ import {
import { useSafeNavigate } from 'hooks/useSafeNavigate'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import getStep from 'lib/getStep'; import getStep from 'lib/getStep';
import history from 'lib/history';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useLocation, useParams } from 'react-router-dom'; import { useLocation, useParams } from 'react-router';
import store from 'store'; import store from 'store';
import { UpdateTimeInterval } from 'store/actions'; import { UpdateTimeInterval } from 'store/actions';
import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData'; import { TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
@@ -40,13 +39,17 @@ import {
} from './util'; } from './util';
function DBCall(): JSX.Element { function DBCall(): JSX.Element {
const { servicename: encodedServiceName } = useParams<IServiceName>(); // Temp: Hard type casting for string | undefined
const {
servicename: encodedServiceName,
} = (useParams() as unknown) as IServiceName;
const servicename = decodeURIComponent(encodedServiceName); const servicename = decodeURIComponent(encodedServiceName);
const [selectedTimeStamp, setSelectedTimeStamp] = useState<number>(0); const [selectedTimeStamp, setSelectedTimeStamp] = useState<number>(0);
const { queries } = useResourceAttribute(); const { queries } = useResourceAttribute();
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
const { pathname } = useLocation(); const { pathname } = useLocation();
const { safeNavigate } = useSafeNavigate();
const dispatch = useDispatch(); const dispatch = useDispatch();
const onDragSelect = useCallback( const onDragSelect = useCallback(
@@ -57,13 +60,13 @@ function DBCall(): JSX.Element {
urlQuery.set(QueryParams.startTime, startTimestamp.toString()); urlQuery.set(QueryParams.startTime, startTimestamp.toString());
urlQuery.set(QueryParams.endTime, endTimestamp.toString()); urlQuery.set(QueryParams.endTime, endTimestamp.toString());
const generatedUrl = `${pathname}?${urlQuery.toString()}`; const generatedUrl = `${pathname}?${urlQuery.toString()}`;
history.push(generatedUrl); safeNavigate(generatedUrl);
if (startTimestamp !== endTimestamp) { if (startTimestamp !== endTimestamp) {
dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp])); dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp]));
} }
}, },
[dispatch, pathname, urlQuery], [dispatch, pathname, urlQuery, safeNavigate],
); );
const tagFilterItems: TagFilterItem[] = useMemo( const tagFilterItems: TagFilterItem[] = useMemo(
@@ -158,7 +161,6 @@ function DBCall(): JSX.Element {
servicename, servicename,
isDBCall: true, isDBCall: true,
}); });
const { safeNavigate } = useSafeNavigate();
const onGraphClickHandler = useGraphClickHandler(setSelectedTimeStamp); const onGraphClickHandler = useGraphClickHandler(setSelectedTimeStamp);

View File

@@ -18,10 +18,9 @@ import {
import { useSafeNavigate } from 'hooks/useSafeNavigate'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import getStep from 'lib/getStep'; import getStep from 'lib/getStep';
import history from 'lib/history';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useLocation, useParams } from 'react-router-dom'; import { useLocation, useParams } from 'react-router';
import store from 'store'; import store from 'store';
import { UpdateTimeInterval } from 'store/actions'; import { UpdateTimeInterval } from 'store/actions';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
@@ -43,10 +42,14 @@ import {
function External(): JSX.Element { function External(): JSX.Element {
const [selectedTimeStamp, setSelectedTimeStamp] = useState<number>(0); const [selectedTimeStamp, setSelectedTimeStamp] = useState<number>(0);
const { servicename: encodedServiceName } = useParams<IServiceName>(); // Temp: Hard type casting for string | undefined
const {
servicename: encodedServiceName,
} = (useParams() as unknown) as IServiceName;
const servicename = decodeURIComponent(encodedServiceName); const servicename = decodeURIComponent(encodedServiceName);
const { queries } = useResourceAttribute(); const { queries } = useResourceAttribute();
const { safeNavigate } = useSafeNavigate();
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
const { pathname } = useLocation(); const { pathname } = useLocation();
@@ -60,13 +63,13 @@ function External(): JSX.Element {
urlQuery.set(QueryParams.startTime, startTimestamp.toString()); urlQuery.set(QueryParams.startTime, startTimestamp.toString());
urlQuery.set(QueryParams.endTime, endTimestamp.toString()); urlQuery.set(QueryParams.endTime, endTimestamp.toString());
const generatedUrl = `${pathname}?${urlQuery.toString()}`; const generatedUrl = `${pathname}?${urlQuery.toString()}`;
history.push(generatedUrl); safeNavigate(generatedUrl);
if (startTimestamp !== endTimestamp) { if (startTimestamp !== endTimestamp) {
dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp])); dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp]));
} }
}, },
[dispatch, pathname, urlQuery], [dispatch, pathname, urlQuery, safeNavigate],
); );
const tagFilterItems = useMemo( const tagFilterItems = useMemo(
@@ -221,8 +224,6 @@ function External(): JSX.Element {
isExternalCall: true, isExternalCall: true,
}); });
const { safeNavigate } = useSafeNavigate();
const onGraphClickHandler = useGraphClickHandler(setSelectedTimeStamp); const onGraphClickHandler = useGraphClickHandler(setSelectedTimeStamp);
return ( return (

View File

@@ -16,14 +16,13 @@ import {
import { useSafeNavigate } from 'hooks/useSafeNavigate'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import getStep from 'lib/getStep'; import getStep from 'lib/getStep';
import history from 'lib/history';
import { OnClickPluginOpts } from 'lib/uPlotLib/plugins/onClickPlugin'; import { OnClickPluginOpts } from 'lib/uPlotLib/plugins/onClickPlugin';
import { defaultTo } from 'lodash-es'; import { defaultTo } from 'lodash-es';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useQuery } from 'react-query'; import { useQuery } from 'react-query';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { useLocation, useParams } from 'react-router-dom'; import { useLocation, useParams } from 'react-router';
import { UpdateTimeInterval } from 'store/actions'; import { UpdateTimeInterval } from 'store/actions';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
@@ -58,7 +57,10 @@ import {
} from './util'; } from './util';
function Application(): JSX.Element { function Application(): JSX.Element {
const { servicename: encodedServiceName } = useParams<IServiceName>(); // Temp: Hard type casting for string | undefined
const {
servicename: encodedServiceName,
} = (useParams() as unknown) as IServiceName;
const servicename = decodeURIComponent(encodedServiceName); const servicename = decodeURIComponent(encodedServiceName);
const { maxTime, minTime } = useSelector<AppState, GlobalReducer>( const { maxTime, minTime } = useSelector<AppState, GlobalReducer>(
@@ -69,6 +71,7 @@ function Application(): JSX.Element {
const { search, pathname } = useLocation(); const { search, pathname } = useLocation();
const { queries } = useResourceAttribute(); const { queries } = useResourceAttribute();
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
const { safeNavigate } = useSafeNavigate();
const { featureFlags } = useAppContext(); const { featureFlags } = useAppContext();
const isSpanMetricEnabled = const isSpanMetricEnabled =
@@ -208,13 +211,13 @@ function Application(): JSX.Element {
urlQuery.set(QueryParams.startTime, startTimestamp.toString()); urlQuery.set(QueryParams.startTime, startTimestamp.toString());
urlQuery.set(QueryParams.endTime, endTimestamp.toString()); urlQuery.set(QueryParams.endTime, endTimestamp.toString());
const generatedUrl = `${pathname}?${urlQuery.toString()}`; const generatedUrl = `${pathname}?${urlQuery.toString()}`;
history.push(generatedUrl); safeNavigate(generatedUrl);
if (startTimestamp !== endTimestamp) { if (startTimestamp !== endTimestamp) {
dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp])); dispatch(UpdateTimeInterval('custom', [startTimestamp, endTimestamp]));
} }
}, },
[dispatch, pathname, urlQuery], [dispatch, pathname, urlQuery, safeNavigate],
); );
/** /**
@@ -253,7 +256,7 @@ function Application(): JSX.Element {
queryString, queryString,
); );
history.push(newPath); safeNavigate(newPath);
}, },
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
[stepInterval], [stepInterval],
@@ -295,7 +298,6 @@ function Application(): JSX.Element {
}, },
], ],
}); });
const { safeNavigate } = useSafeNavigate();
return ( return (
<> <>

View File

@@ -16,7 +16,7 @@ import {
import { getWidgetQueryBuilder } from 'container/MetricsApplication/MetricsApplication.factory'; import { getWidgetQueryBuilder } from 'container/MetricsApplication/MetricsApplication.factory';
import { apDexMetricsQueryBuilderQueries } from 'container/MetricsApplication/MetricsPageQueries/OverviewQueries'; import { apDexMetricsQueryBuilderQueries } from 'container/MetricsApplication/MetricsPageQueries/OverviewQueries';
import { ReactNode, useMemo } from 'react'; import { ReactNode, useMemo } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router';
import { EQueryType } from 'types/common/dashboard'; import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
@@ -32,7 +32,10 @@ function ApDexMetrics({
topLevelOperationsRoute, topLevelOperationsRoute,
handleGraphClick, handleGraphClick,
}: ApDexMetricsProps): JSX.Element { }: ApDexMetricsProps): JSX.Element {
const { servicename: encodedServiceName } = useParams<IServiceName>(); // Temp: Hard type casting for string | undefined
const {
servicename: encodedServiceName,
} = (useParams() as unknown) as IServiceName;
const servicename = decodeURIComponent(encodedServiceName); const servicename = decodeURIComponent(encodedServiceName);
const apDexMetricsWidget = useMemo( const apDexMetricsWidget = useMemo(

View File

@@ -1,7 +1,7 @@
import Spinner from 'components/Spinner'; import Spinner from 'components/Spinner';
import { useGetMetricMeta } from 'hooks/apDex/useGetMetricMeta'; import { useGetMetricMeta } from 'hooks/apDex/useGetMetricMeta';
import useErrorNotification from 'hooks/useErrorNotification'; import useErrorNotification from 'hooks/useErrorNotification';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router';
import { IServiceName } from '../../types'; import { IServiceName } from '../../types';
import ApDexMetrics from './ApDexMetrics'; import ApDexMetrics from './ApDexMetrics';
@@ -15,7 +15,10 @@ function ApDexMetricsApplication({
thresholdValue, thresholdValue,
topLevelOperationsRoute, topLevelOperationsRoute,
}: ApDexDataSwitcherProps): JSX.Element { }: ApDexDataSwitcherProps): JSX.Element {
const { servicename: encodedServiceName } = useParams<IServiceName>(); // Temp: Hard type casting for string | undefined
const {
servicename: encodedServiceName,
} = (useParams() as unknown) as IServiceName;
const servicename = decodeURIComponent(encodedServiceName); const servicename = decodeURIComponent(encodedServiceName);
const { data, isLoading, error } = useGetMetricMeta(metricMeta, servicename); const { data, isLoading, error } = useGetMetricMeta(metricMeta, servicename);

View File

@@ -7,7 +7,7 @@ import { GraphTitle } from 'container/MetricsApplication/constant';
import { getWidgetQueryBuilder } from 'container/MetricsApplication/MetricsApplication.factory'; import { getWidgetQueryBuilder } from 'container/MetricsApplication/MetricsApplication.factory';
import { apDexTracesQueryBuilderQueries } from 'container/MetricsApplication/MetricsPageQueries/OverviewQueries'; import { apDexTracesQueryBuilderQueries } from 'container/MetricsApplication/MetricsPageQueries/OverviewQueries';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router';
import { EQueryType } from 'types/common/dashboard'; import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
@@ -21,7 +21,10 @@ function ApDexTraces({
tagFilterItems, tagFilterItems,
thresholdValue, thresholdValue,
}: ApDexDataSwitcherProps): JSX.Element { }: ApDexDataSwitcherProps): JSX.Element {
const { servicename: encodedServiceName } = useParams<IServiceName>(); // Temp: Hard type casting for string | undefined
const {
servicename: encodedServiceName,
} = (useParams() as unknown) as IServiceName;
const servicename = decodeURIComponent(encodedServiceName); const servicename = decodeURIComponent(encodedServiceName);
const apDexTracesWidget = useMemo( const apDexTracesWidget = useMemo(

View File

@@ -3,7 +3,7 @@ import { Card, GraphContainer } from 'container/MetricsApplication/styles';
import { useGetApDexSettings } from 'hooks/apDex/useGetApDexSettings'; import { useGetApDexSettings } from 'hooks/apDex/useGetApDexSettings';
import useErrorNotification from 'hooks/useErrorNotification'; import useErrorNotification from 'hooks/useErrorNotification';
import { memo } from 'react'; import { memo } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router';
import { IServiceName } from '../../types'; import { IServiceName } from '../../types';
import ApDexMetricsApplication from './ApDexMetricsApplication'; import ApDexMetricsApplication from './ApDexMetricsApplication';
@@ -15,7 +15,10 @@ function ApDexApplication({
topLevelOperationsRoute, topLevelOperationsRoute,
tagFilterItems, tagFilterItems,
}: ApDexApplicationProps): JSX.Element { }: ApDexApplicationProps): JSX.Element {
const { servicename: encodedServiceName } = useParams<IServiceName>(); // Temp: Hard type casting for string | undefined
const {
servicename: encodedServiceName,
} = (useParams() as unknown) as IServiceName;
const servicename = decodeURIComponent(encodedServiceName); const servicename = decodeURIComponent(encodedServiceName);
const { data, isLoading, error, isRefetching } = useGetApDexSettings( const { data, isLoading, error, isRefetching } = useGetApDexSettings(

View File

@@ -16,7 +16,7 @@ import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { OnClickPluginOpts } from 'lib/uPlotLib/plugins/onClickPlugin'; import { OnClickPluginOpts } from 'lib/uPlotLib/plugins/onClickPlugin';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router';
import { EQueryType } from 'types/common/dashboard'; import { EQueryType } from 'types/common/dashboard';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
@@ -38,7 +38,10 @@ function ServiceOverview({
topLevelOperationsIsLoading, topLevelOperationsIsLoading,
stepInterval, stepInterval,
}: ServiceOverviewProps): JSX.Element { }: ServiceOverviewProps): JSX.Element {
const { servicename: encodedServiceName } = useParams<IServiceName>(); // Temp: Hard type casting for string | undefined
const {
servicename: encodedServiceName,
} = (useParams() as unknown) as IServiceName;
const servicename = decodeURIComponent(encodedServiceName); const servicename = decodeURIComponent(encodedServiceName);
const { featureFlags } = useAppContext(); const { featureFlags } = useAppContext();

View File

@@ -5,7 +5,7 @@ import { convertRawQueriesToTraceSelectedTags } from 'hooks/useResourceAttribute
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useQuery } from 'react-query'; import { useQuery } from 'react-query';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { PayloadProps } from 'types/api/metrics/getTopOperations'; import { PayloadProps } from 'types/api/metrics/getTopOperations';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
@@ -15,9 +15,10 @@ function TopOperation(): JSX.Element {
const { maxTime, minTime } = useSelector<AppState, GlobalReducer>( const { maxTime, minTime } = useSelector<AppState, GlobalReducer>(
(state) => state.globalTime, (state) => state.globalTime,
); );
const { servicename: encodedServiceName } = useParams<{ // Temp: Hard type casting for string | undefined
const { servicename: encodedServiceName } = (useParams() as unknown) as {
servicename?: string; servicename?: string;
}>(); };
const servicename = decodeURIComponent(encodedServiceName || ''); const servicename = decodeURIComponent(encodedServiceName || '');
const { queries } = useResourceAttribute(); const { queries } = useResourceAttribute();

View File

@@ -12,7 +12,7 @@ import { convertRawQueriesToTraceSelectedTags } from 'hooks/useResourceAttribute
import { RowData } from 'lib/query/createTableColumnsFromQuery'; import { RowData } from 'lib/query/createTableColumnsFromQuery';
import { ReactNode, useMemo } from 'react'; import { ReactNode, useMemo } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { EQueryType } from 'types/common/dashboard'; import { EQueryType } from 'types/common/dashboard';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
@@ -24,7 +24,10 @@ import ColumnWithLink from './TableRenderer/ColumnWithLink';
import { getTableColumnRenderer } from './TableRenderer/TableColumnRenderer'; import { getTableColumnRenderer } from './TableRenderer/TableColumnRenderer';
function TopOperationMetrics(): JSX.Element { function TopOperationMetrics(): JSX.Element {
const { servicename: encodedServiceName } = useParams<IServiceName>(); // Temp: Hard type casting for string | undefined
const {
servicename: encodedServiceName,
} = (useParams() as unknown) as IServiceName;
const servicename = decodeURIComponent(encodedServiceName); const servicename = decodeURIComponent(encodedServiceName);
const { notifications } = useNotifications(); const { notifications } = useNotifications();

View File

@@ -11,7 +11,7 @@ import { convertRawQueriesToTraceSelectedTags } from 'hooks/useResourceAttribute
import { useSafeNavigate } from 'hooks/useSafeNavigate'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { useRef } from 'react'; import { useRef } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse'; import { DataTypes } from 'types/api/queryBuilder/queryAutocompleteResponse';
import { Query, TagFilterItem } from 'types/api/queryBuilder/queryBuilderData'; import { Query, TagFilterItem } from 'types/api/queryBuilder/queryBuilderData';
@@ -31,7 +31,10 @@ function TopOperationsTable({
isLoading, isLoading,
}: TopOperationsTableProps): JSX.Element { }: TopOperationsTableProps): JSX.Element {
const searchInput = useRef<InputRef>(null); const searchInput = useRef<InputRef>(null);
const { servicename: encodedServiceName } = useParams<IServiceName>(); // Temp: Hard type casting for string | undefined
const {
servicename: encodedServiceName,
} = (useParams() as unknown) as IServiceName;
const { safeNavigate } = useSafeNavigate(); const { safeNavigate } = useSafeNavigate();
const servicename = decodeURIComponent(encodedServiceName); const servicename = decodeURIComponent(encodedServiceName);
const { minTime, maxTime } = useSelector<AppState, GlobalReducer>( const { minTime, maxTime } = useSelector<AppState, GlobalReducer>(
@@ -45,7 +48,8 @@ function TopOperationsTable({
const apmToTraceQuery = useGetAPMToTracesQueries({ servicename }); const apmToTraceQuery = useGetAPMToTracesQueries({ servicename });
const params = useParams<{ servicename: string }>(); // Temp: Hard type casting for string | undefined
const params = (useParams() as unknown) as { servicename: string };
const handleOnClick = (operation: string): void => { const handleOnClick = (operation: string): void => {
const { servicename: encodedServiceName } = params; const { servicename: encodedServiceName } = params;

View File

@@ -4,10 +4,9 @@ import { QueryParams } from 'constants/query';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { useSafeNavigate } from 'hooks/useSafeNavigate'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import history from 'lib/history';
import { Bell, Grid } from 'lucide-react'; import { Bell, Grid } from 'lucide-react';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { generatePath } from 'react-router-dom'; import { generatePath } from 'react-router';
import { DashboardsAndAlertsPopoverProps } from './types'; import { DashboardsAndAlertsPopoverProps } from './types';
@@ -27,7 +26,7 @@ function DashboardsAndAlertsPopover({
key={alert.alert_id} key={alert.alert_id}
onClick={(): void => { onClick={(): void => {
params.set(QueryParams.ruleId, alert.alert_id); params.set(QueryParams.ruleId, alert.alert_id);
history.push(`${ROUTES.ALERT_OVERVIEW}?${params.toString()}`); safeNavigate(`${ROUTES.ALERT_OVERVIEW}?${params.toString()}`);
}} }}
className="dashboards-popover-content-item" className="dashboards-popover-content-item"
> >
@@ -37,7 +36,7 @@ function DashboardsAndAlertsPopover({
})); }));
} }
return null; return null;
}, [alerts, params]); }, [alerts, params, safeNavigate]);
const uniqueDashboards = useMemo( const uniqueDashboards = useMemo(
() => () =>

View File

@@ -4,9 +4,10 @@ import { Card, Modal } from 'antd';
import logEvent from 'api/common/logEvent'; import logEvent from 'api/common/logEvent';
import { QueryParams } from 'constants/query'; import { QueryParams } from 'constants/query';
import { PANEL_TYPES } from 'constants/queryBuilder'; import { PANEL_TYPES } from 'constants/queryBuilder';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import createQueryParams from 'lib/createQueryParams'; import createQueryParams from 'lib/createQueryParams';
import history from 'lib/history';
import { useDashboard } from 'providers/Dashboard/Dashboard'; import { useDashboard } from 'providers/Dashboard/Dashboard';
import { useLocation } from 'react-router';
import { LogsAggregatorOperator } from 'types/common/queryBuilder'; import { LogsAggregatorOperator } from 'types/common/queryBuilder';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
@@ -16,7 +17,8 @@ import { Text } from './styles';
function DashboardGraphSlider(): JSX.Element { function DashboardGraphSlider(): JSX.Element {
const { handleToggleDashboardSlider, isDashboardSliderOpen } = useDashboard(); const { handleToggleDashboardSlider, isDashboardSliderOpen } = useDashboard();
const { safeNavigate } = useSafeNavigate();
const location = useLocation();
// eslint-disable-next-line sonarjs/cognitive-complexity // eslint-disable-next-line sonarjs/cognitive-complexity
const onClickHandler = (name: PANEL_TYPES) => (): void => { const onClickHandler = (name: PANEL_TYPES) => (): void => {
const id = uuid(); const id = uuid();
@@ -56,13 +58,11 @@ function DashboardGraphSlider(): JSX.Element {
), ),
}; };
if (name === PANEL_TYPES.LIST) { if (name === PANEL_TYPES.LIST) {
history.push( safeNavigate(
`${history.location.pathname}/new?${createQueryParams(queryParamsLog)}`, `${location.pathname}/new?${createQueryParams(queryParamsLog)}`,
); );
} else { } else {
history.push( safeNavigate(`${location.pathname}/new?${createQueryParams(queryParams)}`);
`${history.location.pathname}/new?${createQueryParams(queryParams)}`,
);
} }
}; };

View File

@@ -2,7 +2,8 @@ import { getNonIntegrationDashboardById } from 'mocks-server/__mockdata__/dashbo
import { server } from 'mocks-server/server'; import { server } from 'mocks-server/server';
import { rest } from 'msw'; import { rest } from 'msw';
import { DashboardProvider } from 'providers/Dashboard/Dashboard'; import { DashboardProvider } from 'providers/Dashboard/Dashboard';
import { MemoryRouter, useLocation } from 'react-router-dom'; import { MemoryRouter } from 'react-router-dom';
import { useLocation } from 'react-router-dom-v5-compat';
import { fireEvent, render, screen, waitFor } from 'tests/test-utils'; import { fireEvent, render, screen, waitFor } from 'tests/test-utils';
import DashboardDescription from '..'; import DashboardDescription from '..';

View File

@@ -1,14 +1,15 @@
import { CompassOutlined } from '@ant-design/icons'; import { CompassOutlined } from '@ant-design/icons';
import { Badge, Button } from 'antd'; import { Badge, Button } from 'antd';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { buttonText, RIBBON_STYLES } from './config'; import { buttonText, RIBBON_STYLES } from './config';
function NewExplorerCTA(): JSX.Element | null { function NewExplorerCTA(): JSX.Element | null {
const location = useLocation(); const location = useLocation();
const { safeNavigate } = useSafeNavigate();
const isTraceOrLogsExplorerPage = useMemo( const isTraceOrLogsExplorerPage = useMemo(
() => () =>
@@ -21,15 +22,15 @@ function NewExplorerCTA(): JSX.Element | null {
const onClickHandler = useCallback((): void => { const onClickHandler = useCallback((): void => {
if (location.pathname === ROUTES.LOGS_EXPLORER) { if (location.pathname === ROUTES.LOGS_EXPLORER) {
history.push(ROUTES.OLD_LOGS_EXPLORER); safeNavigate(ROUTES.OLD_LOGS_EXPLORER);
} else if (location.pathname === ROUTES.TRACE) { } else if (location.pathname === ROUTES.TRACE) {
history.push(ROUTES.TRACES_EXPLORER); safeNavigate(ROUTES.TRACES_EXPLORER);
} else if (location.pathname === ROUTES.OLD_LOGS_EXPLORER) { } else if (location.pathname === ROUTES.OLD_LOGS_EXPLORER) {
history.push(ROUTES.LOGS_EXPLORER); safeNavigate(ROUTES.LOGS_EXPLORER);
} else if (location.pathname === ROUTES.TRACES_EXPLORER) { } else if (location.pathname === ROUTES.TRACES_EXPLORER) {
history.push(ROUTES.TRACE); safeNavigate(ROUTES.TRACE);
} }
}, [location.pathname]); }, [location.pathname, safeNavigate]);
const button = useMemo( const button = useMemo(
() => ( () => (

View File

@@ -22,7 +22,7 @@ import {
} from 'react'; } from 'react';
import { UseQueryResult } from 'react-query'; import { UseQueryResult } from 'react-query';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { UpdateTimeInterval } from 'store/actions'; import { UpdateTimeInterval } from 'store/actions';
import { SuccessResponse } from 'types/api'; import { SuccessResponse } from 'types/api';
import { Widgets } from 'types/api/dashboard/getAll'; import { Widgets } from 'types/api/dashboard/getAll';

View File

@@ -1,6 +1,6 @@
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { QueryBuilderProvider } from 'providers/QueryBuilder'; import { QueryBuilderProvider } from 'providers/QueryBuilder';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom-v5-compat';
import { render } from 'tests/test-utils'; import { render } from 'tests/test-utils';
import { Query } from 'types/api/queryBuilder/queryBuilderData'; import { Query } from 'types/api/queryBuilder/queryBuilderData';

View File

@@ -35,7 +35,7 @@ import {
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { generatePath, useParams } from 'react-router-dom'; import { generatePath, useParams } from 'react-router';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { ColumnUnit, Dashboard, Widgets } from 'types/api/dashboard/getAll'; import { ColumnUnit, Dashboard, Widgets } from 'types/api/dashboard/getAll';
import { IField } from 'types/api/logs/fields'; import { IField } from 'types/api/logs/fields';
@@ -101,7 +101,8 @@ function NewWidget({ selectedGraph }: NewWidgetProps): JSX.Element {
const query = useUrlQuery(); const query = useUrlQuery();
const { dashboardId } = useParams<DashboardWidgetPageParams>(); // Temp: Hard type casting for string | undefined
const { dashboardId } = (useParams() as unknown) as DashboardWidgetPageParams;
const [isNewDashboard, setIsNewDashboard] = useState<boolean>(false); const [isNewDashboard, setIsNewDashboard] = useState<boolean>(false);

View File

@@ -4,7 +4,7 @@ import { Typography } from 'antd';
import logEvent from 'api/common/logEvent'; import logEvent from 'api/common/logEvent';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { useGetTenantLicense } from 'hooks/useGetTenantLicense'; import { useGetTenantLicense } from 'hooks/useGetTenantLicense';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { ArrowUpRight } from 'lucide-react'; import { ArrowUpRight } from 'lucide-react';
import { DataSource } from 'types/common/queryBuilder'; import { DataSource } from 'types/common/queryBuilder';
import DOCLINKS from 'utils/docLinks'; import DOCLINKS from 'utils/docLinks';
@@ -15,6 +15,7 @@ export default function NoLogs({
dataSource: DataSource; dataSource: DataSource;
}): JSX.Element { }): JSX.Element {
const { isCloudUser: isCloudUserVal } = useGetTenantLicense(); const { isCloudUser: isCloudUserVal } = useGetTenantLicense();
const { safeNavigate } = useSafeNavigate();
const handleLinkClick = ( const handleLinkClick = (
e: React.MouseEvent<HTMLAnchorElement, MouseEvent>, e: React.MouseEvent<HTMLAnchorElement, MouseEvent>,
@@ -28,7 +29,7 @@ export default function NoLogs({
} else if (dataSource === DataSource.LOGS) { } else if (dataSource === DataSource.LOGS) {
logEvent('Logs Explorer: Navigate to onboarding', {}); logEvent('Logs Explorer: Navigate to onboarding', {});
} }
history.push( safeNavigate(
dataSource === 'traces' dataSource === 'traces'
? ROUTES.GET_STARTED_APPLICATION_MONITORING ? ROUTES.GET_STARTED_APPLICATION_MONITORING
: ROUTES.GET_STARTED_LOGS_MANAGEMENT, : ROUTES.GET_STARTED_LOGS_MANAGEMENT,

View File

@@ -12,12 +12,13 @@ import ROUTES from 'constants/routes';
import FullScreenHeader from 'container/FullScreenHeader/FullScreenHeader'; import FullScreenHeader from 'container/FullScreenHeader/FullScreenHeader';
import InviteUserModal from 'container/OrganizationSettings/InviteUserModal/InviteUserModal'; import InviteUserModal from 'container/OrganizationSettings/InviteUserModal/InviteUserModal';
import { InviteMemberFormValues } from 'container/OrganizationSettings/PendingInvitesContainer'; import { InviteMemberFormValues } from 'container/OrganizationSettings/PendingInvitesContainer';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { UserPlus } from 'lucide-react'; import { UserPlus } from 'lucide-react';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useCallback, useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useQuery } from 'react-query'; import { useQuery } from 'react-query';
import { useLocation } from 'react-router';
import { useEffectOnce } from 'react-use'; import { useEffectOnce } from 'react-use';
import ModuleStepsContainer from './common/ModuleStepsContainer/ModuleStepsContainer'; import ModuleStepsContainer from './common/ModuleStepsContainer/ModuleStepsContainer';
@@ -105,8 +106,9 @@ export default function Onboarding(): JSX.Element {
const [selectedModuleSteps, setSelectedModuleSteps] = useState(APM_STEPS); const [selectedModuleSteps, setSelectedModuleSteps] = useState(APM_STEPS);
const [activeStep, setActiveStep] = useState(1); const [activeStep, setActiveStep] = useState(1);
const [current, setCurrent] = useState(0); const [current, setCurrent] = useState(0);
const { location } = history; const location = useLocation();
const { t } = useTranslation(['onboarding']); const { t } = useTranslation(['onboarding']);
const { safeNavigate } = useSafeNavigate();
const { featureFlags } = useAppContext(); const { featureFlags } = useAppContext();
const isOnboardingV3Enabled = featureFlags?.find( const isOnboardingV3Enabled = featureFlags?.find(
@@ -254,7 +256,7 @@ export default function Onboarding(): JSX.Element {
const handleNext = (): void => { const handleNext = (): void => {
if (activeStep <= 3) { if (activeStep <= 3) {
history.push(moduleRouteMap[selectedModule.id as ModulesMap]); safeNavigate(moduleRouteMap[selectedModule.id as ModulesMap]);
} }
}; };
@@ -319,7 +321,7 @@ export default function Onboarding(): JSX.Element {
<div <div
onClick={(): void => { onClick={(): void => {
logEvent('Onboarding V2: Skip Button Clicked', {}); logEvent('Onboarding V2: Skip Button Clicked', {});
history.push(ROUTES.APPLICATION); safeNavigate(ROUTES.APPLICATION);
}} }}
className="skip-to-console" className="skip-to-console"
> >
@@ -393,9 +395,9 @@ export default function Onboarding(): JSX.Element {
resetProgress(); resetProgress();
if (isOnboardingV3Enabled) { if (isOnboardingV3Enabled) {
history.push(ROUTES.GET_STARTED_WITH_CLOUD); safeNavigate(ROUTES.GET_STARTED_WITH_CLOUD);
} else { } else {
history.push(ROUTES.GET_STARTED); safeNavigate(ROUTES.GET_STARTED);
} }
}} }}
selectedModule={selectedModule} selectedModule={selectedModule}

View File

@@ -20,11 +20,11 @@ import {
messagingQueueKakfaSupportedDataSources, messagingQueueKakfaSupportedDataSources,
} from 'container/OnboardingContainer/utils/dataSourceUtils'; } from 'container/OnboardingContainer/utils/dataSourceUtils';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import { useSafeNavigate } from 'hooks/useSafeNavigate';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import { Blocks, Check } from 'lucide-react'; import { Blocks, Check } from 'lucide-react';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useHistory } from 'react-router-dom';
import { popupContainer } from 'utils/selectPopupContainer'; import { popupContainer } from 'utils/selectPopupContainer';
export interface DataSourceType { export interface DataSourceType {
@@ -37,7 +37,7 @@ export interface DataSourceType {
export default function DataSource(): JSX.Element { export default function DataSource(): JSX.Element {
const [form] = Form.useForm(); const [form] = Form.useForm();
const { t } = useTranslation(['common']); const { t } = useTranslation(['common']);
const history = useHistory(); const { safeNavigate } = useSafeNavigate();
const getStartedSource = useUrlQuery().get(QueryParams.getStartedSource); const getStartedSource = useUrlQuery().get(QueryParams.getStartedSource);
@@ -147,7 +147,7 @@ export default function DataSource(): JSX.Element {
dataSource: selectedDataSource?.name, dataSource: selectedDataSource?.name,
framework: selectedFramework, framework: selectedFramework,
}); });
history.push(ROUTES.INTEGRATIONS); safeNavigate(ROUTES.INTEGRATIONS);
}; };
return ( return (

View File

@@ -17,7 +17,7 @@ import ROUTES from 'constants/routes';
import { stepsMap } from 'container/OnboardingContainer/constants/stepsConfig'; import { stepsMap } from 'container/OnboardingContainer/constants/stepsConfig';
import { DataSourceType } from 'container/OnboardingContainer/Steps/DataSource/DataSource'; import { DataSourceType } from 'container/OnboardingContainer/Steps/DataSource/DataSource';
import { hasFrameworks } from 'container/OnboardingContainer/utils/dataSourceUtils'; import { hasFrameworks } from 'container/OnboardingContainer/utils/dataSourceUtils';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { isEmpty, isNull } from 'lodash-es'; import { isEmpty, isNull } from 'lodash-es';
import { UserPlus } from 'lucide-react'; import { UserPlus } from 'lucide-react';
import { SetStateAction, useState } from 'react'; import { SetStateAction, useState } from 'react';
@@ -83,6 +83,8 @@ export default function ModuleStepsContainer({
const [metaData, setMetaData] = useState<MetaDataProps[]>(defaultMetaData); const [metaData, setMetaData] = useState<MetaDataProps[]>(defaultMetaData);
const lastStepIndex = selectedModuleSteps.length - 1; const lastStepIndex = selectedModuleSteps.length - 1;
const { safeNavigate } = useSafeNavigate();
// eslint-disable-next-line sonarjs/cognitive-complexity // eslint-disable-next-line sonarjs/cognitive-complexity
const isValidForm = (): boolean => { const isValidForm = (): boolean => {
const { id: selectedModuleID } = selectedModule; const { id: selectedModuleID } = selectedModule;
@@ -153,15 +155,15 @@ export default function ModuleStepsContainer({
}); });
if (selectedModule.id === ModulesMap.APM) { if (selectedModule.id === ModulesMap.APM) {
history.push(ROUTES.APPLICATION); safeNavigate(ROUTES.APPLICATION);
} else if (selectedModule.id === ModulesMap.LogsManagement) { } else if (selectedModule.id === ModulesMap.LogsManagement) {
history.push(ROUTES.LOGS_EXPLORER); safeNavigate(ROUTES.LOGS_EXPLORER);
} else if (selectedModule.id === ModulesMap.InfrastructureMonitoring) { } else if (selectedModule.id === ModulesMap.InfrastructureMonitoring) {
history.push(ROUTES.APPLICATION); safeNavigate(ROUTES.APPLICATION);
} else if (selectedModule.id === ModulesMap.AwsMonitoring) { } else if (selectedModule.id === ModulesMap.AwsMonitoring) {
history.push(ROUTES.APPLICATION); safeNavigate(ROUTES.APPLICATION);
} else { } else {
history.push(ROUTES.APPLICATION); safeNavigate(ROUTES.APPLICATION);
} }
}; };
@@ -380,7 +382,7 @@ export default function ModuleStepsContainer({
}; };
const handleLogoClick = (): void => { const handleLogoClick = (): void => {
history.push('/home'); safeNavigate('/home');
}; };
return ( return (

View File

@@ -11,7 +11,7 @@ import { FeatureKeys } from 'constants/features';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { InviteTeamMembersProps } from 'container/OrganizationSettings/PendingInvitesContainer'; import { InviteTeamMembersProps } from 'container/OrganizationSettings/PendingInvitesContainer';
import { useNotifications } from 'hooks/useNotifications'; import { useNotifications } from 'hooks/useNotifications';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useMutation, useQuery } from 'react-query'; import { useMutation, useQuery } from 'react-query';
@@ -72,6 +72,7 @@ function OnboardingQuestionaire(): JSX.Element {
const [signozDetails, setSignozDetails] = useState<SignozDetails>( const [signozDetails, setSignozDetails] = useState<SignozDetails>(
INITIAL_SIGNOZ_DETAILS, INITIAL_SIGNOZ_DETAILS,
); );
const { safeNavigate } = useSafeNavigate();
const [ const [
optimiseSignozDetails, optimiseSignozDetails,
@@ -122,9 +123,9 @@ function OnboardingQuestionaire(): JSX.Element {
logEvent('Org Onboarding: Redirecting to Get Started', {}); logEvent('Org Onboarding: Redirecting to Get Started', {});
if (isOnboardingV3Enabled) { if (isOnboardingV3Enabled) {
history.push(ROUTES.GET_STARTED_WITH_CLOUD); safeNavigate(ROUTES.GET_STARTED_WITH_CLOUD);
} else { } else {
history.push(ROUTES.GET_STARTED); safeNavigate(ROUTES.GET_STARTED);
} }
}, },
onError: () => { onError: () => {

View File

@@ -16,7 +16,7 @@ import logEvent from 'api/common/logEvent';
import LaunchChatSupport from 'components/LaunchChatSupport/LaunchChatSupport'; import LaunchChatSupport from 'components/LaunchChatSupport/LaunchChatSupport';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import useDebouncedFn from 'hooks/useDebouncedFunction'; import useDebouncedFn from 'hooks/useDebouncedFunction';
import history from 'lib/history'; import { useSafeNavigate } from 'hooks/useSafeNavigate';
import { isEmpty } from 'lodash-es'; import { isEmpty } from 'lodash-es';
import { CheckIcon, Goal, UserPlus, X } from 'lucide-react'; import { CheckIcon, Goal, UserPlus, X } from 'lucide-react';
import { useAppContext } from 'providers/App/App'; import { useAppContext } from 'providers/App/App';
@@ -120,6 +120,7 @@ function OnboardingAddDataSource(): JSX.Element {
const question2Ref = useRef<HTMLDivElement | null>(null); const question2Ref = useRef<HTMLDivElement | null>(null);
const question3Ref = useRef<HTMLDivElement | null>(null); const question3Ref = useRef<HTMLDivElement | null>(null);
const configureProdRef = useRef<HTMLDivElement | null>(null); const configureProdRef = useRef<HTMLDivElement | null>(null);
const { safeNavigate } = useSafeNavigate();
const [showConfigureProduct, setShowConfigureProduct] = useState<boolean>( const [showConfigureProduct, setShowConfigureProduct] = useState<boolean>(
false, false,
@@ -417,22 +418,22 @@ function OnboardingAddDataSource(): JSX.Element {
} else if (step === 3) { } else if (step === 3) {
switch (selectedDataSource?.module) { switch (selectedDataSource?.module) {
case 'apm': case 'apm':
history.push(ROUTES.APPLICATION); safeNavigate(ROUTES.APPLICATION);
break; break;
case 'logs': case 'logs':
history.push(ROUTES.LOGS); safeNavigate(ROUTES.LOGS);
break; break;
case 'metrics': case 'metrics':
history.push(ROUTES.ALL_DASHBOARD); safeNavigate(ROUTES.ALL_DASHBOARD);
break; break;
case 'infra-monitoring-hosts': case 'infra-monitoring-hosts':
history.push(ROUTES.INFRASTRUCTURE_MONITORING_HOSTS); safeNavigate(ROUTES.INFRASTRUCTURE_MONITORING_HOSTS);
break; break;
case 'infra-monitoring-k8s': case 'infra-monitoring-k8s':
history.push(ROUTES.INFRASTRUCTURE_MONITORING_KUBERNETES); safeNavigate(ROUTES.INFRASTRUCTURE_MONITORING_KUBERNETES);
break; break;
default: default:
history.push(ROUTES.APPLICATION); safeNavigate(ROUTES.APPLICATION);
} }
} }
}; };
@@ -590,7 +591,7 @@ function OnboardingAddDataSource(): JSX.Element {
}, },
); );
history.push(ROUTES.HOME); safeNavigate(ROUTES.HOME);
}} }}
/> />
<Typography.Text>Get Started (2/4)</Typography.Text> <Typography.Text>Get Started (2/4)</Typography.Text>

View File

@@ -11,7 +11,7 @@ import { useAppContext } from 'providers/App/App';
import { useCallback, useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useQuery } from 'react-query'; import { useQuery } from 'react-query';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router';
import { useCopyToClipboard } from 'react-use'; import { useCopyToClipboard } from 'react-use';
import { PayloadProps } from 'types/api/user/getPendingInvites'; import { PayloadProps } from 'types/api/user/getPendingInvites';
import { ROLES } from 'types/roles'; import { ROLES } from 'types/roles';

View File

@@ -9,7 +9,7 @@ import { useIsDarkMode } from 'hooks/useDarkMode';
import useUrlQuery from 'hooks/useUrlQuery'; import useUrlQuery from 'hooks/useUrlQuery';
import { generateColor } from 'lib/uPlotLib/utils/generateColor'; import { generateColor } from 'lib/uPlotLib/utils/generateColor';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router';
import { TraceDetailFlamegraphURLProps } from 'types/api/trace/getTraceFlamegraph'; import { TraceDetailFlamegraphURLProps } from 'types/api/trace/getTraceFlamegraph';
import { Span } from 'types/api/trace/getTraceV2'; import { Span } from 'types/api/trace/getTraceV2';
@@ -34,7 +34,10 @@ function TraceFlamegraph(props: ITraceFlamegraphProps): JSX.Element {
traceFlamegraphStatsWidth, traceFlamegraphStatsWidth,
selectedSpan, selectedSpan,
} = props; } = props;
const { id: traceId } = useParams<TraceDetailFlamegraphURLProps>(); // Temp: Hard type casting for string | undefined
const {
id: traceId,
} = (useParams() as unknown) as TraceDetailFlamegraphURLProps;
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
const [firstSpanAtFetchLevel, setFirstSpanAtFetchLevel] = useState<string>( const [firstSpanAtFetchLevel, setFirstSpanAtFetchLevel] = useState<string>(
urlQuery.get('spanId') || '', urlQuery.get('spanId') || '',

Some files were not shown because too many files have changed in this diff Show More