mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-11 22:39:01 +08:00
feat: antd is updated from v4 to v5 (#2012)
* feat: v5 is in progress * feat: antdv5 is updated * fix: build is fixed * fix: default config is over written by custom one * chore: onchange handler is updated * chore: overflow is hidden in the layout * Update index.tsx * fix: import is fixed * chore: un used import is fixed * fix: dark mode is updated in service map * fix: config dropdown is updated * fix: logs types is updated * fix: copy clipboard notification is updated * chore: layout changes are updated * chore: colors is updated * chore: action width is updated Co-authored-by: Pranay Prateek <pranay@signoz.io> Co-authored-by: Vishal Sharma <makeavish786@gmail.com>
This commit is contained in:
parent
ca77820e9d
commit
2f5908a3dd
@ -27,8 +27,8 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^6.0.0",
|
||||
"@ant-design/icons": "^4.6.2",
|
||||
"@ant-design/colors": "6.0.0",
|
||||
"@ant-design/icons": "4.8.0",
|
||||
"@grafana/data": "^8.4.3",
|
||||
"@monaco-editor/react": "^4.3.1",
|
||||
"@testing-library/jest-dom": "^5.11.4",
|
||||
@ -36,7 +36,7 @@
|
||||
"@testing-library/user-event": "^12.1.10",
|
||||
"@welldone-software/why-did-you-render": "^6.2.1",
|
||||
"@xstate/react": "^3.0.0",
|
||||
"antd": "4.19.2",
|
||||
"antd": "5.0.5",
|
||||
"axios": "^0.21.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-jest": "^26.6.0",
|
||||
|
10
frontend/public/css/antd.dark.min.css
vendored
10
frontend/public/css/antd.dark.min.css
vendored
File diff suppressed because one or more lines are too long
10
frontend/public/css/antd.min.css
vendored
10
frontend/public/css/antd.min.css
vendored
File diff suppressed because one or more lines are too long
@ -1,6 +1,8 @@
|
||||
import { ConfigProvider } from 'antd';
|
||||
import NotFound from 'components/NotFound';
|
||||
import Spinner from 'components/Spinner';
|
||||
import AppLayout from 'container/AppLayout';
|
||||
import { useThemeConfig } from 'hooks/useDarkMode';
|
||||
import history from 'lib/history';
|
||||
import React, { Suspense } from 'react';
|
||||
import { Route, Router, Switch } from 'react-router-dom';
|
||||
@ -9,29 +11,31 @@ import PrivateRoute from './Private';
|
||||
import routes from './routes';
|
||||
|
||||
function App(): JSX.Element {
|
||||
const themeConfig = useThemeConfig();
|
||||
|
||||
return (
|
||||
<Router history={history}>
|
||||
<PrivateRoute>
|
||||
<AppLayout>
|
||||
<Suspense fallback={<Spinner size="large" tip="Loading..." />}>
|
||||
<Switch>
|
||||
{routes.map(({ path, component, exact }) => {
|
||||
return (
|
||||
<ConfigProvider theme={themeConfig}>
|
||||
<Router history={history}>
|
||||
<PrivateRoute>
|
||||
<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>
|
||||
</PrivateRoute>
|
||||
</Router>
|
||||
<Route path="*" component={NotFound} />
|
||||
</Switch>
|
||||
</Suspense>
|
||||
</AppLayout>
|
||||
</PrivateRoute>
|
||||
</Router>
|
||||
</ConfigProvider>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,9 +0,0 @@
|
||||
import generatePicker from 'antd/es/date-picker/generatePicker';
|
||||
import { Dayjs } from 'dayjs';
|
||||
// included in antd
|
||||
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||
import dayjsGenerateConfig from 'rc-picker/lib/generate/dayjs';
|
||||
|
||||
const DatePicker = generatePicker<Dayjs>(dayjsGenerateConfig);
|
||||
|
||||
export default DatePicker;
|
@ -1,8 +1,6 @@
|
||||
import MEditor, { EditorProps } from '@monaco-editor/react';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
function Editor({
|
||||
value,
|
||||
@ -12,7 +10,7 @@ function Editor({
|
||||
height,
|
||||
options,
|
||||
}: MEditorProps): JSX.Element {
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
return (
|
||||
<MEditor
|
||||
theme={isDarkMode ? 'vs-dark' : 'vs-light'}
|
||||
|
@ -23,10 +23,8 @@ import {
|
||||
} from 'chart.js';
|
||||
import * as chartjsAdapter from 'chartjs-adapter-date-fns';
|
||||
import annotationPlugin from 'chartjs-plugin-annotation';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React, { useCallback, useEffect, useRef } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
import { hasData } from './hasData';
|
||||
import { legend } from './Plugin';
|
||||
@ -67,8 +65,9 @@ function Graph({
|
||||
staticLine,
|
||||
containerHeight,
|
||||
}: GraphProps): JSX.Element {
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const chartRef = useRef<HTMLCanvasElement>(null);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const currentTheme = isDarkMode ? 'dark' : 'light';
|
||||
const xAxisTimeUnit = useXAxisTimeUnit(data); // Computes the relevant time unit for x axis by analyzing the time stamp data
|
||||
|
||||
|
@ -1,29 +1,27 @@
|
||||
import { Popover } from 'antd';
|
||||
import React from 'react';
|
||||
import { notification, Popover } from 'antd';
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import { useCopyToClipboard } from 'react-use';
|
||||
|
||||
interface CopyClipboardHOCProps {
|
||||
textToCopy: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
function CopyClipboardHOC({
|
||||
textToCopy,
|
||||
children,
|
||||
}: CopyClipboardHOCProps): JSX.Element {
|
||||
const [, setCopy] = useCopyToClipboard();
|
||||
const [value, setCopy] = useCopyToClipboard();
|
||||
|
||||
useEffect(() => {
|
||||
if (value.value) {
|
||||
notification.success({
|
||||
message: 'Copied to clipboard',
|
||||
});
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
const onClick = useCallback((): void => {
|
||||
setCopy(textToCopy);
|
||||
}, [setCopy, textToCopy]);
|
||||
|
||||
return (
|
||||
<span
|
||||
style={{
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
onClick={(): void => setCopy(textToCopy)}
|
||||
onKeyDown={(): void => setCopy(textToCopy)}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
>
|
||||
<span onClick={onClick} onKeyDown={onClick} role="button" tabIndex={0}>
|
||||
<Popover
|
||||
placement="top"
|
||||
content={<span style={{ fontSize: '0.9rem' }}>Copy to clipboard</span>}
|
||||
@ -34,4 +32,9 @@ function CopyClipboardHOC({
|
||||
);
|
||||
}
|
||||
|
||||
interface CopyClipboardHOCProps {
|
||||
textToCopy: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export default CopyClipboardHOC;
|
||||
|
@ -14,7 +14,7 @@ import { ILogsReducer } from 'types/reducer/logs';
|
||||
|
||||
import AddToQueryHOC from '../AddToQueryHOC';
|
||||
import CopyClipboardHOC from '../CopyClipboardHOC';
|
||||
import { Container } from './styles';
|
||||
import { Container, Text, TextContainer } from './styles';
|
||||
import { isValidLogField } from './util';
|
||||
|
||||
interface LogFieldProps {
|
||||
@ -23,21 +23,17 @@ interface LogFieldProps {
|
||||
}
|
||||
function LogGeneralField({ fieldKey, fieldValue }: LogFieldProps): JSX.Element {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
overflow: 'hidden',
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
<Typography.Text type="secondary">{fieldKey}</Typography.Text>
|
||||
<TextContainer>
|
||||
<Text ellipsis type="secondary">
|
||||
{fieldKey}
|
||||
</Text>
|
||||
<CopyClipboardHOC textToCopy={fieldValue}>
|
||||
<Typography.Text ellipsis>
|
||||
{': '}
|
||||
{fieldValue}
|
||||
</Typography.Text>
|
||||
</CopyClipboardHOC>
|
||||
</div>
|
||||
</TextContainer>
|
||||
);
|
||||
}
|
||||
function LogSelectedField({
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Card } from 'antd';
|
||||
import { Card, Typography } from 'antd';
|
||||
import styled, { keyframes } from 'styled-components';
|
||||
|
||||
const fadeInAnimation = keyframes`
|
||||
@ -16,3 +16,16 @@ export const Container = styled(Card)`
|
||||
animation-duration: 0.2s;
|
||||
animation-timing-function: ease-in;
|
||||
`;
|
||||
|
||||
export const Text = styled(Typography.Text)`
|
||||
&&& {
|
||||
min-width: 1.5rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
`;
|
||||
|
||||
export const TextContainer = styled.div`
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
`;
|
||||
|
@ -11,7 +11,7 @@ function CustomModal({
|
||||
return (
|
||||
<Modal
|
||||
title={title}
|
||||
visible={isModalVisible}
|
||||
open={isModalVisible}
|
||||
footer={footer}
|
||||
closable={closable}
|
||||
>
|
||||
|
@ -3,4 +3,5 @@ export enum LOCALSTORAGE {
|
||||
IS_LOGGED_IN = 'IS_LOGGED_IN',
|
||||
AUTH_TOKEN = 'AUTH_TOKEN',
|
||||
REFRESH_AUTH_TOKEN = 'REFRESH_AUTH_TOKEN',
|
||||
THEME = 'THEME',
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Button } from 'antd';
|
||||
import { NotificationInstance } from 'antd/lib/notification';
|
||||
import { NotificationInstance } from 'antd/es/notification/interface';
|
||||
import deleteChannel from 'api/channels/delete';
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
@ -3,9 +3,10 @@ import styled from 'styled-components';
|
||||
|
||||
export const Layout = styled(LayoutComponent)`
|
||||
&&& {
|
||||
min-height: 92vh;
|
||||
display: flex;
|
||||
position: relative;
|
||||
min-height: calc(100vh - 4rem);
|
||||
overflow: hidden;
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { Menu, Space } from 'antd';
|
||||
import Spinner from 'components/Spinner';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React, { Suspense, useMemo } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { ConfigProps } from 'types/api/dynamicConfigs/getDynamicConfigs';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
import ErrorLink from './ErrorLink';
|
||||
import LinkContainer from './Link';
|
||||
import { MenuItem } from './styles';
|
||||
|
||||
function HelpToolTip({ config }: HelpToolTipProps): JSX.Element {
|
||||
const sortedConfig = useMemo(
|
||||
@ -15,10 +14,10 @@ function HelpToolTip({ config }: HelpToolTipProps): JSX.Element {
|
||||
[config.components],
|
||||
);
|
||||
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
return (
|
||||
<Menu.ItemGroup>
|
||||
<Menu>
|
||||
{sortedConfig.map((item) => {
|
||||
const iconName = `${isDarkMode ? item.darkIcon : item.lightIcon}`;
|
||||
|
||||
@ -28,19 +27,19 @@ function HelpToolTip({ config }: HelpToolTipProps): JSX.Element {
|
||||
return (
|
||||
<ErrorLink key={item.text + item.href}>
|
||||
<Suspense fallback={<Spinner height="5vh" />}>
|
||||
<Menu.Item>
|
||||
<MenuItem>
|
||||
<LinkContainer href={item.href}>
|
||||
<Space size="small" align="start">
|
||||
<Component />
|
||||
{item.text}
|
||||
</Space>
|
||||
</LinkContainer>
|
||||
</Menu.Item>
|
||||
</MenuItem>
|
||||
</Suspense>
|
||||
</ErrorLink>
|
||||
);
|
||||
})}
|
||||
</Menu.ItemGroup>
|
||||
</Menu>
|
||||
);
|
||||
}
|
||||
|
||||
|
10
frontend/src/container/ConfigDropdown/Config/styles.ts
Normal file
10
frontend/src/container/ConfigDropdown/Config/styles.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { Menu } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const MenuItem = styled(Menu.Item)`
|
||||
&&& {
|
||||
height: 1.75rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
`;
|
@ -5,6 +5,7 @@ import {
|
||||
QuestionCircleOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { Dropdown, Menu, Space } from 'antd';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
@ -15,9 +16,8 @@ import HelpToolTip from './Config';
|
||||
function DynamicConfigDropdown({
|
||||
frontendId,
|
||||
}: DynamicConfigDropdownProps): JSX.Element {
|
||||
const { configs, isDarkMode } = useSelector<AppState, AppReducer>(
|
||||
(state) => state.app,
|
||||
);
|
||||
const { configs } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
const [isHelpDropDownOpen, setIsHelpDropDownOpen] = useState<boolean>(false);
|
||||
|
||||
const config = useMemo(
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Select } from 'antd';
|
||||
import FormItem from 'antd/lib/form/FormItem';
|
||||
import { Form, Select } from 'antd';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AlertDef, Labels } from 'types/api/alerts/def';
|
||||
@ -31,7 +30,7 @@ function BasicInfo({ alertDef, setAlertDef }: BasicInfoProps): JSX.Element {
|
||||
<>
|
||||
<StepHeading> {t('alert_form_step3')} </StepHeading>
|
||||
<FormContainer>
|
||||
<FormItem
|
||||
<Form.Item
|
||||
label={t('field_severity')}
|
||||
labelAlign="left"
|
||||
name={['labels', 'severity']}
|
||||
@ -54,9 +53,9 @@ function BasicInfo({ alertDef, setAlertDef }: BasicInfoProps): JSX.Element {
|
||||
<Option value="warning">{t('option_warning')}</Option>
|
||||
<Option value="info">{t('option_info')}</Option>
|
||||
</SeveritySelect>
|
||||
</FormItem>
|
||||
</Form.Item>
|
||||
|
||||
<FormItem label={t('field_alert_name')} labelAlign="left" name="alert">
|
||||
<Form.Item label={t('field_alert_name')} labelAlign="left" name="alert">
|
||||
<InputSmall
|
||||
onChange={(e): void => {
|
||||
setAlertDef({
|
||||
@ -65,8 +64,8 @@ function BasicInfo({ alertDef, setAlertDef }: BasicInfoProps): JSX.Element {
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t('field_alert_desc')}
|
||||
labelAlign="left"
|
||||
name={['annotations', 'description']}
|
||||
@ -82,7 +81,7 @@ function BasicInfo({ alertDef, setAlertDef }: BasicInfoProps): JSX.Element {
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</FormItem>
|
||||
</Form.Item>
|
||||
<FormItemMedium label={t('field_labels')}>
|
||||
<LabelSelect
|
||||
onSetLabels={(l: Labels): void => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ExclamationCircleOutlined, SaveOutlined } from '@ant-design/icons';
|
||||
import { FormInstance, Modal, notification, Typography } from 'antd';
|
||||
import { Col, FormInstance, Modal, notification, Typography } from 'antd';
|
||||
import saveAlertApi from 'api/alerts/save';
|
||||
import testAlertApi from 'api/alerts/testAlert';
|
||||
import ROUTES from 'constants/routes';
|
||||
@ -34,7 +34,6 @@ import {
|
||||
MainFormContainer,
|
||||
PanelContainer,
|
||||
StyledLeftContainer,
|
||||
StyledRightContainer,
|
||||
} from './styles';
|
||||
import useDebounce from './useDebounce';
|
||||
import UserGuide from './UserGuide';
|
||||
@ -535,9 +534,9 @@ function FormAlertRules({
|
||||
</ButtonContainer>
|
||||
</MainFormContainer>
|
||||
</StyledLeftContainer>
|
||||
<StyledRightContainer flex="1 1 300px">
|
||||
<Col flex="1 1 300px">
|
||||
<UserGuide queryType={queryCategory} />
|
||||
</StyledRightContainer>
|
||||
</Col>
|
||||
</PanelContainer>
|
||||
</>
|
||||
);
|
||||
|
@ -4,13 +4,11 @@ import {
|
||||
} from '@ant-design/icons';
|
||||
import { useMachine } from '@xstate/react';
|
||||
import { Button, Input, message, Modal } from 'antd';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { map } from 'lodash-es';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { Labels } from 'types/api/alerts/def';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { ResourceAttributesFilterMachine } from './Labels.machine';
|
||||
@ -29,7 +27,8 @@ function LabelSelect({
|
||||
initialValues,
|
||||
}: LabelSelectProps): JSX.Element | null {
|
||||
const { t } = useTranslation('alerts');
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const [currentVal, setCurrentVal] = useState('');
|
||||
const [staging, setStaging] = useState<string[]>([]);
|
||||
const [queries, setQueries] = useState<ILabelRecord[]>(
|
||||
|
@ -9,19 +9,15 @@ import {
|
||||
Select,
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import FormItem from 'antd/lib/form/FormItem';
|
||||
import TextArea from 'antd/lib/input/TextArea';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const { TextArea } = Input;
|
||||
const { Item } = Form;
|
||||
|
||||
export const PanelContainer = styled(Row)`
|
||||
flex-wrap: nowrap;
|
||||
`;
|
||||
|
||||
export const StyledRightContainer = styled(Col)`
|
||||
&&& {
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledLeftContainer = styled(Col)`
|
||||
&&& {
|
||||
margin-right: 1rem;
|
||||
@ -111,7 +107,7 @@ export const TextareaMedium = styled(TextArea)`
|
||||
width: 70%;
|
||||
`;
|
||||
|
||||
export const FormItemMedium = styled(FormItem)`
|
||||
export const FormItemMedium = styled(Item)`
|
||||
width: 70%;
|
||||
`;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { convertTimeToRelevantUnit } from 'container/TraceDetail/utils';
|
||||
import useThemeMode from 'hooks/useThemeMode';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React from 'react';
|
||||
import { toFixed } from 'utils/toFixed';
|
||||
|
||||
@ -14,7 +14,7 @@ interface SpanLengthProps {
|
||||
|
||||
function SpanLength(props: SpanLengthProps): JSX.Element {
|
||||
const { width, leftOffset, bgColor, inMsCount } = props;
|
||||
const { isDarkMode } = useThemeMode();
|
||||
const isDarkMode = useIsDarkMode();
|
||||
const { time, timeUnitName } = convertTimeToRelevantUnit(inMsCount);
|
||||
return (
|
||||
<SpanWrapper>
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { CaretDownFilled, CaretRightFilled } from '@ant-design/icons';
|
||||
import { Col } from 'antd';
|
||||
import { Col, Typography } from 'antd';
|
||||
import { StyledCol, StyledRow } from 'components/Styled';
|
||||
import { IIntervalUnit } from 'container/TraceDetail/utils';
|
||||
import useThemeMode from 'hooks/useThemeMode';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { SPAN_DETAILS_LEFT_COL_WIDTH } from 'pages/TraceDetail/constants';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { ITraceTree } from 'types/api/trace/getTraceItem';
|
||||
|
||||
import { ITraceMetaData } from '..';
|
||||
@ -19,6 +19,7 @@ import {
|
||||
styles,
|
||||
Wrapper,
|
||||
} from './styles';
|
||||
import { getIconStyles } from './utils';
|
||||
|
||||
function Trace(props: TraceProps): JSX.Element {
|
||||
const {
|
||||
@ -42,7 +43,8 @@ function Trace(props: TraceProps): JSX.Element {
|
||||
isMissing,
|
||||
} = props;
|
||||
|
||||
const { isDarkMode } = useThemeMode();
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const [isOpen, setOpen] = useState<boolean>(activeSpanPath[level] === id);
|
||||
|
||||
const localTreeExpandInteraction = useRef<boolean | 0>(0); // Boolean is for the state of the expansion whereas the number i.e. 0 is for skipping the user interaction.
|
||||
@ -111,6 +113,18 @@ function Trace(props: TraceProps): JSX.Element {
|
||||
const width = (value * 1e2) / (globalSpread * 1e6);
|
||||
const panelWidth = SPAN_DETAILS_LEFT_COL_WIDTH - level * (16 + 1) - 48;
|
||||
|
||||
const iconStyles = useMemo(() => getIconStyles(isDarkMode), [isDarkMode]);
|
||||
|
||||
const icon = useMemo(
|
||||
() =>
|
||||
isOpen ? (
|
||||
<CaretDownFilled style={iconStyles} />
|
||||
) : (
|
||||
<CaretRightFilled style={iconStyles} />
|
||||
),
|
||||
[isOpen, iconStyles],
|
||||
);
|
||||
|
||||
return (
|
||||
<Wrapper
|
||||
onMouseEnter={onMouseEnterHandler}
|
||||
@ -136,10 +150,8 @@ function Trace(props: TraceProps): JSX.Element {
|
||||
isDarkMode={isDarkMode}
|
||||
onClick={onClickTreeExpansion}
|
||||
>
|
||||
{totalSpans}
|
||||
<CaretContainer>
|
||||
{isOpen ? <CaretDownFilled /> : <CaretRightFilled />}
|
||||
</CaretContainer>
|
||||
<Typography>{totalSpans}</Typography>
|
||||
<CaretContainer>{icon}</CaretContainer>
|
||||
</CardComponent>
|
||||
)}
|
||||
</Col>
|
||||
|
3
frontend/src/container/GantChart/Trace/utils.ts
Normal file
3
frontend/src/container/GantChart/Trace/utils.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export const getIconStyles = (isDarkMode: boolean): Record<string, string> => ({
|
||||
color: isDarkMode ? 'white' : 'black',
|
||||
});
|
@ -572,7 +572,7 @@ function GeneralSettings({
|
||||
onOkHandler(category.name.toLowerCase() as TTTLType)
|
||||
}
|
||||
centered
|
||||
visible={category.save.modal}
|
||||
open={category.save.modal}
|
||||
confirmLoading={category.save.apiLoading}
|
||||
>
|
||||
<Typography>
|
||||
|
@ -183,7 +183,7 @@ function GridCardGraph({
|
||||
<Modal
|
||||
destroyOnClose
|
||||
onCancel={(): void => onToggleModal(setDeleteModal)}
|
||||
visible={deleteModal}
|
||||
open={deleteModal}
|
||||
title="Delete"
|
||||
height="10vh"
|
||||
onOk={onDeleteHandler}
|
||||
@ -196,7 +196,7 @@ function GridCardGraph({
|
||||
title="View"
|
||||
footer={[]}
|
||||
centered
|
||||
visible={modal}
|
||||
open={modal}
|
||||
onCancel={(): void => onToggleModal(setModal)}
|
||||
width="85%"
|
||||
destroyOnClose
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { PlusOutlined, SaveFilled } from '@ant-design/icons';
|
||||
import useComponentPermission from 'hooks/useComponentPermission';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React from 'react';
|
||||
import { Layout } from 'react-grid-layout';
|
||||
import { useSelector } from 'react-redux';
|
||||
@ -27,7 +28,7 @@ function GraphLayout({
|
||||
setLayout,
|
||||
}: GraphLayoutProps): JSX.Element {
|
||||
const { role } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const [saveLayoutPermission, addPanelPermission] = useComponentPermission(
|
||||
['save_layout', 'add_panel'],
|
||||
|
@ -3,67 +3,39 @@ import {
|
||||
CaretUpFilled,
|
||||
LogoutOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import {
|
||||
Avatar,
|
||||
Divider,
|
||||
Dropdown,
|
||||
Layout,
|
||||
Menu,
|
||||
Space,
|
||||
Typography,
|
||||
} from 'antd';
|
||||
import { Divider, Dropdown, Menu, Space, Typography } from 'antd';
|
||||
import { Logout } from 'api/utils';
|
||||
import ROUTES from 'constants/routes';
|
||||
import Config from 'container/ConfigDropdown';
|
||||
import setTheme, { AppMode } from 'lib/theme/setTheme';
|
||||
import { useIsDarkMode, useThemeMode } from 'hooks/useDarkMode';
|
||||
import React, { Dispatch, SetStateAction, useCallback, useState } from 'react';
|
||||
import { connect, useSelector } from 'react-redux';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { ThunkDispatch } from 'redux-thunk';
|
||||
import { ToggleDarkMode } from 'store/actions';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppActions from 'types/actions';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
import CurrentOrganization from './CurrentOrganization';
|
||||
import ManageLicense from './ManageLicense';
|
||||
import SignedInAS from './SignedInAs';
|
||||
import {
|
||||
AvatarWrapper,
|
||||
Container,
|
||||
Header,
|
||||
IconContainer,
|
||||
LogoutContainer,
|
||||
NavLinkWrapper,
|
||||
ToggleButton,
|
||||
} from './styles';
|
||||
|
||||
function HeaderContainer({ toggleDarkMode }: Props): JSX.Element {
|
||||
const { isDarkMode, user, currentVersion } = useSelector<AppState, AppReducer>(
|
||||
function HeaderContainer(): JSX.Element {
|
||||
const { user, currentVersion } = useSelector<AppState, AppReducer>(
|
||||
(state) => state.app,
|
||||
);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
const { toggleTheme } = useThemeMode();
|
||||
|
||||
const [isUserDropDownOpen, setIsUserDropDownOpen] = useState<boolean>(false);
|
||||
|
||||
const onToggleThemeHandler = useCallback(() => {
|
||||
const preMode: AppMode = isDarkMode ? 'lightMode' : 'darkMode';
|
||||
setTheme(preMode);
|
||||
|
||||
const id: AppMode = preMode;
|
||||
const { head } = document;
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.type = 'text/css';
|
||||
link.href = !isDarkMode ? '/css/antd.dark.min.css' : '/css/antd.min.css';
|
||||
link.media = 'all';
|
||||
link.id = id;
|
||||
head.appendChild(link);
|
||||
|
||||
link.onload = (): void => {
|
||||
toggleDarkMode();
|
||||
const prevNode = document.getElementById('appMode');
|
||||
prevNode?.remove();
|
||||
};
|
||||
}, [toggleDarkMode, isDarkMode]);
|
||||
|
||||
const onToggleHandler = useCallback(
|
||||
(functionToExecute: Dispatch<SetStateAction<boolean>>) => (): void => {
|
||||
functionToExecute((state) => !state);
|
||||
@ -100,15 +72,18 @@ function HeaderContainer({ toggleDarkMode }: Props): JSX.Element {
|
||||
);
|
||||
|
||||
return (
|
||||
<Layout.Header>
|
||||
<Header>
|
||||
<Container>
|
||||
<NavLink to={ROUTES.APPLICATION}>
|
||||
<Space align="center" direction="horizontal">
|
||||
<NavLinkWrapper>
|
||||
<img src={`/signoz.svg?currentVersion=${currentVersion}`} alt="SigNoz" />
|
||||
<Typography.Title style={{ margin: 0, color: '#DBDBDB' }} level={4}>
|
||||
<Typography.Title
|
||||
style={{ margin: 0, color: 'rgb(219, 219, 219)' }}
|
||||
level={4}
|
||||
>
|
||||
SigNoz
|
||||
</Typography.Title>
|
||||
</Space>
|
||||
</NavLinkWrapper>
|
||||
</NavLink>
|
||||
|
||||
<Space style={{ height: '100%' }} align="center">
|
||||
@ -116,7 +91,7 @@ function HeaderContainer({ toggleDarkMode }: Props): JSX.Element {
|
||||
|
||||
<ToggleButton
|
||||
checked={isDarkMode}
|
||||
onChange={onToggleThemeHandler}
|
||||
onChange={toggleTheme}
|
||||
defaultChecked={isDarkMode}
|
||||
checkedChildren="🌜"
|
||||
unCheckedChildren="🌞"
|
||||
@ -129,7 +104,7 @@ function HeaderContainer({ toggleDarkMode }: Props): JSX.Element {
|
||||
visible={isUserDropDownOpen}
|
||||
>
|
||||
<Space>
|
||||
<Avatar shape="circle">{user?.name[0]}</Avatar>
|
||||
<AvatarWrapper shape="circle">{user?.name[0]}</AvatarWrapper>
|
||||
<IconContainer>
|
||||
{!isUserDropDownOpen ? <CaretDownFilled /> : <CaretUpFilled />}
|
||||
</IconContainer>
|
||||
@ -137,20 +112,8 @@ function HeaderContainer({ toggleDarkMode }: Props): JSX.Element {
|
||||
</Dropdown>
|
||||
</Space>
|
||||
</Container>
|
||||
</Layout.Header>
|
||||
</Header>
|
||||
);
|
||||
}
|
||||
|
||||
interface DispatchProps {
|
||||
toggleDarkMode: () => void;
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (
|
||||
dispatch: ThunkDispatch<unknown, unknown, AppActions>,
|
||||
): DispatchProps => ({
|
||||
toggleDarkMode: bindActionCreators(ToggleDarkMode, dispatch),
|
||||
});
|
||||
|
||||
type Props = DispatchProps;
|
||||
|
||||
export default connect(null, mapDispatchToProps)(HeaderContainer);
|
||||
export default HeaderContainer;
|
||||
|
@ -1,10 +1,14 @@
|
||||
import { Switch, Typography } from 'antd';
|
||||
import { Avatar, Layout, Switch, Typography } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const Header = styled(Layout.Header)`
|
||||
background: #1f1f1f !important;
|
||||
`;
|
||||
|
||||
export const Container = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
height: 4rem;
|
||||
`;
|
||||
|
||||
export const AvatarContainer = styled.div`
|
||||
@ -66,3 +70,15 @@ export const ToggleButton = styled(Switch)<DarkModeProps>`
|
||||
export const IconContainer = styled.div`
|
||||
color: white;
|
||||
`;
|
||||
|
||||
export const NavLinkWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
gap: 0.5rem;
|
||||
`;
|
||||
|
||||
export const AvatarWrapper = styled(Avatar)`
|
||||
background-color: rgba(255, 255, 255, 0.25);
|
||||
`;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { NotificationInstance } from 'antd/lib/notification/index';
|
||||
import { NotificationInstance } from 'antd/es/notification/interface';
|
||||
import deleteAlerts from 'api/alerts/delete';
|
||||
import { State } from 'hooks/useFetch';
|
||||
import React, { useState } from 'react';
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* eslint-disable react/display-name */
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { notification, Typography } from 'antd';
|
||||
import Table, { ColumnsType } from 'antd/lib/table';
|
||||
import { notification, Table, Typography } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import TextToolTip from 'components/TextToolTip';
|
||||
import ROUTES from 'constants/routes';
|
||||
import useComponentPermission from 'hooks/useComponentPermission';
|
||||
|
@ -131,7 +131,7 @@ function ImportJSON({
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={isImportJSONModalVisible}
|
||||
open={isImportJSONModalVisible}
|
||||
centered
|
||||
maskClosable
|
||||
destroyOnClose
|
||||
|
@ -5,10 +5,7 @@ import { RefSelectProps } from 'antd/lib/select';
|
||||
import history from 'lib/history';
|
||||
import { filter, map } from 'lodash-es';
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { Dashboard } from 'types/api/dashboard/getAll';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { DashboardSearchAndFilter } from './Dashboard.machine';
|
||||
@ -30,7 +27,6 @@ function SearchFilter({
|
||||
searchData: Dashboard[];
|
||||
filterDashboards: (filteredDashboards: Dashboard[]) => void;
|
||||
}): JSX.Element {
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const [category, setCategory] = useState<TCategory>();
|
||||
const [optionsData, setOptionsData] = useState<IOptionsData>(
|
||||
OptionsSchemas.attribute,
|
||||
@ -154,14 +150,8 @@ function SearchFilter({
|
||||
};
|
||||
|
||||
return (
|
||||
<SearchContainer isDarkMode={isDarkMode}>
|
||||
<div
|
||||
style={{
|
||||
maxWidth: '70%',
|
||||
display: 'flex',
|
||||
overflowX: 'auto',
|
||||
}}
|
||||
>
|
||||
<SearchContainer>
|
||||
<div>
|
||||
{map(queries, (query) => (
|
||||
<QueryChip key={query.id} queryData={query} onRemove={removeQueryById} />
|
||||
))}
|
||||
|
@ -2,10 +2,7 @@ import { grey } from '@ant-design/colors';
|
||||
import { Tag } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const SearchContainer = styled.div<{
|
||||
isDarkMode: boolean;
|
||||
}>`
|
||||
background: ${({ isDarkMode }): string => (isDarkMode ? '#000' : '#fff')};
|
||||
export const SearchContainer = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -45,7 +45,7 @@ function TableView({ logData }: TableViewProps): JSX.Element | null {
|
||||
const columns = [
|
||||
{
|
||||
title: 'Action',
|
||||
width: 75,
|
||||
width: 100,
|
||||
render: (fieldData: Record<string, string>): JSX.Element | null => {
|
||||
const fieldKey = fieldData.field.split('.').slice(-1);
|
||||
if (!RESTRICTED_FIELDS.includes(fieldKey[0])) {
|
||||
|
@ -1,20 +1,22 @@
|
||||
import { Drawer, Tabs } from 'antd';
|
||||
import React from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { Dispatch } from 'redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppActions from 'types/actions';
|
||||
import { SET_DETAILED_LOG_DATA } from 'types/actions/logs';
|
||||
import { ILogsReducer } from 'types/reducer/logs';
|
||||
|
||||
import JSONView from './JsonView';
|
||||
import TableView from './TableView';
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
function LogDetailedView(): JSX.Element {
|
||||
const { detailedLog } = useSelector<AppState, ILogsReducer>(
|
||||
(state) => state.logs,
|
||||
);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const dispatch = useDispatch<Dispatch<AppActions>>();
|
||||
|
||||
const onDrawerClose = (): void => {
|
||||
dispatch({
|
||||
type: SET_DETAILED_LOG_DATA,
|
||||
@ -23,30 +25,25 @@ function LogDetailedView(): JSX.Element {
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{}}>
|
||||
<Drawer
|
||||
width="60%"
|
||||
title="Log Details"
|
||||
placement="right"
|
||||
closable
|
||||
mask={false}
|
||||
onClose={onDrawerClose}
|
||||
visible={detailedLog !== null}
|
||||
getContainer={false}
|
||||
style={{ overscrollBehavior: 'contain' }}
|
||||
>
|
||||
{detailedLog && (
|
||||
<Tabs defaultActiveKey="1">
|
||||
<TabPane tab="Table" key="1">
|
||||
<TableView logData={detailedLog} />
|
||||
</TabPane>
|
||||
<TabPane tab="JSON" key="2">
|
||||
<JSONView logData={detailedLog} />
|
||||
</TabPane>
|
||||
</Tabs>
|
||||
)}
|
||||
</Drawer>
|
||||
</div>
|
||||
<Drawer
|
||||
width="60%"
|
||||
title="Log Details"
|
||||
placement="right"
|
||||
closable
|
||||
onClose={onDrawerClose}
|
||||
open={detailedLog !== null}
|
||||
style={{ overscrollBehavior: 'contain' }}
|
||||
destroyOnClose
|
||||
>
|
||||
<Tabs defaultActiveKey="1">
|
||||
<Tabs.TabPane tab="Table" key="1">
|
||||
{detailedLog && <TableView logData={detailedLog} />}
|
||||
</Tabs.TabPane>
|
||||
<Tabs.TabPane tab="JSON" key="2">
|
||||
{detailedLog && <JSONView logData={detailedLog} />}
|
||||
</Tabs.TabPane>
|
||||
</Tabs>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
import { Button, Popover, Select, Space } from 'antd';
|
||||
import { LiveTail } from 'api/logs/livetail';
|
||||
import dayjs from 'dayjs';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { throttle } from 'lodash-es';
|
||||
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
@ -19,7 +20,6 @@ import {
|
||||
TOGGLE_LIVE_TAIL,
|
||||
} from 'types/actions/logs';
|
||||
import { TLogsLiveTailState } from 'types/api/logs/liveTail';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
import { GlobalReducer } from 'types/reducer/globalTime';
|
||||
import { ILogsReducer } from 'types/reducer/logs';
|
||||
|
||||
@ -35,7 +35,8 @@ function LogLiveTail(): JSX.Element {
|
||||
liveTailStartRange,
|
||||
logs,
|
||||
} = useSelector<AppState, ILogsReducer>((state) => state.logs);
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const { selectedAutoRefreshInterval } = useSelector<AppState, GlobalReducer>(
|
||||
(state) => state.globalTime,
|
||||
);
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { Button, Popover, Spin } from 'antd';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React, { useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
import { Field } from './styles';
|
||||
|
||||
@ -26,7 +24,7 @@ export function FieldItem({
|
||||
iconHoverText,
|
||||
}: FieldItemProps): JSX.Element {
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
return (
|
||||
<Field
|
||||
onMouseEnter={(): void => {
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { Typography } from 'antd';
|
||||
import LogItem from 'components/Logs/LogItem';
|
||||
import Spinner from 'components/Spinner';
|
||||
import { map } from 'lodash-es';
|
||||
import map from 'lodash-es/map';
|
||||
import React, { memo } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
@ -22,14 +22,7 @@ function LogsTable(): JSX.Element {
|
||||
return (
|
||||
<Container flex="auto">
|
||||
<Heading>
|
||||
<Typography.Text
|
||||
style={{
|
||||
fontSize: '1rem',
|
||||
fontWeight: 400,
|
||||
}}
|
||||
>
|
||||
Event
|
||||
</Typography.Text>
|
||||
<Typography.Text>Event</Typography.Text>
|
||||
</Heading>
|
||||
{Array.isArray(logs) && logs.length > 0 ? (
|
||||
map(logs, (log) => <LogItem key={log.id} logData={log} />)
|
||||
|
@ -10,7 +10,6 @@ import { useDispatch, useSelector } from 'react-redux';
|
||||
import { ResetInitialData } from 'store/actions/metrics/resetInitialData';
|
||||
import { SetResourceAttributeQueries } from 'store/actions/metrics/setResourceAttributeQueries';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
import MetricReducer from 'types/reducer/metrics';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
@ -38,7 +37,6 @@ function ResourceAttributesFilter(): JSX.Element | null {
|
||||
};
|
||||
}, [dispatch]);
|
||||
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const { resourceAttributeQueries } = useSelector<AppState, MetricReducer>(
|
||||
(state) => state.metrics,
|
||||
);
|
||||
@ -156,7 +154,7 @@ function ResourceAttributesFilter(): JSX.Element | null {
|
||||
}
|
||||
|
||||
return (
|
||||
<SearchContainer isDarkMode={isDarkMode} disabled={disabled}>
|
||||
<SearchContainer disabled={disabled}>
|
||||
<div
|
||||
style={{
|
||||
maxWidth: disabled ? '100%' : '70%',
|
||||
|
@ -3,10 +3,8 @@ import { Tag } from 'antd';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const SearchContainer = styled.div<{
|
||||
isDarkMode: boolean;
|
||||
disabled: boolean;
|
||||
}>`
|
||||
background: ${({ isDarkMode }): string => (isDarkMode ? '#000' : '#fff')};
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
import { notification } from 'antd';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import history from 'lib/history';
|
||||
import React, { useCallback } from 'react';
|
||||
import { connect, useSelector } from 'react-redux';
|
||||
@ -11,7 +12,6 @@ import {
|
||||
} from 'store/actions/dashboard/toggleAddWidget';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppActions from 'types/actions';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
import DashboardReducer from 'types/reducer/dashboards';
|
||||
|
||||
import menuItems, { ITEMS } from './menuItems';
|
||||
@ -50,7 +50,7 @@ function DashboardGraphSlider({ toggleAddWidget }: Props): JSX.Element {
|
||||
},
|
||||
[data, toggleAddWidget],
|
||||
);
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
const fillColor: React.CSSProperties['color'] = isDarkMode ? 'white' : 'black';
|
||||
|
||||
return (
|
||||
|
@ -165,7 +165,7 @@ function VariablesSetting({
|
||||
<Modal
|
||||
title="Delete variable"
|
||||
centered
|
||||
visible={deleteVariableModal}
|
||||
open={deleteVariableModal}
|
||||
onOk={handleDeleteConfirm}
|
||||
onCancel={handleDeleteCancel}
|
||||
>
|
||||
|
@ -83,7 +83,7 @@ function ShareModal({
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={isJSONModalVisible}
|
||||
open={isJSONModalVisible}
|
||||
onCancel={(): void => {
|
||||
onToggleHandler();
|
||||
setIsViewJSON(false);
|
||||
|
@ -1,12 +1,10 @@
|
||||
import { CloseCircleFilled } from '@ant-design/icons';
|
||||
import { useMachine } from '@xstate/react';
|
||||
import { Button, Select, Spin } from 'antd';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import { map } from 'lodash-es';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { IMetricsBuilderQuery } from 'types/api/dashboard/getAll';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { ResourceAttributesFilterMachine } from './MetricTagKey.machine';
|
||||
@ -32,7 +30,7 @@ function MetricTagKeyFilter({
|
||||
onSetQuery,
|
||||
selectedTagFilters: selectedTagQueries,
|
||||
}: IMetricTagKeyFilterProps): JSX.Element | null {
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [selectedValues, setSelectedValues] = useState<string[]>([]);
|
||||
const [staging, setStaging] = useState<string[]>([]);
|
||||
|
@ -213,7 +213,7 @@ function NewWidget({
|
||||
onClickSaveHandler();
|
||||
}}
|
||||
centered
|
||||
visible={saveModal}
|
||||
open={saveModal}
|
||||
width={600}
|
||||
>
|
||||
{hasUnstagedChanges ? (
|
||||
|
@ -69,7 +69,7 @@ function AddDomain({ refetch }: Props): JSX.Element {
|
||||
centered
|
||||
title="Add Domain"
|
||||
footer={null}
|
||||
visible={isAddDomains}
|
||||
open={isAddDomains}
|
||||
destroyOnClose
|
||||
onCancel={(): void => setIsDomain(false)}
|
||||
>
|
||||
|
@ -256,7 +256,7 @@ function AuthDomains(): JSX.Element {
|
||||
title="Configure Authentication Method"
|
||||
onCancel={onCloseHandler(setIsSettingsOpen)}
|
||||
destroyOnClose
|
||||
visible={isSettingsOpen}
|
||||
open={isSettingsOpen}
|
||||
footer={null}
|
||||
>
|
||||
<Create
|
||||
@ -285,7 +285,7 @@ function AuthDomains(): JSX.Element {
|
||||
title="Configure Authentication Method"
|
||||
onCancel={onCloseHandler(setIsSettingsOpen)}
|
||||
destroyOnClose
|
||||
visible={isSettingsOpen}
|
||||
open={isSettingsOpen}
|
||||
footer={null}
|
||||
>
|
||||
<Create
|
||||
@ -297,7 +297,7 @@ function AuthDomains(): JSX.Element {
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
visible={isEditModalOpen}
|
||||
open={isEditModalOpen}
|
||||
centered
|
||||
title={EditModalTitleText(currentDomain?.ssoType)}
|
||||
onCancel={onCloseHandler(setIsEditModalOpen)}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Button, Modal, notification, Space, Typography } from 'antd';
|
||||
import Table, { ColumnsType } from 'antd/lib/table';
|
||||
import { Button, Modal, notification, Space, Table, Typography } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import deleteUser from 'api/user/deleteUser';
|
||||
import editUserApi from 'api/user/editUser';
|
||||
import getOrgUser from 'api/user/getOrgUser';
|
||||
@ -176,7 +176,7 @@ function UserFunction({
|
||||
</Space>
|
||||
<Modal
|
||||
title="Edit member details"
|
||||
visible={isModalVisible}
|
||||
open={isModalVisible}
|
||||
onOk={(): void => onModalToggleHandler(setIsModalVisible, false)}
|
||||
onCancel={(): void => onModalToggleHandler(setIsModalVisible, false)}
|
||||
centered
|
||||
@ -214,7 +214,7 @@ function UserFunction({
|
||||
</Modal>
|
||||
<Modal
|
||||
title="Edit member details"
|
||||
visible={isDeleteModalVisible}
|
||||
open={isDeleteModalVisible}
|
||||
onOk={onDeleteHandler}
|
||||
onCancel={(): void => onModalToggleHandler(setIsDeleteModalVisible, false)}
|
||||
centered
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Button, Modal, notification, Space, Typography } from 'antd';
|
||||
import Table, { ColumnsType } from 'antd/lib/table';
|
||||
import { Button, Modal, notification, Space, Table, Typography } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import deleteInvite from 'api/user/deleteInvite';
|
||||
import getPendingInvites from 'api/user/getPendingInvites';
|
||||
import sendInvite from 'api/user/sendInvite';
|
||||
@ -222,7 +222,7 @@ function PendingInvitesContainer(): JSX.Element {
|
||||
<div>
|
||||
<Modal
|
||||
title={t('invite_team_members')}
|
||||
visible={isInviteTeamMemberModalOpen}
|
||||
open={isInviteTeamMemberModalOpen}
|
||||
onCancel={(): void => toggleModal(false)}
|
||||
centered
|
||||
destroyOnClose
|
||||
|
1
frontend/src/container/SideNav/config.ts
Normal file
1
frontend/src/container/SideNav/config.ts
Normal file
@ -0,0 +1 @@
|
||||
export const styles = { background: '#1f1f1f' };
|
@ -4,7 +4,7 @@ import getLocalStorageKey from 'api/browser/localstorage/get';
|
||||
import { IS_SIDEBAR_COLLAPSED } from 'constants/app';
|
||||
import ROUTES from 'constants/routes';
|
||||
import history from 'lib/history';
|
||||
import React, { useCallback, useLayoutEffect, useState } from 'react';
|
||||
import React, { useCallback, useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
@ -12,6 +12,7 @@ import { SideBarCollapse } from 'store/actions/app';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
import { styles } from './config';
|
||||
import menus from './menuItems';
|
||||
import Slack from './Slack';
|
||||
import {
|
||||
@ -89,7 +90,10 @@ function SideNav(): JSX.Element {
|
||||
},
|
||||
];
|
||||
|
||||
const currentMenu = menus.find((menu) => pathname.startsWith(menu.to));
|
||||
const currentMenu = useMemo(
|
||||
() => menus.find((menu) => pathname.startsWith(menu.to)),
|
||||
[pathname],
|
||||
);
|
||||
|
||||
return (
|
||||
<Sider collapsible collapsed={collapsed} onCollapse={onCollapse} width={200}>
|
||||
@ -98,6 +102,7 @@ function SideNav(): JSX.Element {
|
||||
defaultSelectedKeys={[ROUTES.APPLICATION]}
|
||||
selectedKeys={currentMenu ? [currentMenu?.to] : []}
|
||||
mode="inline"
|
||||
style={styles}
|
||||
>
|
||||
{menus.map(({ to, Icon, name, tags }) => (
|
||||
<Menu.Item
|
||||
|
@ -10,18 +10,19 @@ interface LogoProps {
|
||||
}
|
||||
|
||||
export const Sider = styled(SiderComponent)`
|
||||
z-index: 999;
|
||||
.ant-typography {
|
||||
color: white;
|
||||
}
|
||||
.ant-layout-sider-trigger {
|
||||
background-color: #1f1f1f;
|
||||
&&& {
|
||||
background: #1f1f1f;
|
||||
|
||||
.ant-layout-sider-trigger {
|
||||
background: #1f1f1f;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const SlackButton = styled(Typography)`
|
||||
&&& {
|
||||
margin-left: 1rem;
|
||||
color: white;
|
||||
}
|
||||
`;
|
||||
|
||||
@ -31,6 +32,7 @@ export const SlackMenuItemContainer = styled.div<LogoProps>`
|
||||
background: #262626;
|
||||
width: ${({ collapsed }): string => (!collapsed ? '200px' : '80px')};
|
||||
transition: inherit;
|
||||
background: #1f1f1f;
|
||||
|
||||
&&& {
|
||||
li {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { StyledDiv } from 'components/Styled';
|
||||
import { ITraceMetaData } from 'container/GantChart';
|
||||
import { IIntervalUnit, INTERVAL_UNITS } from 'container/TraceDetail/utils';
|
||||
import useThemeMode from 'hooks/useThemeMode';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useMeasure } from 'react-use';
|
||||
|
||||
@ -18,7 +18,7 @@ function Timeline({
|
||||
setIntervalUnit,
|
||||
}: TimelineProps): JSX.Element {
|
||||
const [ref, { width }] = useMeasure<HTMLDivElement>();
|
||||
const { isDarkMode } = useThemeMode();
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const [intervals, setIntervals] = useState<Interval[] | null>(null);
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
import { Modal } from 'antd';
|
||||
import DatePicker from 'components/DatePicker';
|
||||
import { DatePicker, Modal } from 'antd';
|
||||
import dayjs, { Dayjs } from 'dayjs';
|
||||
import React, { useState } from 'react';
|
||||
|
||||
@ -13,22 +12,22 @@ function CustomDateTimeModal({
|
||||
onCreate,
|
||||
onCancel,
|
||||
}: CustomDateTimeModalProps): JSX.Element {
|
||||
const [
|
||||
customDateTimeRange,
|
||||
setCustomDateTimeRange,
|
||||
] = useState<DateTimeRangeType>();
|
||||
const [customDateTimeRange, setCustomDateTimeRange] = useState();
|
||||
|
||||
function handleRangePickerOk(date_time: DateTimeRangeType): void {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function handleRangePickerOk(date_time: any): void {
|
||||
setCustomDateTimeRange(date_time);
|
||||
}
|
||||
|
||||
function disabledDate(current: Dayjs): boolean {
|
||||
return current > dayjs();
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function disabledDate(current: any): boolean {
|
||||
const currentDay = dayjs(current);
|
||||
return currentDay.isAfter(dayjs());
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
open={visible}
|
||||
title="Chose date and time range"
|
||||
okText="Apply"
|
||||
cancelText="Cancel"
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { TableProps, Tag, Typography } from 'antd';
|
||||
import Table, { ColumnsType } from 'antd/lib/table';
|
||||
import { Table, TableProps, Tag, Typography } from 'antd';
|
||||
import { ColumnsType } from 'antd/lib/table';
|
||||
import ROUTES from 'constants/routes';
|
||||
import {
|
||||
getSpanOrder,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Collapse } from 'antd';
|
||||
import useThemeMode from 'hooks/useThemeMode';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import keys from 'lodash-es/keys';
|
||||
import map from 'lodash-es/map';
|
||||
import React from 'react';
|
||||
@ -18,7 +18,7 @@ function ErrorTag({
|
||||
setText,
|
||||
firstSpanStartTime,
|
||||
}: ErrorTagProps): JSX.Element {
|
||||
const { isDarkMode } = useThemeMode();
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { Popover } from 'antd';
|
||||
import dayjs from 'dayjs';
|
||||
import useThemeMode from 'hooks/useThemeMode';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React from 'react';
|
||||
|
||||
import { CustomSubText, CustomSubTitle } from '../styles';
|
||||
|
||||
function EventStartTime({ timeUnixNano }: EventStartTimeProps): JSX.Element {
|
||||
const { isDarkMode } = useThemeMode();
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const humanReadableTimeInDayJs = dayjs(timeUnixNano / 1e6).format(
|
||||
'YYYY-MM-DD hh:mm:ss.SSS A',
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
import { Popover, Space } from 'antd';
|
||||
import { convertTimeToRelevantUnit } from 'container/TraceDetail/utils';
|
||||
import useThemeMode from 'hooks/useThemeMode';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React from 'react';
|
||||
|
||||
import { CustomSubText, CustomSubTitle } from '../styles';
|
||||
@ -10,7 +10,7 @@ function StartTime({
|
||||
firstSpanStartTime,
|
||||
timeUnixNano,
|
||||
}: StartTimeProps): JSX.Element {
|
||||
const { isDarkMode } = useThemeMode();
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const { time, timeUnitName } = convertTimeToRelevantUnit(
|
||||
timeUnixNano / 1e6 - (firstSpanStartTime || 0),
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { Tooltip } from 'antd';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React, { useMemo } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import { ITraceTag } from 'types/api/trace/getTraceItem';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
import EllipsedButton from '../EllipsedButton';
|
||||
import { CustomSubText, CustomSubTitle, SubTextContainer } from '../styles';
|
||||
@ -11,7 +9,7 @@ import { CommonTagsProps } from '.';
|
||||
import { Container } from './styles';
|
||||
|
||||
function Tag({ tags, onToggleHandler, setText }: TagProps): JSX.Element {
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const { value, isEllipsed } = useMemo(() => {
|
||||
const value = tags.key === 'error' ? 'true' : tags.value;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Modal, Tabs, Tooltip } from 'antd';
|
||||
import Editor from 'components/Editor';
|
||||
import { StyledSpace } from 'components/Styled';
|
||||
import useThemeMode from 'hooks/useThemeMode';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { ITraceTree } from 'types/api/trace/getTraceItem';
|
||||
|
||||
@ -20,7 +20,7 @@ const { TabPane } = Tabs;
|
||||
function SelectedSpanDetails(props: SelectedSpanDetailsProps): JSX.Element {
|
||||
const { tree, firstSpanStartTime } = props;
|
||||
|
||||
const { isDarkMode } = useThemeMode();
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const OverLayComponentName = useMemo(() => tree?.name, [tree?.name]);
|
||||
const OverLayComponentServiceName = useMemo(() => tree?.serviceName, [
|
||||
@ -67,7 +67,7 @@ function SelectedSpanDetails(props: SelectedSpanDetailsProps): JSX.Element {
|
||||
<Modal
|
||||
onCancel={(): void => onToggleHandler(false)}
|
||||
title={text.text}
|
||||
visible={isOpen}
|
||||
open={isOpen}
|
||||
destroyOnClose
|
||||
footer={[]}
|
||||
width="70vw"
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* eslint-disable react/no-unstable-nested-components */
|
||||
import Color from 'color';
|
||||
import { ITraceMetaData } from 'container/GantChart';
|
||||
import useThemeMode from 'hooks/useThemeMode';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React, { useLayoutEffect, useMemo, useState } from 'react';
|
||||
import { ITraceTree } from 'types/api/trace/getTraceItem';
|
||||
|
||||
@ -37,7 +37,7 @@ function SpanItem({
|
||||
const { serviceColour } = spanData;
|
||||
const [isSelected, setIsSelected] = useState<boolean>(false);
|
||||
// const [isLocalHover, setIsLocalHover] = useState<boolean>(false);
|
||||
const { isDarkMode } = useThemeMode();
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (
|
||||
|
4
frontend/src/hooks/useDarkMode/constant.ts
Normal file
4
frontend/src/hooks/useDarkMode/constant.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export const THEME_MODE = {
|
||||
LIGHT: 'light',
|
||||
DARK: 'dark',
|
||||
};
|
74
frontend/src/hooks/useDarkMode/index.tsx
Normal file
74
frontend/src/hooks/useDarkMode/index.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
import { theme as antdTheme } from 'antd';
|
||||
import { ThemeConfig } from 'antd/es/config-provider/context';
|
||||
import get from 'api/browser/localstorage/get';
|
||||
import set from 'api/browser/localstorage/set';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import React, { createContext, useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import { THEME_MODE } from './constant';
|
||||
|
||||
export const ThemeContext = createContext({
|
||||
theme: THEME_MODE.DARK,
|
||||
toggleTheme: () => {},
|
||||
});
|
||||
|
||||
export function ThemeProvider({ children }: ThemeProviderProps): JSX.Element {
|
||||
const [theme, setTheme] = useState(get(LOCALSTORAGE.THEME) || THEME_MODE.DARK);
|
||||
|
||||
const toggleTheme = useCallback(() => {
|
||||
if (theme === THEME_MODE.LIGHT) {
|
||||
setTheme(THEME_MODE.DARK);
|
||||
set(LOCALSTORAGE.THEME, THEME_MODE.DARK);
|
||||
} else {
|
||||
setTheme(THEME_MODE.LIGHT);
|
||||
set(LOCALSTORAGE.THEME, THEME_MODE.LIGHT);
|
||||
}
|
||||
}, [theme]);
|
||||
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
theme,
|
||||
toggleTheme,
|
||||
}),
|
||||
[theme, toggleTheme],
|
||||
);
|
||||
|
||||
return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
|
||||
}
|
||||
|
||||
interface ThemeProviderProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
interface ThemeMode {
|
||||
theme: string;
|
||||
toggleTheme: () => void;
|
||||
}
|
||||
|
||||
export const useThemeMode = (): ThemeMode => {
|
||||
const { theme, toggleTheme } = React.useContext(ThemeContext);
|
||||
|
||||
return { theme, toggleTheme };
|
||||
};
|
||||
|
||||
export const useIsDarkMode = (): boolean => {
|
||||
const { theme } = React.useContext(ThemeContext);
|
||||
|
||||
return theme === THEME_MODE.DARK;
|
||||
};
|
||||
|
||||
export const useThemeConfig = (): ThemeConfig => {
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
return {
|
||||
algorithm: isDarkMode ? antdTheme.darkAlgorithm : antdTheme.defaultAlgorithm,
|
||||
token: {
|
||||
borderRadius: 2,
|
||||
borderRadiusLG: 2,
|
||||
borderRadiusSM: 2,
|
||||
borderRadiusXS: 2,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default useThemeMode;
|
@ -1,15 +0,0 @@
|
||||
import { useSelector } from 'react-redux';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
export interface IUseThemeModeReturn {
|
||||
isDarkMode: boolean;
|
||||
}
|
||||
|
||||
const useThemeMode = (): IUseThemeModeReturn => {
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
|
||||
return { isDarkMode };
|
||||
};
|
||||
|
||||
export default useThemeMode;
|
@ -50,27 +50,9 @@
|
||||
<meta data-react-helmet="true" name="docusaurus_locale" content="en" />
|
||||
<meta data-react-helmet="true" name="docusaurus_tag" content="default" />
|
||||
<link data-react-helmet="true" rel="shortcut icon" href="/favicon.ico" />
|
||||
|
||||
<link
|
||||
id="appMode"
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
rel="preload"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<body style="margin: 0; padding: 0; box-sizing: border-box;">
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
|
||||
<script>
|
||||
const themeNode = document.getElementById('appMode');
|
||||
let userTheme = localStorage.getItem('theme') || "";
|
||||
|
||||
if (userTheme === 'lightMode') {
|
||||
themeNode.setAttribute('href', '/css/antd.min.css');
|
||||
} else {
|
||||
themeNode.setAttribute('href', '/css/antd.dark.min.css');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -2,6 +2,7 @@ import './wdyr';
|
||||
import './ReactI18';
|
||||
|
||||
import AppRoutes from 'AppRoutes';
|
||||
import { ThemeProvider } from 'hooks/useDarkMode';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||
@ -23,15 +24,17 @@ const queryClient = new QueryClient({
|
||||
});
|
||||
|
||||
ReactDOM.render(
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<Provider store={store}>
|
||||
<React.StrictMode>
|
||||
<AppRoutes />
|
||||
</React.StrictMode>
|
||||
</Provider>
|
||||
{process.env.NODE_ENV === 'development' && (
|
||||
<ReactQueryDevtools initialIsOpen />
|
||||
)}
|
||||
</QueryClientProvider>,
|
||||
<ThemeProvider>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<Provider store={store}>
|
||||
<React.StrictMode>
|
||||
<AppRoutes />
|
||||
</React.StrictMode>
|
||||
</Provider>
|
||||
{process.env.NODE_ENV === 'development' && (
|
||||
<ReactQueryDevtools initialIsOpen />
|
||||
)}
|
||||
</QueryClientProvider>
|
||||
</ThemeProvider>,
|
||||
document.querySelector('#root'),
|
||||
);
|
||||
|
@ -1,14 +0,0 @@
|
||||
import getLocalStorageKey from 'api/browser/localstorage/get';
|
||||
|
||||
import { AppMode } from './setTheme';
|
||||
|
||||
const getTheme = (): AppMode => {
|
||||
const userTheme = getLocalStorageKey('theme');
|
||||
if (userTheme === null || userTheme === 'darkMode') {
|
||||
return 'darkMode';
|
||||
}
|
||||
|
||||
return 'lightMode';
|
||||
};
|
||||
|
||||
export default getTheme;
|
@ -1,9 +0,0 @@
|
||||
import setLocalStorageKey from 'api/browser/localstorage/set';
|
||||
|
||||
const setTheme = (value: AppMode): void => {
|
||||
setLocalStorageKey('theme', value);
|
||||
};
|
||||
|
||||
export type AppMode = 'darkMode' | 'lightMode';
|
||||
|
||||
export default setTheme;
|
@ -1,84 +0,0 @@
|
||||
/* eslint-disable */
|
||||
//@ts-nocheck
|
||||
|
||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
import { Select } from 'antd';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import React, { useState } from 'react';
|
||||
import { ServicesItem } from 'store/actions';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
const Container = styled.div`
|
||||
margin-top: 12px;
|
||||
display: flex;
|
||||
.info {
|
||||
display: flex;
|
||||
font-family: Roboto;
|
||||
margin-left: auto;
|
||||
margin-right: 12px;
|
||||
color: #4f4f4f;
|
||||
font-size: 14px;
|
||||
.anticon-info-circle {
|
||||
margin-top: 22px;
|
||||
margin-right: 18px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
interface SelectServiceProps {
|
||||
services: ServicesItem[];
|
||||
zoomToService: (arg0: string) => void;
|
||||
zoomToDefault: () => void;
|
||||
}
|
||||
|
||||
const defaultOption = {
|
||||
serviceName: 'Default',
|
||||
};
|
||||
|
||||
function SelectService(props: SelectServiceProps): JSX.Element {
|
||||
const [selectedVal, setSelectedVal] = useState<string>(
|
||||
defaultOption.serviceName,
|
||||
);
|
||||
const { zoomToService, zoomToDefault, services } = props;
|
||||
const service = cloneDeep(services);
|
||||
service.unshift(defaultOption);
|
||||
|
||||
const handleSelect = (value: string): void => {
|
||||
if (value === defaultOption.serviceName) {
|
||||
zoomToDefault();
|
||||
} else {
|
||||
zoomToService(value);
|
||||
}
|
||||
setSelectedVal(value);
|
||||
};
|
||||
return (
|
||||
<Container>
|
||||
<Select
|
||||
style={{ width: 270, marginBottom: '56px' }}
|
||||
placeholder="Select a service"
|
||||
onChange={handleSelect}
|
||||
value={selectedVal}
|
||||
>
|
||||
{service.map(({ serviceName }) => (
|
||||
<Option key={serviceName} value={serviceName}>
|
||||
{serviceName}
|
||||
</Option>
|
||||
))}
|
||||
</Select>
|
||||
<div className="info">
|
||||
<InfoCircleOutlined />
|
||||
<div>
|
||||
<div>
|
||||
> Size of circles is proportial to the number of requests served by
|
||||
each node
|
||||
</div>
|
||||
<div>> Click on node name to reposition the node</div>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
export default SelectService;
|
@ -3,17 +3,16 @@
|
||||
|
||||
import { Card } from 'antd';
|
||||
import Spinner from 'components/Spinner';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { ForceGraph2D } from 'react-force-graph';
|
||||
import { connect, useSelector } from 'react-redux';
|
||||
import { connect } from 'react-redux';
|
||||
import { RouteComponentProps, withRouter } from 'react-router-dom';
|
||||
import { getDetailedServiceMapItems, ServiceMapStore } from 'store/actions';
|
||||
import { AppState } from 'store/reducers';
|
||||
import styled from 'styled-components';
|
||||
import { GlobalTime } from 'types/actions/globalTime';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
import SelectService from './SelectService';
|
||||
import { getGraphData, getTooltip, getZoomPx, transformLabel } from './utils';
|
||||
|
||||
const Container = styled.div`
|
||||
@ -61,7 +60,7 @@ export interface graphDataType {
|
||||
function ServiceMap(props: ServiceMapProps): JSX.Element {
|
||||
const fgRef = useRef();
|
||||
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
const { getDetailedServiceMapItems, globalTime, serviceMap } = props;
|
||||
|
||||
@ -89,25 +88,10 @@ function ServiceMap(props: ServiceMapProps): JSX.Element {
|
||||
);
|
||||
}
|
||||
|
||||
const zoomToService = (value: string): void => {
|
||||
fgRef &&
|
||||
fgRef.current &&
|
||||
fgRef.current.zoomToFit(700, getZoomPx(), (e) => e.id === value);
|
||||
};
|
||||
|
||||
const zoomToDefault = () => {
|
||||
fgRef && fgRef.current && fgRef.current.zoomToFit(100, 120);
|
||||
};
|
||||
|
||||
const { nodes, links } = getGraphData(serviceMap, isDarkMode);
|
||||
const graphData = { nodes, links };
|
||||
return (
|
||||
<Container>
|
||||
{/* <SelectService
|
||||
services={serviceMap.items}
|
||||
zoomToService={zoomToService}
|
||||
zoomToDefault={zoomToDefault}
|
||||
/> */}
|
||||
<ForceGraph2D
|
||||
ref={fgRef}
|
||||
cooldownTicks={100}
|
||||
@ -153,12 +137,10 @@ const mapStateToProps = (
|
||||
): {
|
||||
serviceMap: serviceMapStore;
|
||||
globalTime: GlobalTime;
|
||||
} => {
|
||||
return {
|
||||
serviceMap: state.serviceMap,
|
||||
globalTime: state.globalTime,
|
||||
};
|
||||
};
|
||||
} => ({
|
||||
serviceMap: state.serviceMap,
|
||||
globalTime: state.globalTime,
|
||||
});
|
||||
|
||||
export default withRouter(
|
||||
connect(mapStateToProps, {
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { Typography } from 'antd';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { AppState } from 'store/reducers';
|
||||
import AppReducer from 'types/reducer/app';
|
||||
|
||||
import { DocCardContainer } from './styles';
|
||||
import { TGetStartedContentDoc } from './types';
|
||||
@ -15,7 +13,7 @@ interface IDocCardProps {
|
||||
url: TGetStartedContentDoc['url'];
|
||||
}
|
||||
function DocCard({ icon, text, url }: IDocCardProps): JSX.Element {
|
||||
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||
const isDarkMode = useIsDarkMode();
|
||||
|
||||
return (
|
||||
<Link to={{ pathname: `${url}${UTMParams}` }} target="_blank">
|
||||
|
@ -1,2 +1 @@
|
||||
export * from './sideBarCollapse';
|
||||
export * from './toggleDarkMode';
|
||||
|
@ -1,12 +0,0 @@
|
||||
import { Dispatch } from 'redux';
|
||||
import AppActions from 'types/actions';
|
||||
|
||||
export const ToggleDarkMode = (): ((
|
||||
dispatch: Dispatch<AppActions>,
|
||||
) => void) => {
|
||||
return (dispatch: Dispatch<AppActions>): void => {
|
||||
dispatch({
|
||||
type: 'SWITCH_DARK_MODE',
|
||||
});
|
||||
};
|
||||
};
|
@ -1,13 +1,11 @@
|
||||
import getLocalStorageKey from 'api/browser/localstorage/get';
|
||||
import { IS_SIDEBAR_COLLAPSED } from 'constants/app';
|
||||
import { LOCALSTORAGE } from 'constants/localStorage';
|
||||
import getTheme from 'lib/theme/getTheme';
|
||||
import { getInitialUserTokenRefreshToken } from 'store/utils';
|
||||
import {
|
||||
AppAction,
|
||||
LOGGED_IN,
|
||||
SIDEBAR_COLLAPSE,
|
||||
SWITCH_DARK_MODE,
|
||||
UPDATE_CONFIGS,
|
||||
UPDATE_CURRENT_ERROR,
|
||||
UPDATE_CURRENT_VERSION,
|
||||
@ -45,7 +43,6 @@ const getInitialUser = (): User | null => {
|
||||
};
|
||||
|
||||
const InitialValue: InitialValueTypes = {
|
||||
isDarkMode: getTheme() === 'darkMode',
|
||||
isLoggedIn: getLocalStorageKey(LOCALSTORAGE.IS_LOGGED_IN) === 'true',
|
||||
isSideBarCollapsed: getLocalStorageKey(IS_SIDEBAR_COLLAPSED) === 'true',
|
||||
currentVersion: '',
|
||||
@ -67,13 +64,6 @@ const appReducer = (
|
||||
action: AppAction,
|
||||
): InitialValueTypes => {
|
||||
switch (action.type) {
|
||||
case SWITCH_DARK_MODE: {
|
||||
return {
|
||||
...state,
|
||||
isDarkMode: !state.isDarkMode,
|
||||
};
|
||||
}
|
||||
|
||||
case LOGGED_IN: {
|
||||
return {
|
||||
...state,
|
||||
|
@ -7,7 +7,6 @@ import { UserFlags } from 'types/api/user/setFlags';
|
||||
import AppReducer, { User } from 'types/reducer/app';
|
||||
import { ROLES } from 'types/roles';
|
||||
|
||||
export const SWITCH_DARK_MODE = 'SWITCH_DARK_MODE';
|
||||
export const LOGGED_IN = 'LOGGED_IN';
|
||||
export const SIDEBAR_COLLAPSE = 'SIDEBAR_COLLAPSE';
|
||||
|
||||
@ -27,10 +26,6 @@ export const UPDATE_FEATURE_FLAGS = 'UPDATE_FEATURE_FLAGS';
|
||||
export const UPDATE_CONFIGS = 'UPDATE_CONFIGS';
|
||||
export const UPDATE_USER_FLAG = 'UPDATE_USER_FLAG';
|
||||
|
||||
export interface SwitchDarkMode {
|
||||
type: typeof SWITCH_DARK_MODE;
|
||||
}
|
||||
|
||||
export interface LoggedInUser {
|
||||
type: typeof LOGGED_IN;
|
||||
payload: {
|
||||
@ -134,7 +129,6 @@ export interface UpdateConfigs {
|
||||
}
|
||||
|
||||
export type AppAction =
|
||||
| SwitchDarkMode
|
||||
| LoggedInUser
|
||||
| SideBarCollapse
|
||||
| UpdateAppVersion
|
||||
|
@ -102,7 +102,7 @@ export interface SetLogsAggregateSeries {
|
||||
}
|
||||
export interface SetDetailedLogData {
|
||||
type: typeof SET_DETAILED_LOG_DATA;
|
||||
payload: ILog;
|
||||
payload: ILog | null;
|
||||
}
|
||||
|
||||
export interface ToggleLiveTail {
|
||||
|
@ -15,7 +15,6 @@ export interface User {
|
||||
}
|
||||
|
||||
export default interface AppReducer {
|
||||
isDarkMode: boolean;
|
||||
isLoggedIn: boolean;
|
||||
isSideBarCollapsed: boolean;
|
||||
currentVersion: string;
|
||||
|
7593
frontend/yarn.lock
7593
frontend/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user