mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-01 04:32:03 +08:00
commit
ff392ba883
@ -137,7 +137,7 @@ services:
|
|||||||
condition: on-failure
|
condition: on-failure
|
||||||
|
|
||||||
query-service:
|
query-service:
|
||||||
image: signoz/query-service:0.25.1
|
image: signoz/query-service:0.25.2
|
||||||
command: ["-config=/root/config/prometheus.yml"]
|
command: ["-config=/root/config/prometheus.yml"]
|
||||||
# ports:
|
# ports:
|
||||||
# - "6060:6060" # pprof port
|
# - "6060:6060" # pprof port
|
||||||
@ -166,7 +166,7 @@ services:
|
|||||||
<<: *clickhouse-depend
|
<<: *clickhouse-depend
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
image: signoz/frontend:0.25.1
|
image: signoz/frontend:0.25.2
|
||||||
deploy:
|
deploy:
|
||||||
restart_policy:
|
restart_policy:
|
||||||
condition: on-failure
|
condition: on-failure
|
||||||
|
@ -153,7 +153,7 @@ services:
|
|||||||
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
|
# Notes for Maintainers/Contributors who will change Line Numbers of Frontend & Query-Section. Please Update Line Numbers in `./scripts/commentLinesForSetup.sh` & `./CONTRIBUTING.md`
|
||||||
|
|
||||||
query-service:
|
query-service:
|
||||||
image: signoz/query-service:${DOCKER_TAG:-0.25.1}
|
image: signoz/query-service:${DOCKER_TAG:-0.25.2}
|
||||||
container_name: query-service
|
container_name: query-service
|
||||||
command: ["-config=/root/config/prometheus.yml"]
|
command: ["-config=/root/config/prometheus.yml"]
|
||||||
# ports:
|
# ports:
|
||||||
@ -181,7 +181,7 @@ services:
|
|||||||
<<: *clickhouse-depend
|
<<: *clickhouse-depend
|
||||||
|
|
||||||
frontend:
|
frontend:
|
||||||
image: signoz/frontend:${DOCKER_TAG:-0.25.1}
|
image: signoz/frontend:${DOCKER_TAG:-0.25.2}
|
||||||
container_name: frontend
|
container_name: frontend
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
depends_on:
|
depends_on:
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
"overview_metrics": "Overview Metrics",
|
"overview_metrics": "Overview Metrics",
|
||||||
"dbcall_metrics": "Database Calls",
|
"dbcall_metrics": "Database Calls",
|
||||||
"external_metrics": "External Calls",
|
"external_metrics": "External Calls",
|
||||||
|
"pipeline": "Pipeline",
|
||||||
"pipelines": "Pipelines",
|
"pipelines": "Pipelines",
|
||||||
"archives": "Archives",
|
"archives": "Archives",
|
||||||
"logs_to_metrics": "Logs To Metrics"
|
"logs_to_metrics": "Logs To Metrics"
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"general": "General",
|
"general": "General",
|
||||||
"alert_channels": "Alert Channels",
|
"alert_channels": "Alert Channels",
|
||||||
"all_errors": "All Exceptions",
|
"all_errors": "All Exceptions",
|
||||||
|
"index_fields": "Index Fields",
|
||||||
"pipelines": "Pipelines"
|
"pipelines": "Pipelines"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
"overview_metrics": "Overview Metrics",
|
"overview_metrics": "Overview Metrics",
|
||||||
"dbcall_metrics": "Database Calls",
|
"dbcall_metrics": "Database Calls",
|
||||||
"external_metrics": "External Calls",
|
"external_metrics": "External Calls",
|
||||||
|
"pipeline": "Pipeline",
|
||||||
"pipelines": "Pipelines",
|
"pipelines": "Pipelines",
|
||||||
"archives": "Archives",
|
"archives": "Archives",
|
||||||
"logs_to_metrics": "Logs To Metrics"
|
"logs_to_metrics": "Logs To Metrics"
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"general": "General",
|
"general": "General",
|
||||||
"alert_channels": "Alert Channels",
|
"alert_channels": "Alert Channels",
|
||||||
"all_errors": "All Exceptions",
|
"all_errors": "All Exceptions",
|
||||||
|
"index_fields": "Index Fields",
|
||||||
"pipelines": "Pipelines"
|
"pipelines": "Pipelines"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,6 +133,11 @@ export const LicensePage = Loadable(
|
|||||||
() => import(/* webpackChunkName: "All Channels" */ 'pages/License'),
|
() => import(/* webpackChunkName: "All Channels" */ 'pages/License'),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const LogsIndexToFields = Loadable(
|
||||||
|
() =>
|
||||||
|
import(/* webpackChunkName: "LogsIndexToFields Page" */ 'pages/LogsSettings'),
|
||||||
|
);
|
||||||
|
|
||||||
export const PipelinePage = Loadable(
|
export const PipelinePage = Loadable(
|
||||||
() => import(/* webpackChunkName: "Pipelines" */ 'pages/Pipelines'),
|
() => import(/* webpackChunkName: "Pipelines" */ 'pages/Pipelines'),
|
||||||
);
|
);
|
||||||
|
@ -17,6 +17,7 @@ import {
|
|||||||
Login,
|
Login,
|
||||||
Logs,
|
Logs,
|
||||||
LogsExplorer,
|
LogsExplorer,
|
||||||
|
LogsIndexToFields,
|
||||||
MySettings,
|
MySettings,
|
||||||
NewDashboardPage,
|
NewDashboardPage,
|
||||||
OrganizationSettings,
|
OrganizationSettings,
|
||||||
@ -44,6 +45,13 @@ const routes: AppRoutes[] = [
|
|||||||
isPrivate: false,
|
isPrivate: false,
|
||||||
key: 'SIGN_UP',
|
key: 'SIGN_UP',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
component: LogsIndexToFields,
|
||||||
|
path: ROUTES.LOGS_INDEX_FIELDS,
|
||||||
|
exact: true,
|
||||||
|
isPrivate: true,
|
||||||
|
key: 'LOGS_INDEX_FIELDS',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
component: ServicesTablePage,
|
component: ServicesTablePage,
|
||||||
path: ROUTES.APPLICATION,
|
path: ROUTES.APPLICATION,
|
||||||
|
@ -3,6 +3,7 @@ import { createMemoryHistory } from 'history';
|
|||||||
import { Router } from 'react-router-dom';
|
import { Router } from 'react-router-dom';
|
||||||
|
|
||||||
import RouteTab from './index';
|
import RouteTab from './index';
|
||||||
|
import { RouteTabProps } from './types';
|
||||||
|
|
||||||
function DummyComponent1(): JSX.Element {
|
function DummyComponent1(): JSX.Element {
|
||||||
return <div>Dummy Component 1</div>;
|
return <div>Dummy Component 1</div>;
|
||||||
@ -11,16 +12,18 @@ function DummyComponent2(): JSX.Element {
|
|||||||
return <div>Dummy Component 2</div>;
|
return <div>Dummy Component 2</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const testRoutes = [
|
const testRoutes: RouteTabProps['routes'] = [
|
||||||
{
|
{
|
||||||
name: 'Tab1',
|
name: 'Tab1',
|
||||||
route: '/tab1',
|
route: '/tab1',
|
||||||
Component: DummyComponent1,
|
Component: DummyComponent1,
|
||||||
|
key: 'Tab1',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Tab2',
|
name: 'Tab2',
|
||||||
route: '/tab2',
|
route: '/tab2',
|
||||||
Component: DummyComponent2,
|
Component: DummyComponent2,
|
||||||
|
key: 'Tab2',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Tabs, TabsProps } from 'antd';
|
import { Tabs, TabsProps } from 'antd';
|
||||||
import { History } from 'history';
|
|
||||||
|
import { RouteTabProps } from './types';
|
||||||
|
|
||||||
function RouteTab({
|
function RouteTab({
|
||||||
routes,
|
routes,
|
||||||
@ -13,16 +14,16 @@ function RouteTab({
|
|||||||
onChangeHandler();
|
onChangeHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedRoute = routes.find((e) => e.name === activeRoute);
|
const selectedRoute = routes.find((e) => e.key === activeRoute);
|
||||||
|
|
||||||
if (selectedRoute) {
|
if (selectedRoute) {
|
||||||
history.push(selectedRoute.route);
|
history.push(selectedRoute.route);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const items = routes.map(({ Component, name, route }) => ({
|
const items = routes.map(({ Component, name, route, key }) => ({
|
||||||
label: name,
|
label: name,
|
||||||
key: name,
|
key,
|
||||||
tabKey: route,
|
tabKey: route,
|
||||||
children: <Component />,
|
children: <Component />,
|
||||||
}));
|
}));
|
||||||
@ -32,6 +33,7 @@ function RouteTab({
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
destroyInactiveTabPane
|
destroyInactiveTabPane
|
||||||
activeKey={activeKey}
|
activeKey={activeKey}
|
||||||
|
defaultActiveKey={activeKey}
|
||||||
animated
|
animated
|
||||||
items={items}
|
items={items}
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||||
@ -40,17 +42,6 @@ function RouteTab({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RouteTabProps {
|
|
||||||
routes: {
|
|
||||||
name: string;
|
|
||||||
route: string;
|
|
||||||
Component: () => JSX.Element;
|
|
||||||
}[];
|
|
||||||
activeKey: TabsProps['activeKey'];
|
|
||||||
onChangeHandler?: VoidFunction;
|
|
||||||
history: History<unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
RouteTab.defaultProps = {
|
RouteTab.defaultProps = {
|
||||||
onChangeHandler: undefined,
|
onChangeHandler: undefined,
|
||||||
};
|
};
|
||||||
|
14
frontend/src/components/RouteTab/types.ts
Normal file
14
frontend/src/components/RouteTab/types.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { TabsProps } from 'antd';
|
||||||
|
import { History } from 'history';
|
||||||
|
|
||||||
|
export interface RouteTabProps {
|
||||||
|
routes: {
|
||||||
|
name: React.ReactNode;
|
||||||
|
route: string;
|
||||||
|
Component: () => JSX.Element;
|
||||||
|
key: string;
|
||||||
|
}[];
|
||||||
|
activeKey: TabsProps['activeKey'];
|
||||||
|
onChangeHandler?: VoidFunction;
|
||||||
|
history: History<unknown>;
|
||||||
|
}
|
@ -32,6 +32,8 @@ const ROUTES = {
|
|||||||
HOME_PAGE: '/',
|
HOME_PAGE: '/',
|
||||||
PASSWORD_RESET: '/password-reset',
|
PASSWORD_RESET: '/password-reset',
|
||||||
LIST_LICENSES: '/licenses',
|
LIST_LICENSES: '/licenses',
|
||||||
|
LOGS_INDEX_FIELDS: '/logs-explorer/index-fields',
|
||||||
|
LOGS_PIPELINE: '/logs-explorer/pipeline',
|
||||||
TRACE_EXPLORER: '/trace-explorer',
|
TRACE_EXPLORER: '/trace-explorer',
|
||||||
PIPELINES: '/pipelines',
|
PIPELINES: '/pipelines',
|
||||||
};
|
};
|
||||||
|
@ -173,6 +173,7 @@ function GridCardGraph({
|
|||||||
allowClone={allowClone}
|
allowClone={allowClone}
|
||||||
allowDelete={allowDelete}
|
allowDelete={allowDelete}
|
||||||
allowEdit={allowEdit}
|
allowEdit={allowEdit}
|
||||||
|
onClickHandler={onClickHandler}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
7
frontend/src/container/LogsIndexToFields/index.tsx
Normal file
7
frontend/src/container/LogsIndexToFields/index.tsx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { Typography } from 'antd';
|
||||||
|
|
||||||
|
function LogsIndexToFields(): JSX.Element {
|
||||||
|
return <Typography>LogsIndexToFields</Typography>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LogsIndexToFields;
|
19
frontend/src/pages/AlertChannelCreate/config.tsx
Normal file
19
frontend/src/pages/AlertChannelCreate/config.tsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import ROUTES from 'constants/routes';
|
||||||
|
import CreateAlertChannels from 'container/CreateAlertChannels';
|
||||||
|
import GeneralSettings from 'container/GeneralSettings';
|
||||||
|
import { t } from 'i18next';
|
||||||
|
|
||||||
|
export const alertsRoutesConfig = [
|
||||||
|
{
|
||||||
|
Component: GeneralSettings,
|
||||||
|
name: t('routes.general'),
|
||||||
|
route: ROUTES.SETTINGS,
|
||||||
|
key: ROUTES.SETTINGS,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Component: (): JSX.Element => <CreateAlertChannels preType="slack" />,
|
||||||
|
name: t('routes.alert_channels'),
|
||||||
|
route: ROUTES.ALL_CHANNELS,
|
||||||
|
key: ROUTES.ALL_CHANNELS,
|
||||||
|
},
|
||||||
|
];
|
@ -1,35 +1,17 @@
|
|||||||
/* eslint-disable react/no-unstable-nested-components */
|
|
||||||
import RouteTab from 'components/RouteTab';
|
import RouteTab from 'components/RouteTab';
|
||||||
import ROUTES from 'constants/routes';
|
|
||||||
import CreateAlertChannels from 'container/CreateAlertChannels';
|
|
||||||
import GeneralSettings from 'container/GeneralSettings';
|
|
||||||
import history from 'lib/history';
|
import history from 'lib/history';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { alertsRoutesConfig } from './config';
|
||||||
|
|
||||||
function SettingsPage(): JSX.Element {
|
function SettingsPage(): JSX.Element {
|
||||||
const pathName = history.location.pathname;
|
const { pathname } = useLocation();
|
||||||
const { t } = useTranslation();
|
|
||||||
return (
|
return (
|
||||||
<RouteTab
|
<RouteTab
|
||||||
history={history}
|
history={history}
|
||||||
{...{
|
routes={alertsRoutesConfig}
|
||||||
routes: [
|
activeKey={pathname}
|
||||||
{
|
|
||||||
Component: GeneralSettings,
|
|
||||||
name: t('routes.general'),
|
|
||||||
route: ROUTES.SETTINGS,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Component: (): JSX.Element => <CreateAlertChannels preType="slack" />,
|
|
||||||
name: t('routes.alert_channels'),
|
|
||||||
route: ROUTES.ALL_CHANNELS,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
activeKey:
|
|
||||||
pathName === ROUTES.SETTINGS
|
|
||||||
? t('routes.general')
|
|
||||||
: t('routes.alert_channels'),
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
12
frontend/src/pages/AllErrors/config.ts
Normal file
12
frontend/src/pages/AllErrors/config.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import ROUTES from 'constants/routes';
|
||||||
|
import AllErrorsContainer from 'container/AllError';
|
||||||
|
import { t } from 'i18next';
|
||||||
|
|
||||||
|
export const routes = [
|
||||||
|
{
|
||||||
|
Component: AllErrorsContainer,
|
||||||
|
name: t('routes.all_errors'),
|
||||||
|
route: ROUTES.ALL_ERROR,
|
||||||
|
key: ROUTES.ALL_ERROR,
|
||||||
|
},
|
||||||
|
];
|
@ -1,33 +1,17 @@
|
|||||||
import RouteTab from 'components/RouteTab';
|
import RouteTab from 'components/RouteTab';
|
||||||
import ROUTES from 'constants/routes';
|
|
||||||
import AllErrorsContainer from 'container/AllError';
|
|
||||||
import ResourceAttributesFilter from 'container/ResourceAttributesFilter';
|
import ResourceAttributesFilter from 'container/ResourceAttributesFilter';
|
||||||
import history from 'lib/history';
|
import history from 'lib/history';
|
||||||
import { useMemo } from 'react';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
import { routes } from './config';
|
||||||
|
|
||||||
function AllErrors(): JSX.Element {
|
function AllErrors(): JSX.Element {
|
||||||
const { t } = useTranslation();
|
const { pathname } = useLocation();
|
||||||
|
|
||||||
const routes = useMemo(
|
|
||||||
() => [
|
|
||||||
{
|
|
||||||
Component: AllErrorsContainer,
|
|
||||||
name: t('routes.all_errors'),
|
|
||||||
route: ROUTES.ALL_ERROR,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[t],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ResourceAttributesFilter />
|
<ResourceAttributesFilter />
|
||||||
<RouteTab
|
<RouteTab routes={routes} activeKey={pathname} history={history} />
|
||||||
routes={routes}
|
|
||||||
activeKey={t('routes.all_errors')}
|
|
||||||
history={history}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
14
frontend/src/pages/LogsSettings/components/TabLabel.tsx
Normal file
14
frontend/src/pages/LogsSettings/components/TabLabel.tsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { Typography } from 'antd';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { TableLabel } from '../types';
|
||||||
|
|
||||||
|
function TabLabel({ routeKey, label }: TableLabel): JSX.Element {
|
||||||
|
const { pathname } = useLocation();
|
||||||
|
|
||||||
|
if (pathname === routeKey) return <Typography.Link>{label}</Typography.Link>;
|
||||||
|
|
||||||
|
return <Typography>{label}</Typography>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TabLabel;
|
21
frontend/src/pages/LogsSettings/config.tsx
Normal file
21
frontend/src/pages/LogsSettings/config.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { RouteTabProps } from 'components/RouteTab/types';
|
||||||
|
import ROUTES from 'constants/routes';
|
||||||
|
import LogsIndexToFields from 'container/LogsIndexToFields';
|
||||||
|
import { TFunction } from 'react-i18next';
|
||||||
|
|
||||||
|
import TabLabel from './components/TabLabel';
|
||||||
|
import { TABS_KEY, TABS_TITLE } from './constant';
|
||||||
|
|
||||||
|
export const getLogsSettingsRoute = (t: TFunction): RouteTabProps['routes'] => [
|
||||||
|
{
|
||||||
|
Component: LogsIndexToFields,
|
||||||
|
name: (
|
||||||
|
<TabLabel
|
||||||
|
label={TABS_TITLE(t)[TABS_KEY.LOGS_INDEX_FIELDS]}
|
||||||
|
routeKey={ROUTES.LOGS_INDEX_FIELDS}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
route: ROUTES.LOGS_INDEX_FIELDS,
|
||||||
|
key: ROUTES.LOGS_INDEX_FIELDS,
|
||||||
|
},
|
||||||
|
];
|
11
frontend/src/pages/LogsSettings/constant.ts
Normal file
11
frontend/src/pages/LogsSettings/constant.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { TFunction } from 'i18next';
|
||||||
|
|
||||||
|
export const TABS_KEY = {
|
||||||
|
LOGS_INDEX_FIELDS: 'LOGS_INDEX_FIELDS',
|
||||||
|
LOGS_PIPELINE: 'LOGS_PIPELINE',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TABS_TITLE = (t: TFunction): Record<string, string> => ({
|
||||||
|
[TABS_KEY.LOGS_INDEX_FIELDS]: t('routes.index_fields'),
|
||||||
|
[TABS_KEY.LOGS_PIPELINE]: t('routes.pipeline'),
|
||||||
|
});
|
18
frontend/src/pages/LogsSettings/index.tsx
Normal file
18
frontend/src/pages/LogsSettings/index.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import RouteTab from 'components/RouteTab';
|
||||||
|
import history from 'lib/history';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { getLogsSettingsRoute } from './config';
|
||||||
|
|
||||||
|
function LogsSettings(): JSX.Element {
|
||||||
|
const { pathname } = useLocation();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const routes = useMemo(() => getLogsSettingsRoute(t), [t]);
|
||||||
|
|
||||||
|
return <RouteTab activeKey={pathname} routes={routes} history={history} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LogsSettings;
|
1
frontend/src/pages/LogsSettings/types.ts
Normal file
1
frontend/src/pages/LogsSettings/types.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type TableLabel = { routeKey: string; label: string };
|
@ -24,6 +24,7 @@ function MetricsApplication(): JSX.Element {
|
|||||||
route: `${generatePath(ROUTES.SERVICE_METRICS, {
|
route: `${generatePath(ROUTES.SERVICE_METRICS, {
|
||||||
servicename,
|
servicename,
|
||||||
})}?tab=${MetricsApplicationTab.OVER_METRICS}`,
|
})}?tab=${MetricsApplicationTab.OVER_METRICS}`,
|
||||||
|
key: MetricsApplicationTab.OVER_METRICS,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Component: DBCall,
|
Component: DBCall,
|
||||||
@ -31,6 +32,7 @@ function MetricsApplication(): JSX.Element {
|
|||||||
route: `${generatePath(ROUTES.SERVICE_METRICS, {
|
route: `${generatePath(ROUTES.SERVICE_METRICS, {
|
||||||
servicename,
|
servicename,
|
||||||
})}?tab=${MetricsApplicationTab.DB_CALL_METRICS}`,
|
})}?tab=${MetricsApplicationTab.DB_CALL_METRICS}`,
|
||||||
|
key: MetricsApplicationTab.DB_CALL_METRICS,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Component: External,
|
Component: External,
|
||||||
@ -38,6 +40,7 @@ function MetricsApplication(): JSX.Element {
|
|||||||
route: `${generatePath(ROUTES.SERVICE_METRICS, {
|
route: `${generatePath(ROUTES.SERVICE_METRICS, {
|
||||||
servicename,
|
servicename,
|
||||||
})}?tab=${MetricsApplicationTab.EXTERNAL_METRICS}`,
|
})}?tab=${MetricsApplicationTab.EXTERNAL_METRICS}`,
|
||||||
|
key: MetricsApplicationTab.EXTERNAL_METRICS,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[servicename],
|
[servicename],
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import useUrlQuery from 'hooks/useUrlQuery';
|
import useUrlQuery from 'hooks/useUrlQuery';
|
||||||
|
|
||||||
import { TAB_KEY_VS_LABEL } from './types';
|
|
||||||
import { getMetricsApplicationKey } from './utils';
|
import { getMetricsApplicationKey } from './utils';
|
||||||
|
|
||||||
const useMetricsApplicationTabKey = (): string => {
|
const useMetricsApplicationTabKey = (): string => {
|
||||||
@ -8,7 +7,7 @@ const useMetricsApplicationTabKey = (): string => {
|
|||||||
|
|
||||||
const tab = urlParams.get('tab');
|
const tab = urlParams.get('tab');
|
||||||
|
|
||||||
return TAB_KEY_VS_LABEL[getMetricsApplicationKey(tab)];
|
return getMetricsApplicationKey(tab);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useMetricsApplicationTabKey;
|
export default useMetricsApplicationTabKey;
|
||||||
|
30
frontend/src/pages/Settings/config.ts
Normal file
30
frontend/src/pages/Settings/config.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { RouteTabProps } from 'components/RouteTab/types';
|
||||||
|
import ROUTES from 'constants/routes';
|
||||||
|
import AlertChannels from 'container/AllAlertChannels';
|
||||||
|
import GeneralSettings from 'container/GeneralSettings';
|
||||||
|
import OrganizationSettings from 'container/OrganizationSettings';
|
||||||
|
import { TFunction } from 'i18next';
|
||||||
|
|
||||||
|
export const commonRoutes = (t: TFunction): RouteTabProps['routes'] => [
|
||||||
|
{
|
||||||
|
Component: GeneralSettings,
|
||||||
|
name: t('routes:general').toString(),
|
||||||
|
route: ROUTES.SETTINGS,
|
||||||
|
key: ROUTES.SETTINGS,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Component: AlertChannels,
|
||||||
|
name: t('routes:alert_channels').toString(),
|
||||||
|
route: ROUTES.ALL_CHANNELS,
|
||||||
|
key: ROUTES.ALL_CHANNELS,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const organizationSettings = (t: TFunction): RouteTabProps['routes'] => [
|
||||||
|
{
|
||||||
|
Component: OrganizationSettings,
|
||||||
|
name: t('routes:organization_settings').toString(),
|
||||||
|
route: ROUTES.ORG_SETTINGS,
|
||||||
|
key: ROUTES.ORG_SETTINGS,
|
||||||
|
},
|
||||||
|
];
|
@ -1,62 +1,30 @@
|
|||||||
import RouteTab from 'components/RouteTab';
|
import RouteTab from 'components/RouteTab';
|
||||||
import ROUTES from 'constants/routes';
|
|
||||||
import AlertChannels from 'container/AllAlertChannels';
|
|
||||||
import GeneralSettings from 'container/GeneralSettings';
|
|
||||||
import OrganizationSettings from 'container/OrganizationSettings';
|
|
||||||
import useComponentPermission from 'hooks/useComponentPermission';
|
import useComponentPermission from 'hooks/useComponentPermission';
|
||||||
import history from 'lib/history';
|
import history from 'lib/history';
|
||||||
|
import { useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import AppReducer from 'types/reducer/app';
|
import AppReducer from 'types/reducer/app';
|
||||||
|
|
||||||
|
import { getRoutes } from './utils';
|
||||||
|
|
||||||
function SettingsPage(): JSX.Element {
|
function SettingsPage(): JSX.Element {
|
||||||
const pathName = history.location.pathname;
|
const { pathname } = useLocation();
|
||||||
const { t } = useTranslation(['routes']);
|
|
||||||
const { role } = useSelector<AppState, AppReducer>((state) => state.app);
|
const { role } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||||
const [currentOrgSettings] = useComponentPermission(
|
const [isCurrentOrgSettings] = useComponentPermission(
|
||||||
['current_org_settings'],
|
['current_org_settings'],
|
||||||
role,
|
role,
|
||||||
);
|
);
|
||||||
|
const { t } = useTranslation(['routes']);
|
||||||
|
|
||||||
const getActiveKey = (pathname: string): string => {
|
const routes = useMemo(() => getRoutes(isCurrentOrgSettings, t), [
|
||||||
if (pathname === ROUTES.SETTINGS) {
|
isCurrentOrgSettings,
|
||||||
return t('general');
|
t,
|
||||||
}
|
]);
|
||||||
if (pathname === ROUTES.ORG_SETTINGS && currentOrgSettings) {
|
|
||||||
return t('organization_settings');
|
|
||||||
}
|
|
||||||
return t('alert_channels');
|
|
||||||
};
|
|
||||||
|
|
||||||
const common = [
|
return <RouteTab routes={routes} activeKey={pathname} history={history} />;
|
||||||
{
|
|
||||||
Component: GeneralSettings,
|
|
||||||
name: t('general'),
|
|
||||||
route: ROUTES.SETTINGS,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Component: AlertChannels,
|
|
||||||
name: t('alert_channels'),
|
|
||||||
route: ROUTES.ALL_CHANNELS,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
if (currentOrgSettings) {
|
|
||||||
common.push({
|
|
||||||
Component: OrganizationSettings,
|
|
||||||
name: t('organization_settings'),
|
|
||||||
route: ROUTES.ORG_SETTINGS,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<RouteTab
|
|
||||||
routes={common}
|
|
||||||
activeKey={getActiveKey(pathName)}
|
|
||||||
history={history}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SettingsPage;
|
export default SettingsPage;
|
||||||
|
17
frontend/src/pages/Settings/utils.ts
Normal file
17
frontend/src/pages/Settings/utils.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { RouteTabProps } from 'components/RouteTab/types';
|
||||||
|
import { TFunction } from 'i18next';
|
||||||
|
|
||||||
|
import { commonRoutes, organizationSettings } from './config';
|
||||||
|
|
||||||
|
export const getRoutes = (
|
||||||
|
isCurrentOrgSettings: boolean,
|
||||||
|
t: TFunction,
|
||||||
|
): RouteTabProps['routes'] => {
|
||||||
|
let common = commonRoutes(t);
|
||||||
|
|
||||||
|
if (isCurrentOrgSettings) {
|
||||||
|
common = [...common, ...organizationSettings(t)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return common;
|
||||||
|
};
|
@ -74,6 +74,8 @@ export const routePermission: Record<keyof typeof ROUTES, ROLES[]> = {
|
|||||||
LOGS: ['ADMIN', 'EDITOR', 'VIEWER'],
|
LOGS: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
LOGS_EXPLORER: ['ADMIN', 'EDITOR', 'VIEWER'],
|
LOGS_EXPLORER: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
LIST_LICENSES: ['ADMIN'],
|
LIST_LICENSES: ['ADMIN'],
|
||||||
|
LOGS_INDEX_FIELDS: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
|
LOGS_PIPELINE: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
TRACE_EXPLORER: ['ADMIN', 'EDITOR', 'VIEWER'],
|
TRACE_EXPLORER: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
PIPELINES: ['ADMIN', 'EDITOR', 'VIEWER'],
|
PIPELINES: ['ADMIN', 'EDITOR', 'VIEWER'],
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user