2023-01-11 14:39:06 +05:30
|
|
|
import { ConfigProvider } from 'antd';
|
2023-09-24 15:05:11 +05:30
|
|
|
import getLocalStorageApi from 'api/browser/localstorage/get';
|
|
|
|
|
import setLocalStorageApi from 'api/browser/localstorage/set';
|
2024-07-23 16:32:45 +05:30
|
|
|
import logEvent from 'api/common/logEvent';
|
2021-08-26 11:50:47 +05:30
|
|
|
import NotFound from 'components/NotFound';
|
|
|
|
|
import Spinner from 'components/Spinner';
|
2023-09-12 19:20:14 +05:30
|
|
|
import { FeatureKeys } from 'constants/features';
|
2023-09-24 15:05:11 +05:30
|
|
|
import { LOCALSTORAGE } from 'constants/localStorage';
|
2023-09-12 19:20:14 +05:30
|
|
|
import ROUTES from 'constants/routes';
|
2021-10-20 09:24:55 +05:30
|
|
|
import AppLayout from 'container/AppLayout';
|
2023-11-17 20:08:04 +05:30
|
|
|
import useAnalytics from 'hooks/analytics/useAnalytics';
|
2024-02-06 14:17:27 +05:30
|
|
|
import { KeyboardHotkeysProvider } from 'hooks/hotkeys/useKeyboardHotkeys';
|
2024-05-29 19:29:53 +05:30
|
|
|
import { useIsDarkMode, useThemeConfig } from 'hooks/useDarkMode';
|
|
|
|
|
import { THEME_MODE } from 'hooks/useDarkMode/constant';
|
2023-09-12 19:20:14 +05:30
|
|
|
import useGetFeatureFlag from 'hooks/useGetFeatureFlag';
|
2023-10-16 23:57:44 +05:30
|
|
|
import useLicense, { LICENSE_PLAN_KEY } from 'hooks/useLicense';
|
2023-02-12 04:23:00 +01:00
|
|
|
import { NotificationProvider } from 'hooks/useNotifications';
|
2023-03-29 14:45:58 +05:30
|
|
|
import { ResourceProvider } from 'hooks/useResourceAttribute';
|
2021-09-23 15:43:43 +05:30
|
|
|
import history from 'lib/history';
|
2024-05-29 19:29:53 +05:30
|
|
|
import { identity, pick, pickBy } from 'lodash-es';
|
2024-06-24 16:48:25 +05:30
|
|
|
import posthog from 'posthog-js';
|
2024-09-04 21:26:10 +05:30
|
|
|
import AlertRuleProvider from 'providers/Alert';
|
2023-10-08 23:21:17 +05:30
|
|
|
import { DashboardProvider } from 'providers/Dashboard/Dashboard';
|
2023-03-24 13:39:31 +02:00
|
|
|
import { QueryBuilderProvider } from 'providers/QueryBuilder';
|
2023-09-19 15:09:28 +05:30
|
|
|
import { Suspense, useEffect, useState } from 'react';
|
2023-09-12 19:20:14 +05:30
|
|
|
import { useDispatch, useSelector } from 'react-redux';
|
2022-05-03 15:27:09 +05:30
|
|
|
import { Route, Router, Switch } from 'react-router-dom';
|
2023-09-12 19:20:14 +05:30
|
|
|
import { Dispatch } from 'redux';
|
|
|
|
|
import { AppState } from 'store/reducers';
|
|
|
|
|
import AppActions from 'types/actions';
|
|
|
|
|
import { UPDATE_FEATURE_FLAG_RESPONSE } from 'types/actions/app';
|
2023-10-17 16:54:37 +05:30
|
|
|
import AppReducer, { User } from 'types/reducer/app';
|
2023-10-19 11:52:58 +05:30
|
|
|
import { extractDomain, isCloudUser, isEECloudUser } from 'utils/app';
|
2021-08-23 11:38:25 +05:30
|
|
|
|
2022-05-03 15:27:09 +05:30
|
|
|
import PrivateRoute from './Private';
|
2024-01-24 14:18:15 +05:30
|
|
|
import defaultRoutes, {
|
|
|
|
|
AppRoutes,
|
|
|
|
|
LIST_LICENSES,
|
|
|
|
|
SUPPORT_ROUTE,
|
|
|
|
|
} from './routes';
|
2021-08-23 11:38:25 +05:30
|
|
|
|
2022-03-22 12:10:31 +05:30
|
|
|
function App(): JSX.Element {
|
2023-01-11 14:39:06 +05:30
|
|
|
const themeConfig = useThemeConfig();
|
2024-06-24 16:48:25 +05:30
|
|
|
const { data: licenseData } = useLicense();
|
2023-10-19 11:52:58 +05:30
|
|
|
const [routes, setRoutes] = useState<AppRoutes[]>(defaultRoutes);
|
2023-10-17 16:54:37 +05:30
|
|
|
const { role, isLoggedIn: isLoggedInState, user, org } = useSelector<
|
2023-09-12 19:20:14 +05:30
|
|
|
AppState,
|
|
|
|
|
AppReducer
|
|
|
|
|
>((state) => state.app);
|
|
|
|
|
|
|
|
|
|
const dispatch = useDispatch<Dispatch<AppActions>>();
|
|
|
|
|
|
2024-07-23 16:32:45 +05:30
|
|
|
const { trackPageView } = useAnalytics();
|
2023-11-17 20:08:04 +05:30
|
|
|
|
2023-09-19 15:09:28 +05:30
|
|
|
const { hostname, pathname } = window.location;
|
2023-09-13 15:00:14 +05:30
|
|
|
|
2023-10-17 16:54:37 +05:30
|
|
|
const isCloudUserVal = isCloudUser();
|
|
|
|
|
|
2024-05-29 19:29:53 +05:30
|
|
|
const isDarkMode = useIsDarkMode();
|
|
|
|
|
|
2023-09-12 19:20:14 +05:30
|
|
|
const featureResponse = useGetFeatureFlag((allFlags) => {
|
|
|
|
|
const isOnboardingEnabled =
|
|
|
|
|
allFlags.find((flag) => flag.name === FeatureKeys.ONBOARDING)?.active ||
|
|
|
|
|
false;
|
|
|
|
|
|
|
|
|
|
const isChatSupportEnabled =
|
|
|
|
|
allFlags.find((flag) => flag.name === FeatureKeys.CHAT_SUPPORT)?.active ||
|
|
|
|
|
false;
|
|
|
|
|
|
2024-08-14 20:50:35 +05:30
|
|
|
const isPremiumSupportEnabled =
|
|
|
|
|
allFlags.find((flag) => flag.name === FeatureKeys.PREMIUM_SUPPORT)?.active ||
|
|
|
|
|
false;
|
|
|
|
|
|
|
|
|
|
const showAddCreditCardModal =
|
|
|
|
|
!isPremiumSupportEnabled &&
|
|
|
|
|
!licenseData?.payload?.trialConvertedToSubscription;
|
|
|
|
|
|
2023-09-12 19:20:14 +05:30
|
|
|
dispatch({
|
|
|
|
|
type: UPDATE_FEATURE_FLAG_RESPONSE,
|
|
|
|
|
payload: {
|
|
|
|
|
featureFlag: allFlags,
|
|
|
|
|
refetch: featureResponse.refetch,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
2023-10-17 16:54:37 +05:30
|
|
|
if (!isOnboardingEnabled || !isCloudUserVal) {
|
2023-09-12 19:20:14 +05:30
|
|
|
const newRoutes = routes.filter(
|
2023-09-13 15:00:14 +05:30
|
|
|
(route) => route?.path !== ROUTES.GET_STARTED,
|
2023-09-12 19:20:14 +05:30
|
|
|
);
|
|
|
|
|
|
|
|
|
|
setRoutes(newRoutes);
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-14 20:50:35 +05:30
|
|
|
if (isLoggedInState && isChatSupportEnabled && !showAddCreditCardModal) {
|
2023-09-12 19:20:14 +05:30
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
window.Intercom('boot', {
|
|
|
|
|
app_id: process.env.INTERCOM_APP_ID,
|
|
|
|
|
email: user?.email || '',
|
|
|
|
|
name: user?.name || '',
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
2023-01-11 14:39:06 +05:30
|
|
|
|
2023-10-16 23:57:44 +05:30
|
|
|
const isOnBasicPlan =
|
2024-06-24 16:48:25 +05:30
|
|
|
licenseData?.payload?.licenses?.some(
|
2023-10-16 23:57:44 +05:30
|
|
|
(license) =>
|
|
|
|
|
license.isCurrent && license.planKey === LICENSE_PLAN_KEY.BASIC_PLAN,
|
2024-06-24 16:48:25 +05:30
|
|
|
) || licenseData?.payload?.licenses === null;
|
2023-10-16 23:57:44 +05:30
|
|
|
|
2023-10-17 16:54:37 +05:30
|
|
|
const enableAnalytics = (user: User): void => {
|
|
|
|
|
const orgName =
|
|
|
|
|
org && Array.isArray(org) && org.length > 0 ? org[0].name : '';
|
|
|
|
|
|
2023-10-26 01:58:24 +05:30
|
|
|
const { name, email } = user;
|
|
|
|
|
|
2023-10-17 16:54:37 +05:30
|
|
|
const identifyPayload = {
|
2023-10-26 01:58:24 +05:30
|
|
|
email,
|
|
|
|
|
name,
|
2023-10-17 16:54:37 +05:30
|
|
|
company_name: orgName,
|
|
|
|
|
role,
|
2023-10-26 01:58:24 +05:30
|
|
|
source: 'signoz-ui',
|
2023-10-17 16:54:37 +05:30
|
|
|
};
|
2023-10-26 01:58:24 +05:30
|
|
|
|
|
|
|
|
const sanitizedIdentifyPayload = pickBy(identifyPayload, identity);
|
|
|
|
|
const domain = extractDomain(email);
|
2023-10-17 16:54:37 +05:30
|
|
|
const hostNameParts = hostname.split('.');
|
|
|
|
|
|
|
|
|
|
const groupTraits = {
|
|
|
|
|
name: orgName,
|
|
|
|
|
tenant_id: hostNameParts[0],
|
|
|
|
|
data_region: hostNameParts[1],
|
|
|
|
|
tenant_url: hostname,
|
|
|
|
|
company_domain: domain,
|
2023-10-26 01:58:24 +05:30
|
|
|
source: 'signoz-ui',
|
2023-10-17 16:54:37 +05:30
|
|
|
};
|
|
|
|
|
|
2023-10-26 01:58:24 +05:30
|
|
|
window.analytics.identify(email, sanitizedIdentifyPayload);
|
2023-10-17 16:54:37 +05:30
|
|
|
window.analytics.group(domain, groupTraits);
|
2024-06-24 16:48:25 +05:30
|
|
|
|
|
|
|
|
posthog?.identify(email, {
|
|
|
|
|
email,
|
|
|
|
|
name,
|
|
|
|
|
orgName,
|
|
|
|
|
tenant_id: hostNameParts[0],
|
|
|
|
|
data_region: hostNameParts[1],
|
|
|
|
|
tenant_url: hostname,
|
|
|
|
|
company_domain: domain,
|
|
|
|
|
source: 'signoz-ui',
|
|
|
|
|
isPaidUser: !!licenseData?.payload?.trialConvertedToSubscription,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
posthog?.group('company', domain, {
|
|
|
|
|
name: orgName,
|
|
|
|
|
tenant_id: hostNameParts[0],
|
|
|
|
|
data_region: hostNameParts[1],
|
|
|
|
|
tenant_url: hostname,
|
|
|
|
|
company_domain: domain,
|
|
|
|
|
source: 'signoz-ui',
|
|
|
|
|
isPaidUser: !!licenseData?.payload?.trialConvertedToSubscription,
|
|
|
|
|
});
|
2023-10-17 16:54:37 +05:30
|
|
|
};
|
|
|
|
|
|
2023-09-19 15:09:28 +05:30
|
|
|
useEffect(() => {
|
2023-09-24 15:05:11 +05:30
|
|
|
const isIdentifiedUser = getLocalStorageApi(LOCALSTORAGE.IS_IDENTIFIED_USER);
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
isLoggedInState &&
|
|
|
|
|
user &&
|
|
|
|
|
user.userId &&
|
|
|
|
|
user.email &&
|
|
|
|
|
!isIdentifiedUser
|
|
|
|
|
) {
|
|
|
|
|
setLocalStorageApi(LOCALSTORAGE.IS_IDENTIFIED_USER, 'true');
|
2023-09-19 15:09:28 +05:30
|
|
|
}
|
2023-10-16 23:57:44 +05:30
|
|
|
|
2024-04-09 12:05:39 +05:30
|
|
|
if (
|
|
|
|
|
isOnBasicPlan ||
|
|
|
|
|
(isLoggedInState && role && role !== 'ADMIN') ||
|
|
|
|
|
!(isCloudUserVal || isEECloudUser())
|
|
|
|
|
) {
|
2023-10-16 23:57:44 +05:30
|
|
|
const newRoutes = routes.filter((route) => route?.path !== ROUTES.BILLING);
|
|
|
|
|
setRoutes(newRoutes);
|
|
|
|
|
}
|
2023-10-19 11:52:58 +05:30
|
|
|
|
|
|
|
|
if (isCloudUserVal || isEECloudUser()) {
|
|
|
|
|
const newRoutes = [...routes, SUPPORT_ROUTE];
|
|
|
|
|
|
2024-01-24 14:18:15 +05:30
|
|
|
setRoutes(newRoutes);
|
|
|
|
|
} else {
|
|
|
|
|
const newRoutes = [...routes, LIST_LICENSES];
|
|
|
|
|
|
2023-10-19 11:52:58 +05:30
|
|
|
setRoutes(newRoutes);
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-19 15:09:28 +05:30
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
2023-10-16 23:57:44 +05:30
|
|
|
}, [isLoggedInState, isOnBasicPlan, user]);
|
2023-09-19 15:09:28 +05:30
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
trackPageView(pathname);
|
2023-11-17 20:08:04 +05:30
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
2023-09-19 15:09:28 +05:30
|
|
|
}, [pathname]);
|
|
|
|
|
|
2024-05-29 19:29:53 +05:30
|
|
|
useEffect(() => {
|
2024-06-06 17:04:00 +05:30
|
|
|
if (user && user?.email && user?.userId && user?.name) {
|
|
|
|
|
try {
|
|
|
|
|
const isThemeAnalyticsSent = getLocalStorageApi(
|
|
|
|
|
LOCALSTORAGE.THEME_ANALYTICS_V1,
|
|
|
|
|
);
|
|
|
|
|
if (!isThemeAnalyticsSent) {
|
2024-07-23 16:32:45 +05:30
|
|
|
logEvent('Theme Analytics', {
|
2024-06-06 17:04:00 +05:30
|
|
|
theme: isDarkMode ? THEME_MODE.DARK : THEME_MODE.LIGHT,
|
|
|
|
|
user: pick(user, ['email', 'userId', 'name']),
|
|
|
|
|
org,
|
|
|
|
|
});
|
|
|
|
|
setLocalStorageApi(LOCALSTORAGE.THEME_ANALYTICS_V1, 'true');
|
|
|
|
|
}
|
|
|
|
|
} catch {
|
|
|
|
|
console.error('Failed to parse local storage theme analytics event');
|
2024-05-29 19:29:53 +05:30
|
|
|
}
|
|
|
|
|
}
|
2024-06-24 16:48:25 +05:30
|
|
|
|
|
|
|
|
if (isCloudUserVal && user && user.email) {
|
|
|
|
|
enableAnalytics(user);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-29 19:29:53 +05:30
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
2024-06-06 17:04:00 +05:30
|
|
|
}, [user]);
|
2024-05-29 19:29:53 +05:30
|
|
|
|
2021-12-02 18:53:05 +05:30
|
|
|
return (
|
2023-01-11 14:39:06 +05:30
|
|
|
<ConfigProvider theme={themeConfig}>
|
2023-03-29 14:45:58 +05:30
|
|
|
<Router history={history}>
|
|
|
|
|
<NotificationProvider>
|
2023-03-24 14:46:28 +02:00
|
|
|
<PrivateRoute>
|
2023-03-29 14:45:58 +05:30
|
|
|
<ResourceProvider>
|
|
|
|
|
<QueryBuilderProvider>
|
2023-10-08 23:21:17 +05:30
|
|
|
<DashboardProvider>
|
2024-02-06 14:17:27 +05:30
|
|
|
<KeyboardHotkeysProvider>
|
2024-09-04 21:26:10 +05:30
|
|
|
<AlertRuleProvider>
|
|
|
|
|
<AppLayout>
|
|
|
|
|
<Suspense fallback={<Spinner size="large" tip="Loading..." />}>
|
|
|
|
|
<Switch>
|
|
|
|
|
{routes.map(({ path, component, exact }) => (
|
|
|
|
|
<Route
|
|
|
|
|
key={`${path}`}
|
|
|
|
|
exact={exact}
|
|
|
|
|
path={path}
|
|
|
|
|
component={component}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
|
|
|
|
|
<Route path="*" component={NotFound} />
|
|
|
|
|
</Switch>
|
|
|
|
|
</Suspense>
|
|
|
|
|
</AppLayout>
|
|
|
|
|
</AlertRuleProvider>
|
2024-02-06 14:17:27 +05:30
|
|
|
</KeyboardHotkeysProvider>
|
2023-10-08 23:21:17 +05:30
|
|
|
</DashboardProvider>
|
2023-03-29 14:45:58 +05:30
|
|
|
</QueryBuilderProvider>
|
|
|
|
|
</ResourceProvider>
|
2023-03-24 14:46:28 +02:00
|
|
|
</PrivateRoute>
|
2023-03-29 14:45:58 +05:30
|
|
|
</NotificationProvider>
|
|
|
|
|
</Router>
|
2023-01-11 14:39:06 +05:30
|
|
|
</ConfigProvider>
|
2021-12-02 18:53:05 +05:30
|
|
|
);
|
2022-03-22 12:10:31 +05:30
|
|
|
}
|
2021-12-02 18:53:05 +05:30
|
|
|
|
2021-08-23 11:38:25 +05:30
|
|
|
export default App;
|