Merge branch 'develop' of github.com:SigNoz/signoz into pranshuchittora/feat/y-axis-unit-selection

This commit is contained in:
Pranshu Chittora 2022-03-16 16:24:40 +05:30
commit 17738a58a2
No known key found for this signature in database
GPG Key ID: 3A9E57A016CC0626
108 changed files with 575 additions and 542 deletions

View File

@ -52,14 +52,11 @@ jobs:
helm install my-release signoz/signoz -n platform \ helm install my-release signoz/signoz -n platform \
--wait \ --wait \
--timeout 10m0s \ --timeout 10m0s \
--set cloud=null \
--set frontend.service.type=LoadBalancer \ --set frontend.service.type=LoadBalancer \
--set query-service.image.tag=$DOCKER_TAG \ --set queryService.image.tag=$DOCKER_TAG \
--set frontend.image.tag=$DOCKER_TAG --set frontend.image.tag=$DOCKER_TAG
# get pods, services and the container images # get pods, services and the container images
kubectl describe deploy/my-release-frontend -n platform | grep Image
kubectl describe statefulset/my-release-query-service -n platform | grep Image
kubectl get pods -n platform kubectl get pods -n platform
kubectl get svc -n platform kubectl get svc -n platform

View File

@ -34,8 +34,10 @@ SigNoz helps developers monitor applications and troubleshoot problems in their
![screenzy-1644432902955](https://user-images.githubusercontent.com/504541/153270713-1b2156e6-ec03-42de-975b-3c02b8ec1836.png) ![screenzy-1644432902955](https://user-images.githubusercontent.com/504541/153270713-1b2156e6-ec03-42de-975b-3c02b8ec1836.png)
<br />
![screenzy-1644432986784](https://user-images.githubusercontent.com/504541/153270725-0efb73b3-06ed-4207-bf13-9b7e2e17c4b8.png) ![screenzy-1644432986784](https://user-images.githubusercontent.com/504541/153270725-0efb73b3-06ed-4207-bf13-9b7e2e17c4b8.png)
<br />
![screenzy-1647005040573](https://user-images.githubusercontent.com/504541/157875938-a3d57904-ea6d-4278-b929-bd1408d7f94c.png)
<br /><br /> <br /><br />

View File

@ -1,13 +1,10 @@
const resizeObserverLoopErrRe = /ResizeObserver loop limit exceeded/; const resizeObserverLoopErrRe = /ResizeObserver loop limit exceeded/;
const unCaughtExpection = () => { const unCaughtExpection = (): void => {
cy.on('uncaught:exception', (err) => { cy.on('uncaught:exception', (err) => {
if (resizeObserverLoopErrRe.test(err.message)) {
// returning false here prevents Cypress from // returning false here prevents Cypress from
// failing the test // failing the test
return false; return !resizeObserverLoopErrRe.test(err.message);
}
return true;
}); });
}; };

View File

@ -4,6 +4,8 @@ import ROUTES from 'constants/routes';
import defaultRules from '../../fixtures/defaultRules.json'; import defaultRules from '../../fixtures/defaultRules.json';
const defaultRuleRoutes = `**/rules/**`;
describe('Alerts', () => { describe('Alerts', () => {
beforeEach(() => { beforeEach(() => {
window.localStorage.setItem('isLoggedIn', 'yes'); window.localStorage.setItem('isLoggedIn', 'yes');
@ -21,7 +23,7 @@ describe('Alerts', () => {
it('Edit Rules Page Failure', async () => { it('Edit Rules Page Failure', async () => {
cy cy
.intercept('**/rules/**', { .intercept(defaultRuleRoutes, {
statusCode: 500, statusCode: 500,
}) })
.as('Get Rules Error'); .as('Get Rules Error');
@ -49,7 +51,7 @@ describe('Alerts', () => {
const text = 'this is the sample value'; const text = 'this is the sample value';
cy cy
.intercept('**/rules/**', { .intercept(defaultRuleRoutes, {
statusCode: 200, statusCode: 200,
body: { body: {
data: { data: {
@ -103,7 +105,7 @@ describe('Alerts', () => {
it('Rules are Deleted', async () => { it('Rules are Deleted', async () => {
cy cy
.intercept('**/rules/**', { .intercept(defaultRuleRoutes, {
body: { body: {
data: 'Deleted', data: 'Deleted',
message: 'Success', message: 'Success',

View File

@ -1,9 +1,15 @@
/* eslint-disable sonarjs/no-duplicate-string */
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import { TraceFilterEnum } from 'types/reducer/trace';
import TableInitialResponse from '../../fixtures/trace/initialSpans.json';
import FilterInitialResponse from '../../fixtures/trace/initialSpanFilter.json';
import GraphInitialResponse from '../../fixtures/trace/initialAggregates.json';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { TraceFilterEnum } from 'types/reducer/trace';
import GraphInitialResponse from '../../fixtures/trace/initialAggregates.json';
import FilterInitialResponse from '../../fixtures/trace/initialSpanFilter.json';
import TableInitialResponse from '../../fixtures/trace/initialSpans.json';
const allFilters = '@Filters.all';
const allGraphs = '@Graph.all';
const allTable = '@Table.all';
describe('Trace', () => { describe('Trace', () => {
beforeEach(() => { beforeEach(() => {
@ -74,9 +80,9 @@ describe('Trace', () => {
JSON.stringify(TableInitialResponse), JSON.stringify(TableInitialResponse),
); );
}); });
cy.get('@Filters.all').should('have.length', 1); cy.get(allFilters).should('have.length', 1);
cy.get('@Graph.all').should('have.length', 1); cy.get(allGraphs).should('have.length', 1);
cy.get('@Table.all').should('have.length', 1); cy.get(allTable).should('have.length', 1);
}); });
it('Clear All', () => { it('Clear All', () => {
@ -102,9 +108,9 @@ describe('Trace', () => {
cy.wait(['@Filters', '@Graph', '@Table']); cy.wait(['@Filters', '@Graph', '@Table']);
// insuring the api get call // insuring the api get call
cy.get('@Filters.all').should('have.length', 2); cy.get(allFilters).should('have.length', 2);
cy.get('@Graph.all').should('have.length', 2); cy.get(allGraphs).should('have.length', 2);
cy.get('@Table.all').should('have.length', 2); cy.get(allTable).should('have.length', 2);
cy cy
.window() .window()
@ -146,9 +152,9 @@ describe('Trace', () => {
expect(tableBody.exclude[0] === 'status').to.be.true; expect(tableBody.exclude[0] === 'status').to.be.true;
}); });
cy.get('@Filters.all').should('have.length', 2); cy.get(allFilters).should('have.length', 2);
cy.get('@Graph.all').should('have.length', 2); cy.get(allGraphs).should('have.length', 2);
cy.get('@Table.all').should('have.length', 2); cy.get(allTable).should('have.length', 2);
}); });
}); });
}); });

View File

@ -11,7 +11,6 @@ import AppReducer from 'types/reducer/app';
import routes from './routes'; import routes from './routes';
const App = (): JSX.Element => { const App = (): JSX.Element => {
const { isLoggedIn } = useSelector<AppState, AppReducer>((state) => state.app); const { isLoggedIn } = useSelector<AppState, AppReducer>((state) => state.app);
@ -20,8 +19,8 @@ const App = (): JSX.Element => {
<AppLayout> <AppLayout>
<Suspense fallback={<Spinner size="large" tip="Loading..." />}> <Suspense fallback={<Spinner size="large" tip="Loading..." />}>
<Switch> <Switch>
{routes.map(({ path, component, exact }, index) => ( {routes.map(({ path, component, exact }) => (
<Route key={index} exact={exact} path={path} component={component} /> <Route key={`${path}`} exact={exact} path={path} component={component} />
))} ))}
<Route <Route
path="/" path="/"
@ -42,5 +41,4 @@ const App = (): JSX.Element => {
); );
}; };
export default App; export default App;

View File

@ -17,8 +17,8 @@ import {
ServicesTablePage, ServicesTablePage,
SettingsPage, SettingsPage,
SignupPage, SignupPage,
TraceFilter,
TraceDetail, TraceDetail,
TraceFilter,
UsageExplorerPage, UsageExplorerPage,
} from './pageComponents'; } from './pageComponents';

View File

@ -1,9 +1,9 @@
import { AxiosAlertManagerInstance } from 'api'; import { AxiosAlertManagerInstance } from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler'; import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import convertObjectIntoParams from 'lib/query/convertObjectIntoParams';
import { ErrorResponse, SuccessResponse } from 'types/api'; import { ErrorResponse, SuccessResponse } from 'types/api';
import { PayloadProps, Props } from 'types/api/alerts/getGroups'; import { PayloadProps, Props } from 'types/api/alerts/getGroups';
import convertObjectIntoParams from 'lib/query/convertObjectIntoParams';
const getGroups = async ( const getGroups = async (
props: Props, props: Props,

View File

@ -1,7 +1,6 @@
const get = (key: string): string | null => { const get = (key: string): string | null => {
try { try {
const value = localStorage.getItem(key); return localStorage.getItem(key);
return value;
} catch (e) { } catch (e) {
return ''; return '';
} }

View File

@ -1,9 +1,9 @@
import axios from 'api'; import axios from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler'; import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import omitBy from 'lodash-es/omitBy';
import { ErrorResponse, SuccessResponse } from 'types/api'; import { ErrorResponse, SuccessResponse } from 'types/api';
import { PayloadProps, Props } from 'types/api/trace/getFilters'; import { PayloadProps, Props } from 'types/api/trace/getFilters';
import omitBy from 'lodash-es/omitBy';
const getFilters = async ( const getFilters = async (
props: Props, props: Props,

View File

@ -2,7 +2,7 @@ import axios from 'api';
import { ErrorResponseHandler } from 'api/ErrorResponseHandler'; import { ErrorResponseHandler } from 'api/ErrorResponseHandler';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import { ErrorResponse, SuccessResponse } from 'types/api'; import { ErrorResponse, SuccessResponse } from 'types/api';
import { Props, PayloadProps } from 'types/api/trace/getTraceItem'; import { PayloadProps, Props } from 'types/api/trace/getTraceItem';
const getTraceItem = async ( const getTraceItem = async (
props: Props, props: Props,

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
const TimeSeries = (props: TimeSeriesProps): JSX.Element => ( const TimeSeries = (): JSX.Element => (
<React.Fragment> <React.Fragment>
<svg <svg
width="81" width="81"
@ -34,9 +34,4 @@ const TimeSeries = (props: TimeSeriesProps): JSX.Element => (
</React.Fragment> </React.Fragment>
); );
export interface TimeSeriesProps{
fillColor: React.CSSProperties['color'];
}
export default TimeSeries; export default TimeSeries;

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
const Value = (props: ValueProps): JSX.Element => { const Value = (props: ValueProps): JSX.Element => {
return( return (
<React.Fragment> <React.Fragment>
<svg <svg
width="78" width="78"
@ -16,9 +16,10 @@ const Value = (props: ValueProps): JSX.Element => {
/> />
</svg> </svg>
</React.Fragment> </React.Fragment>
)}; );
};
interface ValueProps{ interface ValueProps {
fillColor: React.CSSProperties['color']; fillColor: React.CSSProperties['color'];
} }

View File

@ -1,6 +1,6 @@
import generatePicker from 'antd/es/date-picker/generatePicker';
import { Dayjs } from 'dayjs'; import { Dayjs } from 'dayjs';
import dayjsGenerateConfig from 'rc-picker/lib/generate/dayjs'; import dayjsGenerateConfig from 'rc-picker/lib/generate/dayjs';
import generatePicker from 'antd/es/date-picker/generatePicker';
const DatePicker = generatePicker<Dayjs>(dayjsGenerateConfig); const DatePicker = generatePicker<Dayjs>(dayjsGenerateConfig);

View File

@ -1,7 +1,11 @@
import { Plugin, ChartType, Chart, ChartOptions } from 'chart.js'; import { Chart, ChartType, Plugin } from 'chart.js';
import { colors } from 'lib/getRandomColor'; import { colors } from 'lib/getRandomColor';
const getOrCreateLegendList = (chart: Chart, id: string, isLonger: boolean) => { const getOrCreateLegendList = (
chart: Chart,
id: string,
isLonger: boolean,
): HTMLUListElement => {
const legendContainer = document.getElementById(id); const legendContainer = document.getElementById(id);
let listContainer = legendContainer?.querySelector('ul'); let listContainer = legendContainer?.querySelector('ul');
@ -27,7 +31,7 @@ const getOrCreateLegendList = (chart: Chart, id: string, isLonger: boolean) => {
export const legend = (id: string, isLonger: boolean): Plugin<ChartType> => { export const legend = (id: string, isLonger: boolean): Plugin<ChartType> => {
return { return {
id: 'htmlLegend', id: 'htmlLegend',
afterUpdate(chart, args, options: ChartOptions) { afterUpdate(chart): void {
const ul = getOrCreateLegendList(chart, id || 'legend', isLonger); const ul = getOrCreateLegendList(chart, id || 'legend', isLonger);
// Remove old legend items // Remove old legend items
@ -46,7 +50,7 @@ export const legend = (id: string, isLonger: boolean): Plugin<ChartType> => {
li.style.marginLeft = '10px'; li.style.marginLeft = '10px';
li.style.marginTop = '5px'; li.style.marginTop = '5px';
li.onclick = () => { li.onclick = (): void => {
const { type } = chart.config; const { type } = chart.config;
if (type === 'pie' || type === 'doughnut') { if (type === 'pie' || type === 'doughnut') {
// Pie and doughnut charts only have a single dataset and visibility is per item // Pie and doughnut charts only have a single dataset and visibility is per item

View File

@ -77,8 +77,8 @@ export const useXAxisTimeUnit = (data: Chart['data']): IAxisTimeConfig => {
try { try {
let minTime = Number.POSITIVE_INFINITY; let minTime = Number.POSITIVE_INFINITY;
let maxTime = Number.NEGATIVE_INFINITY; let maxTime = Number.NEGATIVE_INFINITY;
data?.labels?.forEach((timeStamp: any) => { data?.labels?.forEach((timeStamp: string | number): void => {
timeStamp = Date.parse(timeStamp); if (typeof timeStamp === 'string') timeStamp = Date.parse(timeStamp);
minTime = Math.min(timeStamp, minTime); minTime = Math.min(timeStamp, minTime);
maxTime = Math.max(timeStamp, maxTime); maxTime = Math.max(timeStamp, maxTime);
}); });

View File

@ -3,9 +3,7 @@ import { ComponentType, lazy } from 'react';
function Loadable(importPath: { function Loadable(importPath: {
(): LoadableProps; (): LoadableProps;
}): React.LazyExoticComponent<LazyComponent> { }): React.LazyExoticComponent<LazyComponent> {
const LazyComponent = lazy(() => importPath()); return lazy(() => importPath());
return LazyComponent;
} }
type LazyComponent = ComponentType<Record<string, unknown>>; type LazyComponent = ComponentType<Record<string, unknown>>;

View File

@ -1,5 +1,5 @@
import React from 'react';
import { Tabs, TabsProps } from 'antd'; import { Tabs, TabsProps } from 'antd';
import React from 'react';
const { TabPane } = Tabs; const { TabPane } = Tabs;
import history from 'lib/history'; import history from 'lib/history';

View File

@ -10,7 +10,7 @@ import React, { useCallback } from 'react';
const { Paragraph } = Typography; const { Paragraph } = Typography;
import AlertChannlesComponent from './AlertChannels'; import AlertChannlesComponent from './AlertChannels';
import { ButtonContainer, Button } from './styles'; import { Button, ButtonContainer } from './styles';
const AlertChannels = (): JSX.Element => { const AlertChannels = (): JSX.Element => {
const onToggleHandler = useCallback(() => { const onToggleHandler = useCallback(() => {

View File

@ -1,5 +1,5 @@
import styled from 'styled-components';
import { Button as ButtonComponent } from 'antd'; import { Button as ButtonComponent } from 'antd';
import styled from 'styled-components';
export const ButtonContainer = styled.div` export const ButtonContainer = styled.div`
&&& { &&& {

View File

@ -7,7 +7,7 @@ import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import AppReducer from 'types/reducer/app'; import AppReducer from 'types/reducer/app';
import { Content, Footer, Layout } from './styles'; import { Content, Layout } from './styles';
const AppLayout: React.FC<AppLayoutProps> = ({ children }) => { const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
const { isLoggedIn } = useSelector<AppState, AppReducer>((state) => state.app); const { isLoggedIn } = useSelector<AppState, AppReducer>((state) => state.app);
@ -27,8 +27,6 @@ const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
} }
}, [isLoggedIn, isSignUpPage]); }, [isLoggedIn, isSignUpPage]);
const currentYear = new Date().getFullYear();
return ( return (
<Layout> <Layout>
{!isSignUpPage && <SideNav />} {!isSignUpPage && <SideNav />}
@ -37,7 +35,6 @@ const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
{!isSignUpPage && <TopNav />} {!isSignUpPage && <TopNav />}
{children} {children}
</Content> </Content>
{/* <Footer>{`SigNoz Inc. © ${currentYear}`}</Footer> */}
</Layout> </Layout>
</Layout> </Layout>
); );

View File

@ -16,10 +16,3 @@ export const Content = styled(LayoutComponent.Content)`
flex-direction: column; flex-direction: column;
} }
`; `;
export const Footer = styled(LayoutComponent.Footer)`
&&& {
text-align: center;
font-size: 0.7rem;
}
`;

View File

@ -1,9 +1,13 @@
import { Tooltip, Typography } from 'antd'; import { Tooltip, Typography } from 'antd';
import React from 'react'; import {
import { SpanBorder, SpanText, SpanWrapper, SpanLine } from './styles'; IIntervalUnit,
import { toFixed } from 'utils/toFixed' resolveTimeFromInterval,
import { IIntervalUnit, resolveTimeFromInterval } from 'container/TraceDetail/utils'; } from 'container/TraceDetail/utils';
import useThemeMode from 'hooks/useThemeMode'; import useThemeMode from 'hooks/useThemeMode';
import React from 'react';
import { toFixed } from 'utils/toFixed';
import { SpanBorder, SpanLine, SpanText, SpanWrapper } from './styles';
interface SpanLengthProps { interface SpanLengthProps {
width: string; width: string;
leftOffset: string; leftOffset: string;
@ -16,12 +20,15 @@ interface SpanLengthProps {
const SpanLength = (props: SpanLengthProps): JSX.Element => { const SpanLength = (props: SpanLengthProps): JSX.Element => {
const { width, leftOffset, bgColor, intervalUnit } = props; const { width, leftOffset, bgColor, intervalUnit } = props;
const { isDarkMode } = useThemeMode() const { isDarkMode } = useThemeMode();
return ( return (
<SpanWrapper> <SpanWrapper>
<SpanLine leftOffset={leftOffset} isDarkMode={isDarkMode} /> <SpanLine leftOffset={leftOffset} isDarkMode={isDarkMode} />
<SpanBorder bgColor={bgColor} leftOffset={leftOffset} width={width} /> <SpanBorder bgColor={bgColor} leftOffset={leftOffset} width={width} />
<SpanText leftOffset={leftOffset} isDarkMode={isDarkMode}>{`${toFixed(resolveTimeFromInterval(props.inMsCount, intervalUnit), 2)} ${intervalUnit.name}`}</SpanText> <SpanText leftOffset={leftOffset} isDarkMode={isDarkMode}>{`${toFixed(
resolveTimeFromInterval(props.inMsCount, intervalUnit),
2,
)} ${intervalUnit.name}`}</SpanText>
</SpanWrapper> </SpanWrapper>
); );
}; };

View File

@ -1,11 +1,12 @@
import React from 'react'; import React from 'react';
import { import {
Container,
Service, Service,
Span, Span,
SpanWrapper,
SpanConnector, SpanConnector,
Container,
SpanName, SpanName,
SpanWrapper,
} from './styles'; } from './styles';
const SpanNameComponent = ({ const SpanNameComponent = ({

View File

@ -1,5 +1,5 @@
import styled from 'styled-components';
import { Typography } from 'antd'; import { Typography } from 'antd';
import styled from 'styled-components';
export const Span = styled(Typography.Paragraph)` export const Span = styled(Typography.Paragraph)`
&&& { &&& {

View File

@ -1,22 +1,25 @@
import React, { useRef, useState, useEffect } from 'react'; import { CaretDownFilled, CaretRightFilled } from '@ant-design/icons';
import { Col, Row } from 'antd';
import {
IIntervalUnit,
resolveTimeFromInterval,
} from 'container/TraceDetail/utils';
import useThemeMode from 'hooks/useThemeMode';
import { SPAN_DETAILS_LEFT_COL_WIDTH } from 'pages/TraceDetail/constants';
import React, { useEffect, useRef, useState } from 'react';
import { pushDStree } from 'store/actions';
import { ITraceMetaData } from '..';
import SpanLength from '../SpanLength';
import SpanName from '../SpanName';
import { getMetaDataFromSpanTree, getTopLeftFromBody } from '../utils';
import { import {
CardComponent, CardComponent,
CardContainer, CardContainer,
CaretContainer, CaretContainer,
Wrapper,
HoverCard, HoverCard,
Wrapper,
} from './styles'; } from './styles';
import { CaretDownFilled, CaretRightFilled } from '@ant-design/icons';
import SpanLength from '../SpanLength';
import SpanName from '../SpanName';
import { pushDStree } from 'store/actions';
import { getMetaDataFromSpanTree, getTopLeftFromBody } from '../utils';
import { ITraceMetaData } from '..';
import { Col, Row } from 'antd';
import { SPAN_DETAILS_LEFT_COL_WIDTH } from 'pages/TraceDetail/constants'
import { IIntervalUnit, resolveTimeFromInterval } from 'container/TraceDetail/utils';
import useThemeMode from 'hooks/useThemeMode';
const Trace = (props: TraceProps): JSX.Element => { const Trace = (props: TraceProps): JSX.Element => {
const { const {
@ -38,7 +41,7 @@ const Trace = (props: TraceProps): JSX.Element => {
intervalUnit, intervalUnit,
} = props; } = props;
const { isDarkMode } = useThemeMode() const { isDarkMode } = useThemeMode();
const [isOpen, setOpen] = useState<boolean>(activeSpanPath[level] === id); 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. 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.
@ -47,20 +50,18 @@ const Trace = (props: TraceProps): JSX.Element => {
if (localTreeExpandInteraction.current !== 0) { if (localTreeExpandInteraction.current !== 0) {
setOpen(localTreeExpandInteraction.current); setOpen(localTreeExpandInteraction.current);
localTreeExpandInteraction.current = 0; localTreeExpandInteraction.current = 0;
} else if (!isOpen) {
setOpen(activeSpanPath[level] === id);
} }
else if (!isOpen) { }, [activeSpanPath, isOpen]);
setOpen(activeSpanPath[level] === id)
}
}, [activeSpanPath, isOpen])
useEffect(() => { useEffect(() => {
if (isExpandAll) { if (isExpandAll) {
setOpen(isExpandAll) setOpen(isExpandAll);
} else {
setOpen(activeSpanPath[level] === id);
} }
else { }, [isExpandAll]);
setOpen(activeSpanPath[level] === id)
}
}, [isExpandAll])
const isOnlyChild = props.children.length === 1; const isOnlyChild = props.children.length === 1;
const [top, setTop] = useState<number>(0); const [top, setTop] = useState<number>(0);
@ -69,9 +70,13 @@ const Trace = (props: TraceProps): JSX.Element => {
React.useEffect(() => { React.useEffect(() => {
if (activeSelectedId === id) { if (activeSelectedId === id) {
ref.current?.scrollIntoView({ block: 'nearest', behavior: 'auto', inline: 'nearest' }); ref.current?.scrollIntoView({
block: 'nearest',
behavior: 'auto',
inline: 'nearest',
});
} }
}, [activeSelectedId]) }, [activeSelectedId]);
const onMouseEnterHandler = () => { const onMouseEnterHandler = () => {
setActiveHoverId(props.id); setActiveHoverId(props.id);
@ -87,18 +92,21 @@ const Trace = (props: TraceProps): JSX.Element => {
const onClick = () => { const onClick = () => {
setActiveSelectedId(id); setActiveSelectedId(id);
} };
const onClickTreeExpansion = (event) => { const onClickTreeExpansion = (event) => {
event.stopPropagation() event.stopPropagation();
setOpen((state) => { localTreeExpandInteraction.current = !isOpen; return !state }); setOpen((state) => {
} localTreeExpandInteraction.current = !isOpen;
return !state;
});
};
const { totalSpans } = getMetaDataFromSpanTree(props); const { totalSpans } = getMetaDataFromSpanTree(props);
const inMsCount = value; const inMsCount = value;
const nodeLeftOffset = ((startTime - globalStart) * 1e2) / globalSpread; const nodeLeftOffset = ((startTime - globalStart) * 1e2) / globalSpread;
const width = (value * 1e2) / (globalSpread * 1e6); const width = (value * 1e2) / (globalSpread * 1e6);
const panelWidth = SPAN_DETAILS_LEFT_COL_WIDTH - (level * (16 + 1)) - 16; const panelWidth = SPAN_DETAILS_LEFT_COL_WIDTH - level * (16 + 1) - 16;
return ( return (
<> <>
@ -115,17 +123,12 @@ const Trace = (props: TraceProps): JSX.Element => {
isDarkMode={isDarkMode} isDarkMode={isDarkMode}
/> />
<CardContainer <CardContainer onClick={onClick}>
onClick={onClick}
>
<Col flex={`${panelWidth}px`} style={{ overflow: 'hidden' }}> <Col flex={`${panelWidth}px`} style={{ overflow: 'hidden' }}>
<Row style={{ flexWrap: 'nowrap' }}> <Row style={{ flexWrap: 'nowrap' }}>
<Col> <Col>
{totalSpans !== 1 && ( {totalSpans !== 1 && (
<CardComponent <CardComponent isDarkMode={isDarkMode} onClick={onClickTreeExpansion}>
isDarkMode={isDarkMode}
onClick={onClickTreeExpansion}
>
{totalSpans} {totalSpans}
<CaretContainer> <CaretContainer>
{isOpen ? <CaretDownFilled /> : <CaretRightFilled />} {isOpen ? <CaretDownFilled /> : <CaretRightFilled />}
@ -138,13 +141,13 @@ const Trace = (props: TraceProps): JSX.Element => {
</Col> </Col>
</Row> </Row>
</Col> </Col>
<Col flex={'1'} > <Col flex={'1'}>
<SpanLength <SpanLength
leftOffset={nodeLeftOffset.toString()} leftOffset={nodeLeftOffset.toString()}
width={width.toString()} width={width.toString()}
bgColor={serviceColour} bgColor={serviceColour}
id={id} id={id}
inMsCount={(inMsCount / 1e6)} inMsCount={inMsCount / 1e6}
intervalUnit={intervalUnit} intervalUnit={intervalUnit}
/> />
</Col> </Col>

View File

@ -1,11 +1,12 @@
import { MinusSquareOutlined, PlusSquareOutlined } from '@ant-design/icons';
import { IIntervalUnit } from 'container/TraceDetail/utils';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import Trace from './Trace';
import { MinusSquareOutlined, PlusSquareOutlined } from '@ant-design/icons'
import { Wrapper, CardWrapper, CardContainer, CollapseButton } from './styles';
import { getSpanPath } from './utils';
import { IIntervalUnit } from 'container/TraceDetail/utils'
import { ITraceTree } from 'types/api/trace/getTraceItem'; import { ITraceTree } from 'types/api/trace/getTraceItem';
import { CardContainer, CardWrapper, CollapseButton, Wrapper } from './styles';
import Trace from './Trace';
import { getSpanPath } from './utils';
const GanttChart = (props: GanttChartProps): JSX.Element => { const GanttChart = (props: GanttChartProps): JSX.Element => {
const { const {
data, data,
@ -15,7 +16,7 @@ const GanttChart = (props: GanttChartProps): JSX.Element => {
activeSelectedId, activeSelectedId,
setActiveSelectedId, setActiveSelectedId,
spanId, spanId,
intervalUnit intervalUnit,
} = props; } = props;
const { globalStart, spread: globalSpread } = traceMetaData; const { globalStart, spread: globalSpread } = traceMetaData;
@ -24,11 +25,11 @@ const GanttChart = (props: GanttChartProps): JSX.Element => {
const [activeSpanPath, setActiveSpanPath] = useState<string[]>([]); const [activeSpanPath, setActiveSpanPath] = useState<string[]>([]);
useEffect(() => { useEffect(() => {
setActiveSpanPath(getSpanPath(data, spanId)) setActiveSpanPath(getSpanPath(data, spanId));
}, [spanId]); }, [spanId]);
useEffect(() => { useEffect(() => {
setActiveSpanPath(getSpanPath(data, activeSelectedId)) setActiveSpanPath(getSpanPath(data, activeSelectedId));
}, [activeSelectedId]); }, [activeSelectedId]);
const handleCollapse = () => { const handleCollapse = () => {
@ -38,7 +39,11 @@ const GanttChart = (props: GanttChartProps): JSX.Element => {
<> <>
<Wrapper> <Wrapper>
<CardContainer> <CardContainer>
<CollapseButton onClick={handleCollapse} style={{ fontSize: '1.2rem' }} title={isExpandAll ? 'Collapse All' : "Expand All"}> <CollapseButton
onClick={handleCollapse}
style={{ fontSize: '1.2rem' }}
title={isExpandAll ? 'Collapse All' : 'Expand All'}
>
{isExpandAll ? <MinusSquareOutlined /> : <PlusSquareOutlined />} {isExpandAll ? <MinusSquareOutlined /> : <PlusSquareOutlined />}
</CollapseButton> </CollapseButton>
<CardWrapper> <CardWrapper>
@ -81,7 +86,7 @@ export interface GanttChartProps {
setActiveHoverId: React.Dispatch<React.SetStateAction<string>>; setActiveHoverId: React.Dispatch<React.SetStateAction<string>>;
setActiveSelectedId: React.Dispatch<React.SetStateAction<string>>; setActiveSelectedId: React.Dispatch<React.SetStateAction<string>>;
spanId: string; spanId: string;
intervalUnit: IIntervalUnit intervalUnit: IIntervalUnit;
} }
export default GanttChart; export default GanttChart;

View File

@ -5,7 +5,7 @@ export const getMetaDataFromSpanTree = (treeData: ITraceTree) => {
let globalEnd = Number.NEGATIVE_INFINITY; let globalEnd = Number.NEGATIVE_INFINITY;
let totalSpans = 0; let totalSpans = 0;
let levels = 1; let levels = 1;
const traverse = (treeNode: ITraceTree, level: number = 0) => { const traverse = (treeNode: ITraceTree, level = 0) => {
if (!treeNode) { if (!treeNode) {
return; return;
} }
@ -35,19 +35,19 @@ export const getMetaDataFromSpanTree = (treeData: ITraceTree) => {
}; };
export function getTopLeftFromBody(elem: HTMLElement) { export function getTopLeftFromBody(elem: HTMLElement) {
let box = elem.getBoundingClientRect(); const box = elem.getBoundingClientRect();
let body = document.body; const body = document.body;
let docEl = document.documentElement; const docEl = document.documentElement;
let scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop; const scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
let scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft; const scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
let clientTop = docEl.clientTop || body.clientTop || 0; const clientTop = docEl.clientTop || body.clientTop || 0;
let clientLeft = docEl.clientLeft || body.clientLeft || 0; const clientLeft = docEl.clientLeft || body.clientLeft || 0;
let top = box.top + scrollTop - clientTop; const top = box.top + scrollTop - clientTop;
let left = box.left + scrollLeft - clientLeft; const left = box.left + scrollLeft - clientLeft;
return { top: Math.round(top), left: Math.round(left) }; return { top: Math.round(top), left: Math.round(left) };
} }
@ -57,7 +57,7 @@ export const getNodeById = (
treeData: ITraceTree, treeData: ITraceTree,
): ITraceTree | undefined => { ): ITraceTree | undefined => {
let foundNode: ITraceTree | undefined = undefined; let foundNode: ITraceTree | undefined = undefined;
const traverse = (treeNode: ITraceTree, level: number = 0) => { const traverse = (treeNode: ITraceTree, level = 0) => {
if (!treeNode) { if (!treeNode) {
return; return;
} }
@ -115,7 +115,7 @@ export const isSpanPresent = (
const traverse = ( const traverse = (
treeNode: ITraceTree, treeNode: ITraceTree,
level: number = 0, level = 0,
foundNode: ITraceTree[], foundNode: ITraceTree[],
) => { ) => {
if (!treeNode) { if (!treeNode) {

View File

@ -23,7 +23,7 @@ import { Widgets } from 'types/api/dashboard/getAll';
import Bar from './Bar'; import Bar from './Bar';
import FullView from './FullView'; import FullView from './FullView';
import { Modal, FullViewContainer, ErrorContainer } from './styles'; import { ErrorContainer, FullViewContainer, Modal } from './styles';
const GridCardGraph = ({ const GridCardGraph = ({
widget, widget,

View File

@ -7,8 +7,8 @@ const { Option } = DefaultSelect;
import getLocalStorageKey from 'api/browser/localstorage/get'; import getLocalStorageKey from 'api/browser/localstorage/get';
import setLocalStorageKey from 'api/browser/localstorage/set'; import setLocalStorageKey from 'api/browser/localstorage/set';
import { LOCAL_STORAGE } from 'constants/localStorage'; import { LOCAL_STORAGE } from 'constants/localStorage';
import getTimeString from 'lib/getTimeString';
import dayjs, { Dayjs } from 'dayjs'; import dayjs, { Dayjs } from 'dayjs';
import getTimeString from 'lib/getTimeString';
import { connect, useSelector } from 'react-redux'; import { connect, useSelector } from 'react-redux';
import { RouteComponentProps, withRouter } from 'react-router'; import { RouteComponentProps, withRouter } from 'react-router';
import { bindActionCreators, Dispatch } from 'redux'; import { bindActionCreators, Dispatch } from 'redux';

View File

@ -2,7 +2,7 @@ import { Col } from 'antd';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import history from 'lib/history'; import history from 'lib/history';
import React from 'react'; import React from 'react';
import { useLocation, matchPath } from 'react-router-dom'; import { matchPath, useLocation } from 'react-router-dom';
import ShowBreadcrumbs from './Breadcrumbs'; import ShowBreadcrumbs from './Breadcrumbs';
import DateTimeSelector from './DateTimeSelection'; import DateTimeSelector from './DateTimeSelection';

View File

@ -12,7 +12,7 @@ import { generatePath } from 'react-router';
import { Alerts } from 'types/api/alerts/getAll'; import { Alerts } from 'types/api/alerts/getAll';
import DeleteAlert from './DeleteAlert'; import DeleteAlert from './DeleteAlert';
import { ButtonContainer, Button } from './styles'; import { Button, ButtonContainer } from './styles';
import Status from './TableComponents/Status'; import Status from './TableComponents/Status';
const ListAlert = ({ allAlertRules }: ListAlertProps): JSX.Element => { const ListAlert = ({ allAlertRules }: ListAlertProps): JSX.Element => {

View File

@ -1,5 +1,5 @@
import styled from 'styled-components';
import { Button as ButtonComponent } from 'antd'; import { Button as ButtonComponent } from 'antd';
import styled from 'styled-components';
export const ButtonContainer = styled.div` export const ButtonContainer = styled.div`
&&& { &&& {

View File

@ -1,8 +1,9 @@
import { Button } from 'antd'; import { Button } from 'antd';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import history from 'lib/history';
import React from 'react'; import React from 'react';
import { generatePath } from 'react-router-dom'; import { generatePath } from 'react-router-dom';
import history from 'lib/history';
import { Data } from '..'; import { Data } from '..';
const Name = (name: Data['name'], data: Data): JSX.Element => { const Name = (name: Data['name'], data: Data): JSX.Element => {

View File

@ -11,7 +11,7 @@ import { AppState } from 'store/reducers';
import DashboardReducer from 'types/reducer/dashboards'; import DashboardReducer from 'types/reducer/dashboards';
import { v4 } from 'uuid'; import { v4 } from 'uuid';
import { NewDashboardButton, TableContainer, ButtonContainer } from './styles'; import { ButtonContainer, NewDashboardButton, TableContainer } from './styles';
import Createdby from './TableComponents/CreatedBy'; import Createdby from './TableComponents/CreatedBy';
import DateComponent from './TableComponents/Date'; import DateComponent from './TableComponents/Date';
import DeleteButton from './TableComponents/DeleteButton'; import DeleteButton from './TableComponents/DeleteButton';

View File

@ -1,4 +1,6 @@
import Table, { ColumnsType } from 'antd/lib/table'; import Table, { ColumnsType } from 'antd/lib/table';
import localStorageGet from 'api/browser/localstorage/get';
import localStorageSet from 'api/browser/localstorage/set';
import { SKIP_ONBOARDING } from 'constants/onboarding'; import { SKIP_ONBOARDING } from 'constants/onboarding';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import history from 'lib/history'; import history from 'lib/history';
@ -10,8 +12,6 @@ import MetricReducer from 'types/reducer/metrics';
import SkipBoardModal from './SkipOnBoardModal'; import SkipBoardModal from './SkipOnBoardModal';
import { Container, Name } from './styles'; import { Container, Name } from './styles';
import localStorageGet from 'api/browser/localstorage/get';
import localStorageSet from 'api/browser/localstorage/set';
const Metrics = (): JSX.Element => { const Metrics = (): JSX.Element => {
const [skipOnboarding, setSkipOnboarding] = useState( const [skipOnboarding, setSkipOnboarding] = useState(
@ -31,7 +31,12 @@ const Metrics = (): JSX.Element => {
history.push(to); history.push(to);
}; };
if (services.length === 0 && loading === false && !skipOnboarding && error === true) { if (
services.length === 0 &&
loading === false &&
!skipOnboarding &&
error === true
) {
return <SkipBoardModal onContinueClick={onContinueClick} />; return <SkipBoardModal onContinueClick={onContinueClick} />;
} }

View File

@ -26,7 +26,7 @@ const DashboardGraphSlider = (): JSX.Element => {
[push, pathname], [push, pathname],
); );
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app); const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
const fillColor:React.CSSProperties['color'] = isDarkMode?"white" : "black"; const fillColor: React.CSSProperties['color'] = isDarkMode ? 'white' : 'black';
return ( return (
<Container> <Container>
{menuItems.map(({ name, Icon, display }) => ( {menuItems.map(({ name, Icon, display }) => (
@ -37,7 +37,7 @@ const DashboardGraphSlider = (): JSX.Element => {
key={name} key={name}
draggable draggable
> >
<Icon fillColor={fillColor}/> <Icon fillColor={fillColor} />
<Text>{display}</Text> <Text>{display}</Text>
</Card> </Card>
))} ))}

View File

@ -1,6 +1,6 @@
import TimeSeries from 'assets/Dashboard/TimeSeries'; import TimeSeries from 'assets/Dashboard/TimeSeries';
import ValueIcon from 'assets/Dashboard/Value';
import { TimeSeriesProps as IconProps } from 'assets/Dashboard/TimeSeries'; import { TimeSeriesProps as IconProps } from 'assets/Dashboard/TimeSeries';
import ValueIcon from 'assets/Dashboard/Value';
const Items: ItemsProps[] = [ const Items: ItemsProps[] = [
{ {

View File

@ -16,10 +16,10 @@ import AppActions from 'types/actions';
import { DeleteQueryProps } from 'types/actions/dashboard'; import { DeleteQueryProps } from 'types/actions/dashboard';
import { import {
ButtonContainer,
Container, Container,
InputContainer, InputContainer,
QueryWrapper, QueryWrapper,
ButtonContainer,
} from './styles'; } from './styles';
const Query = ({ const Query = ({

View File

@ -97,7 +97,23 @@ export const dataTypeCategories = [
{ name: 'exahashes/sec', id: 'EHs' }, { name: 'exahashes/sec', id: 'EHs' },
], ],
}, },
{
name: 'Misc',
formats: [
{ name: 'none', id: 'none' },
{ name: 'String', id: 'string' },
{ name: 'short', id: 'short' },
{ name: 'Percent (0-100)', id: 'percent' },
{ name: 'Percent (0.0-1.0)', id: 'percentunit' },
{ name: 'Humidity (%H)', id: 'humidity' },
{ name: 'Decibel', id: 'dB' },
{ name: 'Hexadecimal (0x)', id: 'hex0x' },
{ name: 'Hexadecimal', id: 'hex' },
{ name: 'Scientific notation', id: 'sci' },
{ name: 'Locale format', id: 'locale' },
{ name: 'Pixels', id: 'pixel' },
],
},
{ {
name: 'Acceleration', name: 'Acceleration',
formats: [ formats: [
@ -364,22 +380,6 @@ export const dataTypeCategories = [
{ name: 'On / Off', id: 'bool_on_off' }, { name: 'On / Off', id: 'bool_on_off' },
], ],
}, },
{
name: 'Misc',
formats: [
{ name: 'String', id: 'string' },
{ name: 'short', id: 'short' },
{ name: 'Percent (0-100)', id: 'percent' },
{ name: 'Percent (0.0-1.0)', id: 'percentunit' },
{ name: 'Humidity (%H)', id: 'humidity' },
{ name: 'Decibel', id: 'dB' },
{ name: 'Hexadecimal (0x)', id: 'hex0x' },
{ name: 'Hexadecimal', id: 'hex' },
{ name: 'Scientific notation', id: 'sci' },
{ name: 'Locale format', id: 'locale' },
{ name: 'Pixels', id: 'pixel' },
],
},
]; ];

View File

@ -77,7 +77,7 @@ const NewWidget = ({
const [description, setDescription] = useState<string>( const [description, setDescription] = useState<string>(
selectedWidget?.description || '', selectedWidget?.description || '',
); );
const [yAxisUnit, setYAxisUnit] = useState<string>(selectedWidget?.yAxisUnit); const [yAxisUnit, setYAxisUnit] = useState<string>(selectedWidget?.yAxisUnit || 'none');
const [stacked, setStacked] = useState<boolean>( const [stacked, setStacked] = useState<boolean>(
selectedWidget?.isStacked || false, selectedWidget?.isStacked || false,

View File

@ -1,7 +1,7 @@
import { Menu, Typography } from 'antd'; import { Menu, Typography } from 'antd';
import { SlackButton, SlackMenuItemContainer, ToggleButton } from './styles';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import history from 'lib/history'; import history from 'lib/history';
import setTheme from 'lib/theme/setTheme';
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import { connect, useSelector } from 'react-redux'; import { connect, useSelector } from 'react-redux';
import { NavLink } from 'react-router-dom'; import { NavLink } from 'react-router-dom';
@ -12,11 +12,11 @@ import { ToggleDarkMode } from 'store/actions';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import AppReducer from 'types/reducer/app'; import AppReducer from 'types/reducer/app';
import setTheme from 'lib/theme/setTheme';
import menus from './menuItems'; import menus from './menuItems';
import { Logo, Sider, ThemeSwitcherWrapper } from './styles';
import Slack from './Slack'; import Slack from './Slack';
import { SlackButton, SlackMenuItemContainer, ToggleButton } from './styles';
import { Logo, Sider, ThemeSwitcherWrapper } from './styles';
const SideNav = ({ toggleDarkMode }: Props): JSX.Element => { const SideNav = ({ toggleDarkMode }: Props): JSX.Element => {
const [collapsed, setCollapsed] = useState<boolean>(false); const [collapsed, setCollapsed] = useState<boolean>(false);

View File

@ -1,36 +1,26 @@
import React, { useState, useMemo } from 'react'; import { INTERVAL_UNITS } from 'container/TraceDetail/utils';
import { isEqual } from 'lodash-es';
import styles from './style.module.css';
import { useMeasure } from 'react-use';
import { toFixed } from 'utils/toFixed';
import {
INTERVAL_UNITS,
resolveTimeFromInterval,
} from 'container/TraceDetail/utils';
import useThemeMode from 'hooks/useThemeMode'; import useThemeMode from 'hooks/useThemeMode';
import React, { useEffect, useState } from 'react';
import { useMeasure } from 'react-use';
import styles from './style.module.css';
import { Interval } from './types'; import { Interval } from './types';
import { getIntervalSpread, getIntervals } from './utils'; import { getIntervals, getIntervalSpread } from './utils';
interface TimelineProps {
traceMetaData: object; const Timeline_Height = 22;
globalTraceMetadata: object; const Timeline_H_Spacing = 0;
intervalUnit: object;
setIntervalUnit: Function;
}
const Timeline = ({ const Timeline = ({
traceMetaData, traceMetaData,
globalTraceMetadata, globalTraceMetadata,
intervalUnit,
setIntervalUnit, setIntervalUnit,
}: TimelineProps) => { }: TimelineProps) => {
const [ref, { width }] = useMeasure<HTMLDivElement>(); const [ref, { width }] = useMeasure<HTMLDivElement>();
const { isDarkMode } = useThemeMode(); const { isDarkMode } = useThemeMode();
const Timeline_Height = 22;
const Timeline_H_Spacing = 0;
const [intervals, setIntervals] = useState<Interval[] | null>(null); const [intervals, setIntervals] = useState<Interval[] | null>(null);
useMemo(() => { useEffect(() => {
const { const {
baseInterval, baseInterval,
baseSpread, baseSpread,
@ -44,7 +34,7 @@ const Timeline = ({
for (const idx in INTERVAL_UNITS) { for (const idx in INTERVAL_UNITS) {
const standard_interval = INTERVAL_UNITS[idx]; const standard_interval = INTERVAL_UNITS[idx];
if (baseSpread * standard_interval.multiplier < 1) { if (baseSpread * standard_interval.multiplier < 1) {
intervalUnit = INTERVAL_UNITS[idx - 1]; if (idx > 1) intervalUnit = INTERVAL_UNITS[idx - 1];
break; break;
} }
} }
@ -58,7 +48,7 @@ const Timeline = ({
intervalUnit, intervalUnit,
}), }),
); );
}, [traceMetaData, globalTraceMetadata]); }, []);
return ( return (
<div ref={ref} style={{ flex: 1, overflow: 'inherit' }}> <div ref={ref} style={{ flex: 1, overflow: 'inherit' }}>
@ -102,4 +92,11 @@ const Timeline = ({
); );
}; };
interface TimelineProps {
traceMetaData: object;
globalTraceMetadata: object;
intervalUnit: object;
setIntervalUnit: Function;
}
export default Timeline; export default Timeline;

View File

@ -1,20 +1,22 @@
import { isEqual } from 'lodash-es';
import { toFixed } from 'utils/toFixed';
import { import {
INTERVAL_UNITS, INTERVAL_UNITS,
resolveTimeFromInterval, resolveTimeFromInterval,
} from 'container/TraceDetail/utils'; } from 'container/TraceDetail/utils';
import { isEqual } from 'lodash-es';
import { toFixed } from 'utils/toFixed';
import { Interval } from './types';
export const getIntervalSpread = ({ export const getIntervalSpread = ({
localTraceMetaData, localTraceMetaData,
globalTraceMetadata, globalTraceMetadata,
}) => { }): {
const { baseInterval: number;
globalStart: localStart, baseSpread: number;
globalEnd: localEnd, intervalSpreadNormalized: number;
spread: localSpread, } => {
} = localTraceMetaData; const { globalStart: localStart, spread: localSpread } = localTraceMetaData;
const { globalStart, globalEnd, globalSpread } = globalTraceMetadata; const { globalStart } = globalTraceMetadata;
let baseInterval = 0; let baseInterval = 0;
@ -24,7 +26,7 @@ export const getIntervalSpread = ({
const MIN_INTERVALS = 5; const MIN_INTERVALS = 5;
const baseSpread = localSpread; const baseSpread = localSpread;
let intervalSpread = (baseSpread / MIN_INTERVALS) * 1.0; const intervalSpread = (baseSpread / MIN_INTERVALS) * 1.0;
const integerPartString = intervalSpread.toString().split('.')[0]; const integerPartString = intervalSpread.toString().split('.')[0];
const integerPartLength = integerPartString.length; const integerPartLength = integerPartString.length;
const intervalSpreadNormalized = const intervalSpreadNormalized =
@ -45,7 +47,7 @@ export const getIntervals = ({
baseSpread, baseSpread,
intervalSpreadNormalized, intervalSpreadNormalized,
intervalUnit, intervalUnit,
}) => { }): Interval[] => {
const intervals: Interval[] = [ const intervals: Interval[] = [
{ {
label: `${toFixed(resolveTimeFromInterval(baseInterval, intervalUnit), 2)}${ label: `${toFixed(resolveTimeFromInterval(baseInterval, intervalUnit), 2)}${

View File

@ -1,19 +1,19 @@
import React, { useState } from 'react';
import { CheckBoxContainer } from './styles';
import { Checkbox, notification, Typography } from 'antd'; import { Checkbox, notification, Typography } from 'antd';
import { connect, useDispatch, useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace';
import { SelectedTraceFilter } from 'store/actions/trace/selectTraceFilter';
import AppActions from 'types/actions';
import { ThunkDispatch } from 'redux-thunk';
import { bindActionCreators, Dispatch } from 'redux';
import { getFilter, updateURL } from 'store/actions/trace/util';
import getFilters from 'api/trace/getFilters'; import getFilters from 'api/trace/getFilters';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import { GlobalReducer } from 'types/reducer/globalTime'; import React, { useState } from 'react';
import { connect, useDispatch, useSelector } from 'react-redux';
import { bindActionCreators, Dispatch } from 'redux';
import { ThunkDispatch } from 'redux-thunk';
import { SelectedTraceFilter } from 'store/actions/trace/selectTraceFilter';
import { getFilter, updateURL } from 'store/actions/trace/util';
import { AppState } from 'store/reducers';
import AppActions from 'types/actions';
import { UPDATE_ALL_FILTERS } from 'types/actions/trace'; import { UPDATE_ALL_FILTERS } from 'types/actions/trace';
import { GlobalReducer } from 'types/reducer/globalTime';
import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace';
import { CheckBoxContainer } from './styles';
const CheckBoxComponent = (props: CheckBoxProps): JSX.Element => { const CheckBoxComponent = (props: CheckBoxProps): JSX.Element => {
const { const {

View File

@ -2,6 +2,7 @@ import React from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace'; import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace';
import CheckBoxComponent from '../Common/Checkbox'; import CheckBoxComponent from '../Common/Checkbox';
const CommonCheckBox = (props: CommonCheckBoxProps): JSX.Element => { const CommonCheckBox = (props: CommonCheckBoxProps): JSX.Element => {

View File

@ -1,20 +1,20 @@
import React, { useState } from 'react';
import { Input, Slider } from 'antd'; import { Input, Slider } from 'antd';
import { Container, InputContainer, Text } from './styles'; import { SliderRangeProps } from 'antd/lib/slider';
import { useDispatch, useSelector } from 'react-redux'; import getFilters from 'api/trace/getFilters';
import { AppState } from 'store/reducers';
import { TraceReducer } from 'types/reducer/trace';
import useDebouncedFn from 'hooks/useDebouncedFunction';
import { getFilter, updateURL } from 'store/actions/trace/util';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import durationPlugin from 'dayjs/plugin/duration'; import durationPlugin from 'dayjs/plugin/duration';
import useDebouncedFn from 'hooks/useDebouncedFunction';
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Dispatch } from 'redux'; import { Dispatch } from 'redux';
import { getFilter, updateURL } from 'store/actions/trace/util';
import { AppState } from 'store/reducers';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import { UPDATE_ALL_FILTERS } from 'types/actions/trace'; import { UPDATE_ALL_FILTERS } from 'types/actions/trace';
import getFilters from 'api/trace/getFilters';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import { SliderRangeProps } from 'antd/lib/slider'; import { TraceReducer } from 'types/reducer/trace';
import { Container, InputContainer, Text } from './styles';
dayjs.extend(durationPlugin); dayjs.extend(durationPlugin);

View File

@ -1,5 +1,5 @@
import styled from 'styled-components';
import { Typography } from 'antd'; import { Typography } from 'antd';
import styled from 'styled-components';
export const DurationText = styled.div` export const DurationText = styled.div`
display: flex; display: flex;

View File

@ -1,12 +1,12 @@
import React from 'react';
import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace';
import { Card } from 'antd'; import { Card } from 'antd';
import Spinner from 'components/Spinner';
import Duration from './Duration'; import React from 'react';
import CommonCheckBox from './CommonCheckBox';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import Spinner from 'components/Spinner'; import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace';
import CommonCheckBox from './CommonCheckBox';
import Duration from './Duration';
const PanelBody = (props: PanelBodyProps): JSX.Element => { const PanelBody = (props: PanelBodyProps): JSX.Element => {
const { type } = props; const { type } = props;

View File

@ -1,6 +1,9 @@
import React, { useState } from 'react';
import { DownOutlined, RightOutlined } from '@ant-design/icons'; import { DownOutlined, RightOutlined } from '@ant-design/icons';
import { Card, Typography, Divider, notification } from 'antd'; import { Card, Divider, notification, Typography } from 'antd';
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace';
import { import {
ButtonComponent, ButtonComponent,
@ -9,19 +12,16 @@ import {
IconContainer, IconContainer,
TextCotainer, TextCotainer,
} from './styles'; } from './styles';
import { useDispatch, useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace';
const { Text } = Typography; const { Text } = Typography;
import { AllPanelHeading } from 'types/reducer/trace';
import getFilters from 'api/trace/getFilters'; import getFilters from 'api/trace/getFilters';
import { GlobalReducer } from 'types/reducer/globalTime'; import { AxiosError } from 'axios';
import { Dispatch } from 'redux';
import { getFilter, updateURL } from 'store/actions/trace/util'; import { getFilter, updateURL } from 'store/actions/trace/util';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import { Dispatch } from 'redux';
import { UPDATE_ALL_FILTERS } from 'types/actions/trace'; import { UPDATE_ALL_FILTERS } from 'types/actions/trace';
import { AxiosError } from 'axios'; import { GlobalReducer } from 'types/reducer/globalTime';
import { AllPanelHeading } from 'types/reducer/trace';
const PanelHeading = (props: PanelHeadingProps): JSX.Element => { const PanelHeading = (props: PanelHeadingProps): JSX.Element => {
const { const {

View File

@ -1,10 +1,10 @@
import { ChartData, ChartDataset, ChartDatasetProperties } from 'chart.js'; import { ChartData, ChartDataset, ChartDatasetProperties } from 'chart.js';
import { TraceReducer } from 'types/reducer/trace';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { colors } from 'lib/getRandomColor'; import { colors } from 'lib/getRandomColor';
import { TraceReducer } from 'types/reducer/trace';
function transposeArray(array: number[][], arrayLength: number) { function transposeArray(array: number[][], arrayLength: number) {
let newArray: number[][] = []; const newArray: number[][] = [];
for (let i = 0; i < array.length; i++) { for (let i = 0; i < array.length; i++) {
newArray.push([]); newArray.push([]);
} }

View File

@ -1,6 +1,6 @@
import { AutoComplete, AutoCompleteProps, Input, notification } from 'antd'; import { AutoComplete, AutoCompleteProps, Input, notification } from 'antd';
import getTagFilters from 'api/trace/getTagFilter'; import getTagFilters from 'api/trace/getTagFilter';
import React, { useEffect, useState } from 'react'; import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
@ -18,7 +18,7 @@ const TagsKey = (props: TagsKeysProps): JSX.Element => {
const [options, setOptions] = useState<AutoCompleteProps['options']>([]); const [options, setOptions] = useState<AutoCompleteProps['options']>([]);
const onSearchHandler = async () => { const onSearchHandler = useCallback(async () => {
try { try {
setSelectLoading(true); setSelectLoading(true);
const response = await getTagFilters({ const response = await getTagFilters({
@ -55,11 +55,16 @@ const TagsKey = (props: TagsKeysProps): JSX.Element => {
}); });
setSelectLoading(false); setSelectLoading(false);
} }
}; }, [globalTime, traces]);
const counter = useRef(0);
useEffect(() => { useEffect(() => {
if (counter.current === 0) {
counter.current = 1;
onSearchHandler(); onSearchHandler();
}, []); }
}, [onSearchHandler]);
return ( return (
<AutoComplete <AutoComplete
@ -68,7 +73,7 @@ const TagsKey = (props: TagsKeysProps): JSX.Element => {
style={{ width: 300 }} style={{ width: 300 }}
options={options} options={options}
value={selectedKey} value={selectedKey}
onChange={(value) => { onChange={(value): void => {
if (options && options.find((option) => option.value === value)) { if (options && options.find((option) => option.value === value)) {
setSelectedKey(value); setSelectedKey(value);

View File

@ -1,21 +1,21 @@
import React from 'react'; import { CloseOutlined } from '@ant-design/icons';
import { Select } from 'antd'; import { Select } from 'antd';
import { SelectValue } from 'antd/lib/select';
import React from 'react';
import { connect, useSelector } from 'react-redux';
import { bindActionCreators } from 'redux';
import { ThunkDispatch } from 'redux-thunk';
import { UpdateSelectedTags } from 'store/actions/trace/updateTagsSelected';
import { AppState } from 'store/reducers';
import AppActions from 'types/actions';
import { TraceReducer } from 'types/reducer/trace';
import { import {
Container, Container,
IconContainer, IconContainer,
SelectComponent, SelectComponent,
ValueSelect, ValueSelect,
} from './styles'; } from './styles';
import { connect, useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { TraceReducer } from 'types/reducer/trace';
import { CloseOutlined } from '@ant-design/icons';
import { SelectValue } from 'antd/lib/select';
import { ThunkDispatch } from 'redux-thunk';
import AppActions from 'types/actions';
import { bindActionCreators } from 'redux';
import { UpdateSelectedTags } from 'store/actions/trace/updateTagsSelected';
import TagsKey from './TagKey'; import TagsKey from './TagKey';
const { Option } = Select; const { Option } = Select;
@ -45,11 +45,11 @@ const SingleTags = (props: AllTagsProps): JSX.Element => {
Values: selectedValues, Values: selectedValues,
} = props.tag; } = props.tag;
const onDeleteTagHandler = (index: number) => { const onDeleteTagHandler = (index: number): void => {
props.onCloseHandler(index); props.onCloseHandler(index);
}; };
const onChangeOperatorHandler = (key: SelectValue) => { const onChangeOperatorHandler = (key: SelectValue): void => {
props.setLocalSelectedTags([ props.setLocalSelectedTags([
...traces.selectedTags.slice(0, props.index), ...traces.selectedTags.slice(0, props.index),
{ {
@ -83,7 +83,7 @@ const SingleTags = (props: AllTagsProps): JSX.Element => {
<ValueSelect <ValueSelect
value={selectedValues} value={selectedValues}
onChange={(value) => { onChange={(value): void => {
props.setLocalSelectedTags((tags) => [ props.setLocalSelectedTags((tags) => [
...tags.slice(0, props.index), ...tags.slice(0, props.index),
{ {
@ -99,7 +99,7 @@ const SingleTags = (props: AllTagsProps): JSX.Element => {
<IconContainer <IconContainer
role={'button'} role={'button'}
onClick={() => onDeleteTagHandler(props.index)} onClick={(): void => onDeleteTagHandler(props.index)}
> >
<CloseOutlined /> <CloseOutlined />
</IconContainer> </IconContainer>

View File

@ -1,5 +1,5 @@
import { Select, Space } from 'antd';
import styled from 'styled-components'; import styled from 'styled-components';
import { Button, Select, Space } from 'antd';
export const SpaceComponent = styled(Space)` export const SpaceComponent = styled(Space)`
&&& { &&& {

View File

@ -1,27 +1,28 @@
import { CaretRightFilled } from '@ant-design/icons';
import { Button, Space, Typography } from 'antd';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Button, Space, Typography } from 'antd';
import { CaretRightFilled } from '@ant-design/icons';
import { import {
Container,
ButtonContainer, ButtonContainer,
Container,
CurrentTagsContainer, CurrentTagsContainer,
Wrapper,
ErrorContainer, ErrorContainer,
Wrapper,
} from './styles'; } from './styles';
import Tags from './Tag'; import Tags from './Tag';
const { Text } = Typography; const { Text } = Typography;
import { PlusOutlined } from '@ant-design/icons'; import { PlusOutlined } from '@ant-design/icons';
import { isEqual } from 'lodash-es';
import { connect, useSelector } from 'react-redux'; import { connect, useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { TraceReducer } from 'types/reducer/trace';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { ThunkDispatch } from 'redux-thunk'; import { ThunkDispatch } from 'redux-thunk';
import AppActions from 'types/actions';
import { UpdateTagIsError } from 'store/actions/trace/updateIsTagsError'; import { UpdateTagIsError } from 'store/actions/trace/updateIsTagsError';
import { parseTagsToQuery } from '../util';
import { isEqual } from 'lodash-es';
import { UpdateTagVisiblity } from 'store/actions/trace/updateTagPanelVisiblity'; import { UpdateTagVisiblity } from 'store/actions/trace/updateTagPanelVisiblity';
import { AppState } from 'store/reducers';
import AppActions from 'types/actions';
import { TraceReducer } from 'types/reducer/trace';
import { parseTagsToQuery } from '../util';
const { Paragraph } = Typography; const { Paragraph } = Typography;
@ -37,7 +38,7 @@ const AllTags = ({
TraceReducer['selectedTags'] TraceReducer['selectedTags']
>(traces.selectedTags); >(traces.selectedTags);
const onTagAddHandler = () => { const onTagAddHandler = (): void => {
setLocalSelectedTags((tags) => [ setLocalSelectedTags((tags) => [
...tags, ...tags,
{ {
@ -52,16 +53,16 @@ const AllTags = ({
if (!isEqual(traces.selectedTags, localSelectedTags)) { if (!isEqual(traces.selectedTags, localSelectedTags)) {
setLocalSelectedTags(traces.selectedTags); setLocalSelectedTags(traces.selectedTags);
} }
}, [traces.selectedTags]); }, [traces.selectedTags, localSelectedTags]);
const onCloseHandler = (index: number) => { const onCloseHandler = (index: number): void => {
setLocalSelectedTags([ setLocalSelectedTags([
...localSelectedTags.slice(0, index), ...localSelectedTags.slice(0, index),
...localSelectedTags.slice(index + 1, localSelectedTags.length), ...localSelectedTags.slice(index + 1, localSelectedTags.length),
]); ]);
}; };
const onRunQueryHandler = () => { const onRunQueryHandler = (): void => {
const parsedQuery = parseTagsToQuery(localSelectedTags); const parsedQuery = parseTagsToQuery(localSelectedTags);
if (parsedQuery.isError) { if (parsedQuery.isError) {
@ -74,7 +75,7 @@ const AllTags = ({
} }
}; };
const onResetHandler = () => { const onResetHandler = (): void => {
setLocalSelectedTags([]); setLocalSelectedTags([]);
}; };
@ -102,10 +103,10 @@ const AllTags = ({
<CurrentTagsContainer> <CurrentTagsContainer>
{localSelectedTags.map((tags, index) => ( {localSelectedTags.map((tags, index) => (
<Tags <Tags
key={index} key={tags.Key.join(',')}
tag={tags} tag={tags}
index={index} index={index}
onCloseHandler={() => onCloseHandler(index)} onCloseHandler={(): void => onCloseHandler(index)}
setLocalSelectedTags={setLocalSelectedTags} setLocalSelectedTags={setLocalSelectedTags}
/> />
))} ))}

View File

@ -1,5 +1,5 @@
import styled from 'styled-components';
import { Card } from 'antd'; import { Card } from 'antd';
import styled from 'styled-components';
export const Container = styled(Card)` export const Container = styled(Card)`
top: 120%; top: 120%;

View File

@ -1,20 +1,21 @@
import React, { useEffect, useRef, useState } from 'react';
import { Space } from 'antd';
import { Container, SearchComponent } from './styles';
import useClickOutside from 'hooks/useClickOutside';
import Tags from './AllTags';
import { connect, useDispatch, useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { TraceReducer } from 'types/reducer/trace';
import { ThunkDispatch } from 'redux-thunk';
import AppActions from 'types/actions';
import { bindActionCreators, Dispatch } from 'redux';
import { UpdateTagVisiblity } from 'store/actions/trace/updateTagPanelVisiblity';
import { parseQueryToTags, parseTagsToQuery } from './util';
import { UpdateTagIsError } from 'store/actions/trace/updateIsTagsError';
import { CaretRightFilled } from '@ant-design/icons'; import { CaretRightFilled } from '@ant-design/icons';
import { Space } from 'antd';
import useClickOutside from 'hooks/useClickOutside';
import React, { useEffect, useRef, useState } from 'react';
import { connect, useDispatch, useSelector } from 'react-redux';
import { bindActionCreators, Dispatch } from 'redux';
import { ThunkDispatch } from 'redux-thunk';
import { UpdateTagIsError } from 'store/actions/trace/updateIsTagsError';
import { UpdateTagVisiblity } from 'store/actions/trace/updateTagPanelVisiblity';
import { updateURL } from 'store/actions/trace/util'; import { updateURL } from 'store/actions/trace/util';
import { AppState } from 'store/reducers';
import AppActions from 'types/actions';
import { UPDATE_ALL_FILTERS } from 'types/actions/trace'; import { UPDATE_ALL_FILTERS } from 'types/actions/trace';
import { TraceReducer } from 'types/reducer/trace';
import Tags from './AllTags';
import { Container, SearchComponent } from './styles';
import { parseQueryToTags, parseTagsToQuery } from './util';
const Search = ({ const Search = ({
updateTagVisiblity, updateTagVisiblity,
@ -38,7 +39,7 @@ const Search = ({
if (value.length === 0 && traces.isTagModalError) { if (value.length === 0 && traces.isTagModalError) {
updateTagIsError(false); updateTagIsError(false);
} }
}, [traces.isTagModalError, value]); }, [traces.isTagModalError, value, updateTagIsError]);
const tagRef = useRef<HTMLDivElement>(null); const tagRef = useRef<HTMLDivElement>(null);
@ -69,11 +70,11 @@ const Search = ({
} }
}); });
const onChangeHandler = (search: string) => { const onChangeHandler = (search: string): void => {
setValue(search); setValue(search);
}; };
const setIsTagsModalHandler = (value: boolean) => { const setIsTagsModalHandler = (value: boolean): void => {
updateTagVisiblity(value); updateTagVisiblity(value);
}; };
@ -82,7 +83,9 @@ const Search = ({
setIsTagsModalHandler(true); setIsTagsModalHandler(true);
}; };
const updateFilters = async (selectedTags: TraceReducer['selectedTags']) => { const updateFilters = async (
selectedTags: TraceReducer['selectedTags'],
): Promise<void> => {
dispatch({ dispatch({
type: UPDATE_ALL_FILTERS, type: UPDATE_ALL_FILTERS,
payload: { payload: {
@ -111,7 +114,7 @@ const Search = ({
<Space direction="vertical" style={{ width: '100%' }}> <Space direction="vertical" style={{ width: '100%' }}>
<Container ref={tagRef}> <Container ref={tagRef}>
<SearchComponent <SearchComponent
onChange={(event) => onChangeHandler(event.target.value)} onChange={(event): void => onChangeHandler(event.target.value)}
value={value} value={value}
allowClear allowClear
disabled={traces.filterLoading} disabled={traces.filterLoading}
@ -119,7 +122,7 @@ const Search = ({
placeholder="Click to filter by tags" placeholder="Click to filter by tags"
type={'search'} type={'search'}
enterButton={<CaretRightFilled />} enterButton={<CaretRightFilled />}
onSearch={(string) => { onSearch={(string): void => {
if (string.length === 0) { if (string.length === 0) {
updateTagVisiblity(false); updateTagVisiblity(false);
updateFilters([]); updateFilters([]);

View File

@ -1,5 +1,5 @@
import styled from 'styled-components';
import { Input } from 'antd'; import { Input } from 'antd';
import styled from 'styled-components';
const { Search } = Input; const { Search } = Input;

View File

@ -1,21 +1,22 @@
import { SelectProps, Space } from 'antd';
import { SelectValue } from 'antd/lib/select';
import React from 'react'; import React from 'react';
import { Space, SelectProps } from 'antd';
import { functions, groupBy } from './config';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { Dispatch } from 'redux';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import { TraceReducer } from 'types/reducer/trace';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import { import {
UPDATE_SELECTED_FUNCTION, UPDATE_SELECTED_FUNCTION,
UPDATE_SELECTED_GROUP_BY, UPDATE_SELECTED_GROUP_BY,
} from 'types/actions/trace'; } from 'types/actions/trace';
import { Dispatch } from 'redux'; import { TraceReducer } from 'types/reducer/trace';
import { functions, groupBy } from './config';
import { SelectComponent } from './styles'; import { SelectComponent } from './styles';
import { SelectValue } from 'antd/lib/select';
const { Option } = SelectComponent; const { Option } = SelectComponent;
const TraceGraphFilter = () => { const TraceGraphFilter = (): JSX.Element => {
const { selectedFunction, selectedGroupBy } = useSelector< const { selectedFunction, selectedGroupBy } = useSelector<
AppState, AppState,
TraceReducer TraceReducer
@ -75,11 +76,13 @@ const TraceGraphFilter = () => {
value={groupBy.find((e) => selectedGroupBy === e.key)?.displayValue} value={groupBy.find((e) => selectedGroupBy === e.key)?.displayValue}
onChange={onClickSelectedGroupByHandler} onChange={onClickSelectedGroupByHandler}
> >
{groupBy.map((value) => ( {groupBy.map(
(value): JSX.Element => (
<Option value={value.key} key={value.key}> <Option value={value.key} key={value.key}>
{value.displayValue} {value.displayValue}
</Option> </Option>
))} ),
)}
</SelectComponent> </SelectComponent>
</Space> </Space>
); );

View File

@ -1,5 +1,4 @@
import { Select } from 'antd'; import { Select } from 'antd';
import styled from 'styled-components'; import styled from 'styled-components';
export const SelectComponent = styled(Select)` export const SelectComponent = styled(Select)`

View File

@ -1,13 +1,13 @@
import { Button, Modal, Collapse } from 'antd'; import { Button, Collapse, Modal } from 'antd';
import useThemeMode from 'hooks/useThemeMode'; import useThemeMode from 'hooks/useThemeMode';
import React, { useRef, useState } from 'react'; import React, { useState } from 'react';
import { ITraceTree } from 'types/api/trace/getTraceItem'; import { ITraceTree } from 'types/api/trace/getTraceItem';
import { CustomSubText, CustomSubTitle } from './styles'; import { CustomSubText, CustomSubTitle } from './styles';
// import Editor from 'components/Editor';
const { Panel } = Collapse; const { Panel } = Collapse;
const ErrorTag = ({ event }: ErrorTagProps) => { const ErrorTag = ({ event }: ErrorTagProps): JSX.Element => {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const { isDarkMode } = useThemeMode(); const { isDarkMode } = useThemeMode();
// const useTextRef = useRef(''); // const useTextRef = useRef('');
@ -17,7 +17,7 @@ const ErrorTag = ({ event }: ErrorTagProps) => {
subText: '', subText: '',
}); });
const onToggleHandler = (state: boolean) => { const onToggleHandler = (state: boolean): void => {
setIsOpen(state); setIsOpen(state);
}; };
@ -30,6 +30,7 @@ const ErrorTag = ({ event }: ErrorTagProps) => {
<Collapse <Collapse
defaultActiveKey={[name || attributeMap.event]} defaultActiveKey={[name || attributeMap.event]}
expandIconPosition="right" expandIconPosition="right"
key={name}
> >
<Panel <Panel
header={name || attributeMap?.event} header={name || attributeMap?.event}
@ -48,7 +49,7 @@ const ErrorTag = ({ event }: ErrorTagProps) => {
{isEllipsed && ( {isEllipsed && (
<Button <Button
style={{ padding: 0, margin: 0 }} style={{ padding: 0, margin: 0 }}
onClick={() => { onClick={(): void => {
onToggleHandler(true); onToggleHandler(true);
setText({ setText({
subText: value, subText: value,
@ -62,8 +63,6 @@ const ErrorTag = ({ event }: ErrorTagProps) => {
</Button> </Button>
)} )}
</CustomSubText> </CustomSubText>
</> </>
); );
})} })}
@ -72,7 +71,7 @@ const ErrorTag = ({ event }: ErrorTagProps) => {
); );
})} })}
<Modal <Modal
onCancel={() => onToggleHandler(false)} onCancel={(): void => onToggleHandler(false)}
title="Log Message" title="Log Message"
visible={isOpen} visible={isOpen}
destroyOnClose destroyOnClose

View File

@ -1,6 +1,9 @@
import { Space, Tabs, Typography } from 'antd'; import { Space, Tabs, Typography } from 'antd';
import useThemeMode from 'hooks/useThemeMode';
import React from 'react'; import React from 'react';
import { ITraceTree } from 'types/api/trace/getTraceItem'; import { ITraceTree } from 'types/api/trace/getTraceItem';
import ErrorTag from './ErrorTag';
import { import {
CardContainer, CardContainer,
CustomSubText, CustomSubText,
@ -8,8 +11,6 @@ import {
CustomText, CustomText,
CustomTitle, CustomTitle,
} from './styles'; } from './styles';
import ErrorTag from './ErrorTag';
import useThemeMode from 'hooks/useThemeMode';
const { TabPane } = Tabs; const { TabPane } = Tabs;
@ -40,7 +41,7 @@ const SelectedSpanDetails = (props: SelectedSpanDetailsProps): JSX.Element => {
{tags.length !== 0 ? ( {tags.length !== 0 ? (
tags.map((tags) => { tags.map((tags) => {
return ( return (
<React.Fragment> <React.Fragment key={tags.key}>
{tags.value && ( {tags.value && (
<> <>
<CustomSubTitle>{tags.key}</CustomSubTitle> <CustomSubTitle>{tags.key}</CustomSubTitle>

View File

@ -1,21 +1,22 @@
import React, { useEffect, useMemo, useState } from 'react';
import { Col, Divider, Row, Typography, Space, Button } from 'antd';
import { FilterOutlined } from '@ant-design/icons'; import { FilterOutlined } from '@ant-design/icons';
import { Button, Col, Divider, Row, Space, Typography } from 'antd';
import GanttChart from 'container/GantChart'; import GanttChart from 'container/GantChart';
import { getNodeById } from 'container/GantChart/utils'; import { getNodeById } from 'container/GantChart/utils';
import Timeline from 'container/Timeline'; import Timeline from 'container/Timeline';
import TraceFlameGraph from 'container/TraceFlameGraph'; import TraceFlameGraph from 'container/TraceFlameGraph';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import useUrlQuery from 'hooks/useUrlQuery';
import { spanServiceNameToColorMapping } from 'lib/getRandomColor'; import { spanServiceNameToColorMapping } from 'lib/getRandomColor';
import { getSortedData } from './utils'; import history from 'lib/history';
import { SPAN_DETAILS_LEFT_COL_WIDTH } from 'pages/TraceDetail/constants';
import React, { useEffect, useMemo, useState } from 'react';
import { ITraceTree, PayloadProps } from 'types/api/trace/getTraceItem'; import { ITraceTree, PayloadProps } from 'types/api/trace/getTraceItem';
import { getSpanTreeMetadata } from 'utils/getSpanTreeMetadata'; import { getSpanTreeMetadata } from 'utils/getSpanTreeMetadata';
import { spanToTreeUtil } from 'utils/spanToTree'; import { spanToTreeUtil } from 'utils/spanToTree';
import SelectedSpanDetails from './SelectedSpanDetails'; import SelectedSpanDetails from './SelectedSpanDetails';
import useUrlQuery from 'hooks/useUrlQuery';
import styles from './TraceGraph.module.css'; import styles from './TraceGraph.module.css';
import history from 'lib/history'; import { getSortedData } from './utils';
import { SPAN_DETAILS_LEFT_COL_WIDTH } from 'pages/TraceDetail/constants';
import { INTERVAL_UNITS } from './utils'; import { INTERVAL_UNITS } from './utils';
const TraceDetail = ({ response }: TraceDetailProps): JSX.Element => { const TraceDetail = ({ response }: TraceDetailProps): JSX.Element => {
@ -25,10 +26,10 @@ const TraceDetail = ({ response }: TraceDetailProps): JSX.Element => {
); );
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
const [spanId, _setSpanId] = useState<string | null>(urlQuery.get('spanId')); const [spanId] = useState<string | null>(urlQuery.get('spanId'));
const [intervalUnit, setIntervalUnit] = useState(INTERVAL_UNITS[0]); const [intervalUnit, setIntervalUnit] = useState(INTERVAL_UNITS[0]);
const [searchSpanString, setSearchSpanString] = useState(''); // const [searchSpanString, setSearchSpanString] = useState('');
const [activeHoverId, setActiveHoverId] = useState<string>(''); const [activeHoverId, setActiveHoverId] = useState<string>('');
const [activeSelectedId, setActiveSelectedId] = useState<string>(spanId || ''); const [activeSelectedId, setActiveSelectedId] = useState<string>(spanId || '');
@ -38,9 +39,9 @@ const TraceDetail = ({ response }: TraceDetailProps): JSX.Element => {
const { treeData: tree, ...traceMetaData } = useMemo(() => { const { treeData: tree, ...traceMetaData } = useMemo(() => {
return getSpanTreeMetadata(getSortedData(treeData), spanServiceColors); return getSpanTreeMetadata(getSortedData(treeData), spanServiceColors);
}, [treeData]); }, [treeData, spanServiceColors]);
const [globalTraceMetadata, _setGlobalTraceMetadata] = useState<object>({ const [globalTraceMetadata] = useState<Record<string, number>>({
...traceMetaData, ...traceMetaData,
}); });
@ -57,10 +58,10 @@ const TraceDetail = ({ response }: TraceDetailProps): JSX.Element => {
return getNodeById(activeSelectedId, treeData); return getNodeById(activeSelectedId, treeData);
}, [activeSelectedId, treeData]); }, [activeSelectedId, treeData]);
const onSearchHandler = (value: string) => { // const onSearchHandler = (value: string) => {
setSearchSpanString(value); // setSearchSpanString(value);
setTreeData(spanToTreeUtil(response[0].events)); // setTreeData(spanToTreeUtil(response[0].events));
}; // };
const onFocusSelectedSpanHandler = () => { const onFocusSelectedSpanHandler = () => {
const treeNode = getNodeById(activeSelectedId, tree); const treeNode = getNodeById(activeSelectedId, tree);
if (treeNode) { if (treeNode) {
@ -68,7 +69,7 @@ const TraceDetail = ({ response }: TraceDetailProps): JSX.Element => {
} }
}; };
const onResetHandler = () => { const onResetHandler = (): void => {
setTreeData(spanToTreeUtil(response[0].events)); setTreeData(spanToTreeUtil(response[0].events));
}; };

View File

@ -1,8 +1,8 @@
/** /**
* string is present on the span or not * string is present on the span or not
*/ */
import { ITraceTree, Span } from 'types/api/trace/getTraceItem';
import { sortBy } from 'lodash-es'; import { sortBy } from 'lodash-es';
import { ITraceTree, Span } from 'types/api/trace/getTraceItem';
export const filterSpansByString = ( export const filterSpansByString = (
searchString: string, searchString: string,
@ -35,12 +35,12 @@ export const INTERVAL_UNITS: IIntervalUnit[] = [
export const resolveTimeFromInterval = ( export const resolveTimeFromInterval = (
intervalTime: number, intervalTime: number,
intervalUnit: IIntervalUnit, intervalUnit: IIntervalUnit,
) => { ): number => {
return intervalTime * intervalUnit.multiplier; return intervalTime * intervalUnit.multiplier;
}; };
export const getSortedData = (treeData: ITraceTree) => { export const getSortedData = (treeData: ITraceTree): undefined | ITraceTree => {
const traverse = (treeNode: ITraceTree, level: number = 0) => { const traverse = (treeNode: ITraceTree, level = 0): void => {
if (!treeNode) { if (!treeNode) {
return; return;
} }

View File

@ -1,7 +1,7 @@
import { expect } from '@jest/globals'; import { expect } from '@jest/globals';
import React from 'react';
import { render } from '@testing-library/react'; import { render } from '@testing-library/react';
import TraceFlameGraph from 'container/TraceFlameGraph'; import TraceFlameGraph from 'container/TraceFlameGraph';
import React from 'react';
test('loads and displays greeting', async () => { test('loads and displays greeting', async () => {
const { asFragment } = render(<TraceFlameGraph />); const { asFragment } = render(<TraceFlameGraph />);

View File

@ -1,17 +1,31 @@
import React, { useState, useLayoutEffect, useMemo } from 'react';
import Color from 'color'; import Color from 'color';
import { pushDStree } from 'store/actions'; import { ITraceMetaData } from 'container/GantChart';
import {
SpanItemContainer,
TraceFlameGraphContainer,
TOTAL_SPAN_HEIGHT,
} from './styles';
import { import {
IIntervalUnit, IIntervalUnit,
resolveTimeFromInterval, resolveTimeFromInterval,
} from 'container/TraceDetail/utils'; } from 'container/TraceDetail/utils';
import { toFixed } from 'utils/toFixed';
import useThemeMode from 'hooks/useThemeMode'; import useThemeMode from 'hooks/useThemeMode';
import React, { useLayoutEffect, useMemo, useState } from 'react';
import { ITraceTree } from 'types/api/trace/getTraceItem';
import { toFixed } from 'utils/toFixed';
import {
SpanItemContainer,
TOTAL_SPAN_HEIGHT,
TraceFlameGraphContainer,
} from './styles';
interface SpanItem {
topOffset: number;
leftOffset: number;
width: number;
spanData: ITraceTree;
tooltipText: string;
onSpanSelect: (id: string) => void;
onSpanHover: React.Dispatch<React.SetStateAction<string>>;
hoveredSpanId: string;
selectedSpanId: string;
}
const SpanItem = ({ const SpanItem = ({
topOffset = 0, // top offset in px topOffset = 0, // top offset in px
@ -23,20 +37,10 @@ const SpanItem = ({
onSpanHover, onSpanHover,
hoveredSpanId, hoveredSpanId,
selectedSpanId, selectedSpanId,
}: { }: SpanItem): JSX.Element => {
topOffset: number;
leftOffset: number;
width: number;
spanData: pushDStree;
tooltipText: string;
onSpanSelect: Function;
onSpanHover: Function;
hoveredSpanId: string;
selectedSpanId: string;
}) => {
const { serviceColour } = spanData; const { serviceColour } = spanData;
const [isSelected, setIsSelected] = useState<boolean>(false); const [isSelected, setIsSelected] = useState<boolean>(false);
const [isLocalHover, setIsLocalHover] = useState<boolean>(false); // const [isLocalHover, setIsLocalHover] = useState<boolean>(false);
const { isDarkMode } = useThemeMode(); const { isDarkMode } = useThemeMode();
useLayoutEffect(() => { useLayoutEffect(() => {
@ -46,16 +50,16 @@ const SpanItem = ({
) { ) {
setIsSelected(true); setIsSelected(true);
} }
}, [hoveredSpanId, selectedSpanId]); }, [hoveredSpanId, selectedSpanId, isSelected, spanData]);
const handleHover = (hoverState: boolean) => { const handleHover = (hoverState: boolean): void => {
setIsLocalHover(hoverState); // setIsLocalHover(hoverState);
if (hoverState) onSpanHover(spanData.id); if (hoverState) onSpanHover(spanData.id);
else onSpanHover(null); else onSpanHover('');
}; };
const handleClick = () => { const handleClick = (): void => {
onSpanSelect(spanData.id); onSpanSelect(spanData.id);
}; };
@ -64,17 +68,17 @@ const SpanItem = ({
? Color(serviceColour).lighten(0.3) ? Color(serviceColour).lighten(0.3)
: Color(serviceColour).darken(0.3); : Color(serviceColour).darken(0.3);
return `${isSelected ? selectedSpanColor : serviceColour}`; return `${isSelected ? selectedSpanColor : serviceColour}`;
}, [isSelected, serviceColour]); }, [isSelected, serviceColour, isDarkMode]);
return ( return (
<> <>
<SpanItemContainer <SpanItemContainer
title={tooltipText} title={tooltipText}
onClick={handleClick} onClick={handleClick}
onMouseEnter={() => { onMouseEnter={(): void => {
handleHover(true); handleHover(true);
}} }}
onMouseLeave={() => { onMouseLeave={(): void => {
handleHover(false); handleHover(false);
}} }}
topOffset={topOffset} topOffset={topOffset}
@ -89,26 +93,20 @@ const SpanItem = ({
}; };
const TraceFlameGraph = (props: { const TraceFlameGraph = (props: {
treeData: pushDStree; treeData: ITraceTree;
traceMetaData: any; traceMetaData: ITraceMetaData;
onSpanHover: Function; onSpanHover: SpanItem['onSpanHover'];
onSpanSelect: Function; onSpanSelect: SpanItem['onSpanSelect'];
hoveredSpanId: string; hoveredSpanId: string;
selectedSpanId: string; selectedSpanId: string;
intervalUnit: IIntervalUnit; intervalUnit: IIntervalUnit;
}) => { }): JSX.Element => {
if (!props.treeData || props.treeData.id === 'empty' || !props.traceMetaData) { if (!props.treeData || props.treeData.id === 'empty' || !props.traceMetaData) {
return null; return <></>;
} }
const { intervalUnit } = props; const { intervalUnit } = props;
const { const { globalStart, spread, levels } = props.traceMetaData;
globalStart,
globalEnd,
spread,
totalSpans,
levels,
} = props.traceMetaData;
const RenderSpanRecursive = ({ const RenderSpanRecursive = ({
level = 0, level = 0,
spanData, spanData,
@ -118,16 +116,16 @@ const TraceFlameGraph = (props: {
hoveredSpanId, hoveredSpanId,
selectedSpanId, selectedSpanId,
}: { }: {
spanData: pushDStree; spanData: ITraceTree;
level?: number; level?: number;
parentLeftOffset?: number; parentLeftOffset?: number;
onSpanHover: Function; onSpanHover: SpanItem['onSpanHover'];
onSpanSelect: Function; onSpanSelect: SpanItem['onSpanSelect'];
hoveredSpanId: string; hoveredSpanId: string;
selectedSpanId: string; selectedSpanId: string;
}) => { }): JSX.Element => {
if (!spanData) { if (!spanData) {
return null; return <></>;
} }
const leftOffset = ((spanData.startTime - globalStart) * 100) / spread; const leftOffset = ((spanData.startTime - globalStart) * 100) / spread;

View File

@ -16,14 +16,14 @@ export const SpanItemContainer = styled.div<{
zIdx: number; zIdx: number;
}>` }>`
position: absolute; position: absolute;
top: ${(props) => props.topOffset}px; top: ${(props): string | number => props.topOffset}px;
left: ${(props) => props.leftOffset}%; left: ${(props): string | number => props.leftOffset}%;
width: ${(props) => props.width}%; width: ${(props): string | number => props.width}%;
height: ${SPAN_HEIGHT}px; height: ${SPAN_HEIGHT}px;
margin: ${SPAN_V_PADDING}px 0; margin: ${SPAN_V_PADDING}px 0;
background-color: ${({ spanColor }) => spanColor}; background-color: ${({ spanColor }): string | number => spanColor};
border-radius: ${SPAN_HEIGHT / 2}px; border-radius: ${SPAN_HEIGHT / 2}px;
z-index: ${(props) => props.zIdx}; z-index: ${(props): string | number => props.zIdx};
`; `;
/** /**
@ -34,5 +34,5 @@ export const TraceFlameGraphContainer = styled.div<{
}>` }>`
position: relative; position: relative;
width: 100%; width: 100%;
height: ${({ height }) => (height ? height : 120)}px; height: ${({ height }): string | number => (height ? height : 120)}px;
`; `;

View File

@ -1,26 +1,27 @@
import React, { useEffect } from 'react'; import React, { useCallback, useEffect } from 'react';
const useClickOutside = ( const useClickOutside = (
ref: React.RefObject<HTMLElement>, ref: React.RefObject<HTMLElement>,
callback: (e: HTMLElement) => void | null, callback: (e: HTMLElement) => void | null,
) => { ): void => {
const listener = (e: Event) => { const listener = useCallback(
(e: Event) => {
const node = e?.target as HTMLElement; const node = e?.target as HTMLElement;
if (ref.current && !ref.current.contains(node)) { if (ref.current && !ref.current.contains(node) && callback) {
if (callback) {
callback(node); callback(node);
} }
} },
}; [callback, ref],
);
useEffect(() => { useEffect(() => {
document.addEventListener('click', listener); document.addEventListener('click', listener);
return () => { return (): void => {
document.removeEventListener('click', listener); document.removeEventListener('click', listener);
}; };
}, [ref, callback]); }, [ref, callback, listener]);
}; };
export default useClickOutside; export default useClickOutside;

View File

@ -1,7 +1,7 @@
import { useMemo, useRef } from 'react';
import debounce from 'lodash-es/debounce'; import debounce from 'lodash-es/debounce';
import { useMemo, useRef } from 'react';
export interface DebouncedFunc<T extends (...args: any[]) => any> { export interface DebouncedFunc<T extends (...args: unknown[]) => unknown> {
(...args: Parameters<T>): ReturnType<T> | undefined; (...args: Parameters<T>): ReturnType<T> | undefined;
cancel(): void; cancel(): void;
@ -20,18 +20,17 @@ const defaultOptions: DebounceOptions = {
trailing: true, trailing: true,
}; };
const useDebouncedFn = <T extends (...args: any) => any>( const useDebouncedFn = <T extends (...args: Array<unknown>) => unknown>(
fn: T, fn: T,
wait: number = 100, wait = 100,
options: DebounceOptions = defaultOptions, options: DebounceOptions = defaultOptions,
dependencies?: ReadonlyArray<any>,
): DebouncedFunc<T> => { ): DebouncedFunc<T> => {
const fnRef = useRef(fn); const fnRef = useRef(fn);
fnRef.current = fn; fnRef.current = fn;
return useMemo( return useMemo(
() => debounce(((...args) => fnRef.current(...args)) as T, wait, options), () => debounce(((...args) => fnRef.current(...args)) as T, wait, options),
[...(dependencies || [])], [options, wait],
); );
}; };

View File

@ -6,7 +6,7 @@ export interface IUseThemeModeReturn {
isDarkMode: boolean; isDarkMode: boolean;
} }
const useThemeMode = () => { const useThemeMode = (): IUseThemeModeReturn => {
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app); const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
return { isDarkMode }; return { isDarkMode };

View File

@ -1,7 +1,7 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
function useUrlQuery() { function useUrlQuery(): URLSearchParams {
const { search } = useLocation(); const { search } = useLocation();
return useMemo(() => new URLSearchParams(search), [search]); return useMemo(() => new URLSearchParams(search), [search]);

View File

@ -1,4 +1,4 @@
import { span } from 'store/actions'; import { Span } from 'types/api/trace/getTraceItem';
export const colors = [ export const colors = [
'#2F80ED', '#2F80ED',
@ -21,7 +21,9 @@ const getRandomColor = (): string => {
return colors[index]; return colors[index];
}; };
export const spanServiceNameToColorMapping = (spans: span[]) => { export const spanServiceNameToColorMapping = (
spans: Span[],
): { [key: string]: string } => {
const serviceNameSet = new Set(); const serviceNameSet = new Set();
spans.forEach((spanItem) => { spans.forEach((spanItem) => {
serviceNameSet.add(spanItem[3]); serviceNameSet.add(spanItem[3]);

View File

@ -1,9 +1,7 @@
const getMinAgo = ({ minutes }: getMinAgoProps): Date => { const getMinAgo = ({ minutes }: getMinAgoProps): Date => {
const currentDate = new Date(); const currentDate = new Date();
const agoDate = new Date(currentDate.getTime() - minutes * 60000); return new Date(currentDate.getTime() - minutes * 60000);
return agoDate;
}; };
interface getMinAgoProps { interface getMinAgoProps {

View File

@ -12,7 +12,10 @@ interface GetStepInput {
/** /**
* Converts given timestamp to ms. * Converts given timestamp to ms.
*/ */
const convertToMs = (timestamp: number, inputFormat: DateInputFormatType) => { const convertToMs = (
timestamp: number,
inputFormat: DateInputFormatType,
): number => {
switch (inputFormat) { switch (inputFormat) {
case 's': case 's':
return timestamp * 1e3; return timestamp * 1e3;

View File

@ -1,7 +1,7 @@
const convertObjectIntoParams = ( const convertObjectIntoParams = (
props: Record<any, any>, props: Record<string, unknown>,
stringify = false, stringify = false,
) => { ): string => {
return Object.keys(props) return Object.keys(props)
.map( .map(
(e) => (e) =>

View File

@ -18,7 +18,7 @@ const SettingsPage = (): JSX.Element => {
route: ROUTES.SETTINGS, route: ROUTES.SETTINGS,
}, },
{ {
Component: () => { Component: (): JSX.Element => {
return <CreateAlertChannels />; return <CreateAlertChannels />;
}, },
name: 'Alert Channels', name: 'Alert Channels',

View File

@ -1,9 +1,9 @@
import AlertChannels from 'container/AllAlertChannels';
import GeneralSettings from 'container/GeneralSettings';
import React from 'react';
import RouteTab from 'components/RouteTab'; import RouteTab from 'components/RouteTab';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import AlertChannels from 'container/AllAlertChannels';
import GeneralSettings from 'container/GeneralSettings';
import history from 'lib/history'; import history from 'lib/history';
import React from 'react';
const AllAlertChannels = (): JSX.Element => { const AllAlertChannels = (): JSX.Element => {
const pathName = history.location.pathname; const pathName = history.location.pathname;

View File

@ -26,6 +26,9 @@ const CreateAlert = (): JSX.Element => {
}); });
const [notifications, Element] = notification.useNotification(); const [notifications, Element] = notification.useNotification();
const defaultError =
'Oops! Some issue occured in saving the alert please try again or contact support@signoz.io';
const onSaveHandler = useCallback(async () => { const onSaveHandler = useCallback(async () => {
try { try {
setNewAlertState((state) => ({ setNewAlertState((state) => ({
@ -65,24 +68,19 @@ const CreateAlert = (): JSX.Element => {
}, 3000); }, 3000);
} else { } else {
notifications.error({ notifications.error({
description: description: response.error || defaultError,
response.error ||
'Oops! Some issue occured in saving the alert please try again or contact support@signoz.io',
message: 'Error', message: 'Error',
}); });
setNewAlertState((state) => ({ setNewAlertState((state) => ({
...state, ...state,
loading: false, loading: false,
error: true, error: true,
errorMessage: errorMessage: response.error || defaultError,
response.error ||
'Oops! Some issue occured in saving the alert please try again or contact support@signoz.io',
})); }));
} }
} catch (error) { } catch (error) {
notifications.error({ notifications.error({
message: message: defaultError,
'Oops! Some issue occured in saving the alert please try again or contact support@signoz.io',
}); });
} }
}, [notifications]); }, [notifications]);

View File

@ -1,3 +1,4 @@
import getLocalStorageKey from 'api/browser/localstorage/get';
import Spinner from 'components/Spinner'; import Spinner from 'components/Spinner';
import { SKIP_ONBOARDING } from 'constants/onboarding'; import { SKIP_ONBOARDING } from 'constants/onboarding';
import MetricTable from 'container/MetricsTable'; import MetricTable from 'container/MetricsTable';
@ -10,7 +11,6 @@ import { AppState } from 'store/reducers';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import MetricReducer from 'types/reducer/metrics'; import MetricReducer from 'types/reducer/metrics';
import getLocalStorageKey from 'api/browser/localstorage/get';
const Metrics = ({ getService }: MetricsProps): JSX.Element => { const Metrics = ({ getService }: MetricsProps): JSX.Element => {
const { minTime, maxTime, loading, selectedTime } = useSelector< const { minTime, maxTime, loading, selectedTime } = useSelector<

View File

@ -1,9 +1,9 @@
import AlertChannels from 'container/AllAlertChannels';
import GeneralSettings from 'container/GeneralSettings';
import React from 'react';
import RouteTab from 'components/RouteTab'; import RouteTab from 'components/RouteTab';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import AlertChannels from 'container/AllAlertChannels';
import GeneralSettings from 'container/GeneralSettings';
import history from 'lib/history'; import history from 'lib/history';
import React from 'react';
const SettingsPage = (): JSX.Element => { const SettingsPage = (): JSX.Element => {
const pathName = history.location.pathname; const pathName = history.location.pathname;

View File

@ -1,20 +1,23 @@
import { import {
Button, Button,
Card,
Input, Input,
notification, notification,
Typography,
Switch,
Space, Space,
Card, Switch,
Typography,
} from 'antd'; } from 'antd';
import setLocalStorageKey from 'api/browser/localstorage/set';
import signup from 'api/user/signup'; import signup from 'api/user/signup';
import ROUTES from 'constants/routes'; import ROUTES from 'constants/routes';
import history from 'lib/history'; import history from 'lib/history';
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import setLocalStorageKey from 'api/browser/localstorage/set';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
const { Title } = Typography; const { Title } = Typography;
import setPreference from 'api/user/setPreference';
import { IS_LOGGED_IN } from 'constants/auth';
import { useDispatch } from 'react-redux';
import { Dispatch } from 'redux';
import { PayloadProps } from 'types/api/user/getUserPreference'; import { PayloadProps } from 'types/api/user/getUserPreference';
import { import {
@ -26,10 +29,6 @@ import {
Logo, Logo,
MarginTop, MarginTop,
} from './styles'; } from './styles';
import { IS_LOGGED_IN } from 'constants/auth';
import { useDispatch } from 'react-redux';
import { Dispatch } from 'redux';
import setPreference from 'api/user/setPreference';
const Signup = ({ version, userpref }: SignupProps): JSX.Element => { const Signup = ({ version, userpref }: SignupProps): JSX.Element => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@ -52,7 +51,7 @@ const Signup = ({ version, userpref }: SignupProps): JSX.Element => {
const setState = ( const setState = (
value: string, value: string,
setFunction: React.Dispatch<React.SetStateAction<string>>, setFunction: React.Dispatch<React.SetStateAction<string>>,
) => { ): void => {
setFunction(value); setFunction(value);
}; };
@ -109,7 +108,7 @@ const Signup = ({ version, userpref }: SignupProps): JSX.Element => {
const onSwitchHandler = ( const onSwitchHandler = (
value: boolean, value: boolean,
setFunction: React.Dispatch<React.SetStateAction<boolean>>, setFunction: React.Dispatch<React.SetStateAction<boolean>>,
) => { ): void => {
setFunction(value); setFunction(value);
}; };

View File

@ -1,15 +1,15 @@
import useFetch from 'hooks/useFetch';
import React from 'react';
import SignUpComponent from './SignUp';
import getVersion from 'api/user/getVersion';
import { PayloadProps as VersionPayload } from 'types/api/user/getVersion';
import { PayloadProps as UserPrefPayload } from 'types/api/user/getUserPreference';
import Spinner from 'components/Spinner';
import { Typography } from 'antd'; import { Typography } from 'antd';
import getPreference from 'api/user/getPreference'; import getPreference from 'api/user/getPreference';
import getVersion from 'api/user/getVersion';
import Spinner from 'components/Spinner';
import useFetch from 'hooks/useFetch';
import React from 'react';
import { PayloadProps as UserPrefPayload } from 'types/api/user/getUserPreference';
import { PayloadProps as VersionPayload } from 'types/api/user/getVersion';
const SignUp = () => { import SignUpComponent from './SignUp';
const SignUp = (): JSX.Element => {
const versionResponse = useFetch<VersionPayload, undefined>(getVersion); const versionResponse = useFetch<VersionPayload, undefined>(getVersion);
const userPrefResponse = useFetch<UserPrefPayload, undefined>(getPreference); const userPrefResponse = useFetch<UserPrefPayload, undefined>(getPreference);

View File

@ -45,7 +45,7 @@ interface Props {
} }
export const MarginTop = styled.div<Props>` export const MarginTop = styled.div<Props>`
margin-top: ${({ marginTop }) => marginTop}; margin-top: ${({ marginTop = 0 }): number | string => marginTop};
`; `;
export const Logo = styled.img` export const Logo = styled.img`

View File

@ -23,10 +23,10 @@ import { GlobalReducer } from 'types/reducer/globalTime';
import { TraceReducer } from 'types/reducer/trace'; import { TraceReducer } from 'types/reducer/trace';
import { import {
ClearAllFilter,
Container, Container,
LeftContainer, LeftContainer,
RightContainer, RightContainer,
ClearAllFilter,
} from './styles'; } from './styles';
const Trace = ({ const Trace = ({

View File

@ -1,5 +1,5 @@
import styled from 'styled-components';
import { Button, Card } from 'antd'; import { Button, Card } from 'antd';
import styled from 'styled-components';
export const Container = styled.div` export const Container = styled.div`
display: flex; display: flex;

View File

@ -1,11 +1,11 @@
import React from 'react'; import { Typography } from 'antd';
import useFetch from 'hooks/useFetch';
import getTraceItem from 'api/trace/getTraceItem'; import getTraceItem from 'api/trace/getTraceItem';
import Spinner from 'components/Spinner';
import TraceDetailContainer from 'container/TraceDetail';
import useFetch from 'hooks/useFetch';
import React from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { Props as TraceDetailProps } from 'types/api/trace/getTraceItem'; import { Props as TraceDetailProps } from 'types/api/trace/getTraceItem';
import Spinner from 'components/Spinner';
import { Typography } from 'antd';
import TraceDetailContainer from 'container/TraceDetail';
const TraceDetail = (): JSX.Element => { const TraceDetail = (): JSX.Element => {
const { id } = useParams<TraceDetailProps>(); const { id } = useParams<TraceDetailProps>();

View File

@ -6,10 +6,10 @@ import GetMaxMinTime from 'lib/getMaxMinTime';
import GetMinMax from 'lib/getMinMax'; import GetMinMax from 'lib/getMinMax';
import GetStartAndEndTime from 'lib/getStartAndEndTime'; import GetStartAndEndTime from 'lib/getStartAndEndTime';
import { Dispatch } from 'redux'; import { Dispatch } from 'redux';
import store from 'store';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import { Query } from 'types/api/dashboard/getAll'; import { Query } from 'types/api/dashboard/getAll';
import { GlobalReducer } from 'types/reducer/globalTime'; import { GlobalReducer } from 'types/reducer/globalTime';
import store from 'store';
export const GetQueryResults = ( export const GetQueryResults = (
props: GetQueryResultsProps, props: GetQueryResultsProps,

View File

@ -39,8 +39,6 @@ export const GetInitialData = (
globalTime.maxTime / 1000000, globalTime.maxTime / 1000000,
]); ]);
const step = 60;
const [ const [
// getDBOverViewResponse, // getDBOverViewResponse,
// getExternalAverageDurationResponse, // getExternalAverageDurationResponse,

View File

@ -1,25 +1,26 @@
import { notification } from 'antd';
import getFiltersApi from 'api/trace/getFilters';
import xor from 'lodash-es/xor';
import { Dispatch, Store } from 'redux'; import { Dispatch, Store } from 'redux';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import { GlobalReducer } from 'types/reducer/globalTime';
import getFiltersApi from 'api/trace/getFilters';
import {
parseSelectedFilter,
parseFilterToFetchData,
parseQueryIntoCurrent,
parseQueryIntoSelectedTags,
isTraceFilterEnum,
parseQueryIntoFilter,
parseIsSkippedSelection,
parseFilterExclude,
} from './util';
import { import {
UPDATE_ALL_FILTERS, UPDATE_ALL_FILTERS,
UPDATE_TRACE_FILTER_LOADING, UPDATE_TRACE_FILTER_LOADING,
} from 'types/actions/trace'; } from 'types/actions/trace';
import { GlobalReducer } from 'types/reducer/globalTime';
import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace'; import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace';
import { notification } from 'antd';
import xor from 'lodash-es/xor'; import {
isTraceFilterEnum,
parseFilterExclude,
parseFilterToFetchData,
parseIsSkippedSelection,
parseQueryIntoCurrent,
parseQueryIntoFilter,
parseQueryIntoSelectedTags,
parseSelectedFilter,
} from './util';
export const GetInitialTraceFilter = ( export const GetInitialTraceFilter = (
minTime: GlobalReducer['minTime'], minTime: GlobalReducer['minTime'],
@ -89,7 +90,7 @@ export const GetInitialTraceFilter = (
isFilterExclude: getIsFilterExcluded.currentValue, isFilterExclude: getIsFilterExcluded.currentValue,
}); });
let preSelectedFilter: Map<TraceFilterEnum, string[]> = new Map( const preSelectedFilter: Map<TraceFilterEnum, string[]> = new Map(
getSelectedFilter.currentValue, getSelectedFilter.currentValue,
); );

View File

@ -1,3 +1,5 @@
import { notification } from 'antd';
import getSpans from 'api/trace/getSpans';
import { Dispatch, Store } from 'redux'; import { Dispatch, Store } from 'redux';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
@ -6,9 +8,7 @@ import {
UPDATE_TRACE_GRAPH_LOADING, UPDATE_TRACE_GRAPH_LOADING,
UPDATE_TRACE_GRAPH_SUCCESS, UPDATE_TRACE_GRAPH_SUCCESS,
} from 'types/actions/trace'; } from 'types/actions/trace';
import getSpans from 'api/trace/getSpans';
import { Props } from 'types/api/trace/getSpans'; import { Props } from 'types/api/trace/getSpans';
import { notification } from 'antd';
export const GetSpans = ( export const GetSpans = (
props: GetSpansProps, props: GetSpansProps,

View File

@ -1,4 +1,5 @@
import { TraceReducer } from 'types/reducer/trace'; import { TraceReducer } from 'types/reducer/trace';
import { ParsedUrl } from '../util'; import { ParsedUrl } from '../util';
export const parseQueryIntoCurrent = ( export const parseQueryIntoCurrent = (

View File

@ -1,4 +1,5 @@
import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace'; import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace';
import { isTraceFilterEnum, ParsedUrl } from '../util'; import { isTraceFilterEnum, ParsedUrl } from '../util';
export const parseQueryIntoFilter = ( export const parseQueryIntoFilter = (

View File

@ -1,4 +1,5 @@
import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace'; import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace';
import { ParsedUrl } from '../util'; import { ParsedUrl } from '../util';
export const parseFilterToFetchData = ( export const parseFilterToFetchData = (
@ -7,7 +8,7 @@ export const parseFilterToFetchData = (
): ParsedUrl<TraceFilterEnum[]> => { ): ParsedUrl<TraceFilterEnum[]> => {
const url = new URLSearchParams(query); const url = new URLSearchParams(query);
let filterToFetchData: TraceFilterEnum[] = []; const filterToFetchData: TraceFilterEnum[] = [];
const selected = url.get('filterToFetchData'); const selected = url.get('filterToFetchData');

View File

@ -1,8 +1,8 @@
export * from './current';
export * from './filter';
export * from './filterToFetchData';
export * from './isFilterExclude';
export * from './minMaxTime'; export * from './minMaxTime';
export * from './selectedFilter'; export * from './selectedFilter';
export * from './filterToFetchData';
export * from './selectedTags'; export * from './selectedTags';
export * from './filter';
export * from './skippedSelected'; export * from './skippedSelected';
export * from './current';
export * from './isFilterExclude';

View File

@ -1,4 +1,5 @@
import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace'; import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace';
import { isTraceFilterEnum, ParsedUrl } from '../util'; import { isTraceFilterEnum, ParsedUrl } from '../util';
export const parseFilterExclude = ( export const parseFilterExclude = (

View File

@ -1,4 +1,5 @@
import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace'; import { TraceFilterEnum, TraceReducer } from 'types/reducer/trace';
import { isTraceFilterEnum, ParsedUrl } from '../util'; import { isTraceFilterEnum, ParsedUrl } from '../util';
export const parseSelectedFilter = ( export const parseSelectedFilter = (

View File

@ -1,4 +1,5 @@
import { TraceReducer } from 'types/reducer/trace'; import { TraceReducer } from 'types/reducer/trace';
import { ParsedUrl } from '../util'; import { ParsedUrl } from '../util';
export const parseQueryIntoSelectedTags = ( export const parseQueryIntoSelectedTags = (

View File

@ -2,6 +2,7 @@ import { Dispatch, Store } from 'redux';
import { AppState } from 'store/reducers'; import { AppState } from 'store/reducers';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import { TraceFilterEnum } from 'types/reducer/trace'; import { TraceFilterEnum } from 'types/reducer/trace';
import { updateURL } from './util'; import { updateURL } from './util';
export const SelectedTraceFilter = (props: { export const SelectedTraceFilter = (props: {

View File

@ -1,7 +1,7 @@
import { Dispatch } from 'redux'; import { Dispatch } from 'redux';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import { TraceReducer } from 'types/reducer/trace';
import { UPDATE_IS_TAG_ERROR } from 'types/actions/trace'; import { UPDATE_IS_TAG_ERROR } from 'types/actions/trace';
import { TraceReducer } from 'types/reducer/trace';
export const UpdateTagIsError = ( export const UpdateTagIsError = (
isTagModalError: TraceReducer['isTagModalError'], isTagModalError: TraceReducer['isTagModalError'],

View File

@ -1,7 +1,7 @@
import { Dispatch } from 'redux'; import { Dispatch } from 'redux';
import AppActions from 'types/actions'; import AppActions from 'types/actions';
import { TraceReducer } from 'types/reducer/trace';
import { UPDATE_TAG_MODAL_VISIBLITY } from 'types/actions/trace'; import { UPDATE_TAG_MODAL_VISIBLITY } from 'types/actions/trace';
import { TraceReducer } from 'types/reducer/trace';
export const UpdateTagVisiblity = ( export const UpdateTagVisiblity = (
isTagModalOpen: TraceReducer['isTagModalOpen'], isTagModalOpen: TraceReducer['isTagModalOpen'],

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