801 dropdown is added in the dashboard page (#1669)

* chore: update the import from constant rather than static string

* chore: removed redundant div

* feat: added auto refresh component

* refactor: top nav is refactored
This commit is contained in:
Palash Gupta 2022-11-10 20:48:40 +05:30 committed by GitHub
parent a3b03ef0ca
commit 65af8c1b98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 250 additions and 46 deletions

View File

@ -11,3 +11,5 @@ export const INVITE_MEMBERS_HASH = '#invite-team-members';
export const SIGNOZ_UPGRADE_PLAN_URL =
'https://upgrade.signoz.io/upgrade-from-app';
export const DASHBOARD_TIME_IN_DURATION = 'refreshInterval';

View File

@ -0,0 +1,63 @@
export const options: IOptions[] = [
{
label: '',
key: 'off',
value: 0,
},
{
label: '5s',
key: '5s',
value: 5000,
},
{
label: '10s',
key: '10s',
value: 10000,
},
{
label: '30s',
key: '30s',
value: 30000,
},
{
label: '1m',
key: '1m',
value: 60000,
},
{
label: '5m',
key: '5m',
value: 300000,
},
{
label: '10m',
key: '10m',
value: 600000,
},
{
label: '30m',
key: '30m',
value: 1800000,
},
{
label: '1h',
key: '1h',
value: 3600000,
},
{
label: '2h',
key: '2h',
value: 7200000,
},
{
label: '1d',
key: '1d',
value: 86400000,
},
];
export interface IOptions {
label: string;
key: string;
value: number;
}

View File

@ -0,0 +1,108 @@
import { Select } from 'antd';
import get from 'api/browser/localstorage/get';
import set from 'api/browser/localstorage/set';
import { DASHBOARD_TIME_IN_DURATION } from 'constants/app';
import dayjs from 'dayjs';
import useUrlQuery from 'hooks/useUrlQuery';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom';
import { useInterval } from 'react-use';
import { Dispatch } from 'redux';
import { AppState } from 'store/reducers';
import AppActions from 'types/actions';
import { UPDATE_TIME_INTERVAL } from 'types/actions/globalTime';
import { GlobalReducer } from 'types/reducer/globalTime';
import { options } from './config';
import { SelectContainer } from './styles';
function AutoRefresh({ disabled = false }: AutoRefreshProps): JSX.Element {
const { minTime: initialMinTime, selectedTime } = useSelector<
AppState,
GlobalReducer
>((state) => state.globalTime);
const { pathname } = useLocation();
const params = useUrlQuery();
const localStorageData = JSON.parse(get(DASHBOARD_TIME_IN_DURATION) || '{}');
const localStorageValue = useMemo(() => localStorageData[pathname], [
pathname,
localStorageData,
]);
const dispatch = useDispatch<Dispatch<AppActions>>();
const [selectedOption, setSelectedOption] = useState<string>(
localStorageValue || options[0].key,
);
useEffect(() => {
setSelectedOption(localStorageValue || options[0].key);
}, [localStorageValue, params]);
const getOption = useMemo(
() => options.find((option) => option.key === selectedOption),
[selectedOption],
);
useInterval(() => {
const selectedValue = getOption?.value;
if (disabled) {
return;
}
if (selectedOption !== 'off' && selectedValue) {
const min = initialMinTime / 1000000;
dispatch({
type: UPDATE_TIME_INTERVAL,
payload: {
maxTime: dayjs().valueOf() * 1000000,
minTime: dayjs(min).subtract(selectedValue, 'second').valueOf() * 1000000,
selectedTime,
},
});
}
}, getOption?.value || 0);
const onChangeHandler = useCallback(
(value: unknown) => {
if (typeof value === 'string') {
setSelectedOption(value);
params.set(DASHBOARD_TIME_IN_DURATION, value);
set(
DASHBOARD_TIME_IN_DURATION,
JSON.stringify({ ...localStorageData, [pathname]: value }),
);
}
},
[params, pathname, localStorageData],
);
return (
<SelectContainer
disabled={disabled}
onChange={onChangeHandler}
value={selectedOption}
>
{options.map((option) => (
<Select.Option key={option.key} value={option.key}>
{option.label}
</Select.Option>
))}
</SelectContainer>
);
}
interface AutoRefreshProps {
disabled?: boolean;
}
AutoRefresh.defaultProps = {
disabled: false,
};
export default AutoRefresh;

View File

@ -0,0 +1,9 @@
import { Select } from 'antd';
import styled from 'styled-components';
export const SelectContainer = styled(Select)`
&&& {
width: 100%;
min-width: 4rem;
}
`;

View File

@ -2,7 +2,10 @@ import React, { useEffect, useState } from 'react';
import { RefreshTextContainer, Typography } from './styles';
function RefreshText({ onLastRefreshHandler }: RefreshTextProps): JSX.Element {
function RefreshText({
onLastRefreshHandler,
refreshButtonHidden,
}: RefreshTextProps): JSX.Element {
const [refreshText, setRefreshText] = useState<string>('');
// this is to update the refresh text
@ -19,7 +22,7 @@ function RefreshText({ onLastRefreshHandler }: RefreshTextProps): JSX.Element {
}, [onLastRefreshHandler, refreshText]);
return (
<RefreshTextContainer>
<RefreshTextContainer refreshButtonHidden={refreshButtonHidden}>
<Typography>{refreshText}</Typography>
</RefreshTextContainer>
);
@ -27,6 +30,7 @@ function RefreshText({ onLastRefreshHandler }: RefreshTextProps): JSX.Element {
interface RefreshTextProps {
onLastRefreshHandler: () => string;
refreshButtonHidden: boolean;
}
export default RefreshText;

View File

@ -67,3 +67,19 @@ export const getOptions = (routes: string): Option[] => {
}
return Options;
};
export const routesToSkip = [
ROUTES.SETTINGS,
ROUTES.LIST_ALL_ALERT,
ROUTES.TRACE_DETAIL,
ROUTES.ALL_CHANNELS,
ROUTES.USAGE_EXPLORER,
ROUTES.INSTRUMENTATION,
ROUTES.VERSION,
ROUTES.ALL_DASHBOARD,
ROUTES.ORG_SETTINGS,
ROUTES.ERROR_DETAIL,
ROUTES.ALERTS_NEW,
ROUTES.EDIT_ALERTS,
ROUTES.LIST_ALL_ALERT,
];

View File

@ -1,3 +1,4 @@
import { SyncOutlined } from '@ant-design/icons';
import { Button, Select as DefaultSelect } from 'antd';
import getLocalStorageKey from 'api/browser/localstorage/get';
import setLocalStorageKey from 'api/browser/localstorage/set';
@ -14,10 +15,11 @@ import { AppState } from 'store/reducers';
import AppActions from 'types/actions';
import { GlobalReducer } from 'types/reducer/globalTime';
import AutoRefresh from '../AutoRefresh';
import CustomDateTimeModal, { DateTimeRangeType } from '../CustomDateTimeModal';
import { getDefaultOption, getOptions, Time } from './config';
import RefreshText from './Refresh';
import { Container, Form, FormItem } from './styles';
import { Form, FormItem } from './styles';
const { Option } = DefaultSelect;
@ -240,6 +242,8 @@ function DateTimeSelection({
setStartTime(dayjs(preStartTime));
setEndTime(dayjs(preEndTime));
setRefreshButtonHidden(updatedTime === 'custom');
updateTimeInterval(updatedTime, [preStartTime, preEndTime]);
}, [
location.pathname,
@ -253,7 +257,7 @@ function DateTimeSelection({
]);
return (
<Container>
<>
<Form
form={formSelector}
layout="inline"
@ -272,9 +276,15 @@ function DateTimeSelection({
</DefaultSelect>
<FormItem hidden={refreshButtonHidden}>
<Button type="primary" onClick={onRefreshHandler}>
Refresh
</Button>
<Button
icon={<SyncOutlined />}
type="primary"
onClick={onRefreshHandler}
/>
</FormItem>
<FormItem>
<AutoRefresh disabled={refreshButtonHidden} />
</FormItem>
</Form>
@ -282,6 +292,7 @@ function DateTimeSelection({
{...{
onLastRefreshHandler,
}}
refreshButtonHidden={refreshButtonHidden}
/>
<CustomDateTimeModal
@ -291,7 +302,7 @@ function DateTimeSelection({
setCustomDTPickerVisible(false);
}}
/>
</Container>
</>
);
}

View File

@ -1,10 +1,6 @@
import { Form as FormComponent, Typography as TypographyComponent } from 'antd';
import styled from 'styled-components';
export const Container = styled.div`
justify-content: flex-end;
`;
export const Form = styled(FormComponent)`
&&& {
justify-content: flex-end;
@ -23,6 +19,12 @@ export const FormItem = styled(Form.Item)`
}
`;
export const RefreshTextContainer = styled.div`
interface Props {
refreshButtonHidden: boolean;
}
export const RefreshTextContainer = styled.div<Props>`
min-height: 2rem;
visibility: ${({ refreshButtonHidden }): string =>
refreshButtonHidden ? 'hidden' : 'visible'};
`;

View File

@ -1,52 +1,40 @@
import { Col } from 'antd';
import ROUTES from 'constants/routes';
import history from 'lib/history';
import React from 'react';
import { matchPath } from 'react-router-dom';
import React, { useMemo } from 'react';
import { matchPath, useHistory } from 'react-router-dom';
import ShowBreadcrumbs from './Breadcrumbs';
import DateTimeSelector from './DateTimeSelection';
import { routesToSkip } from './DateTimeSelection/config';
import { Container } from './styles';
const routesToSkip = [
ROUTES.SETTINGS,
ROUTES.LIST_ALL_ALERT,
ROUTES.TRACE_DETAIL,
ROUTES.ALL_CHANNELS,
ROUTES.USAGE_EXPLORER,
ROUTES.INSTRUMENTATION,
ROUTES.VERSION,
ROUTES.ALL_DASHBOARD,
ROUTES.ORG_SETTINGS,
ROUTES.ERROR_DETAIL,
ROUTES.ALERTS_NEW,
ROUTES.EDIT_ALERTS,
ROUTES.LIST_ALL_ALERT,
];
function TopNav(): JSX.Element | null {
if (history.location.pathname === ROUTES.SIGN_UP) {
const { location } = useHistory();
const isRouteToSkip = useMemo(
() =>
routesToSkip.some((route) =>
matchPath(location.pathname, { path: route, exact: true }),
),
[location.pathname],
);
const isSignUpPage = useMemo(
() => matchPath(location.pathname, { path: ROUTES.SIGN_UP, exact: true }),
[location.pathname],
);
if (isSignUpPage) {
return null;
}
const checkRouteExists = (currentPath: string): boolean => {
for (let i = 0; i < routesToSkip.length; i += 1) {
if (
matchPath(currentPath, { path: routesToSkip[i], exact: true, strict: true })
) {
return true;
}
}
return false;
};
return (
<Container>
<Col span={16}>
<ShowBreadcrumbs />
</Col>
{!checkRouteExists(history.location.pathname) && (
{!isRouteToSkip && (
<Col span={8}>
<DateTimeSelector />
</Col>

View File

@ -2,6 +2,7 @@ import { Time } from 'container/TopNav/DateTimeSelection/config';
import GetMinMax from 'lib/getMinMax';
import { Dispatch } from 'redux';
import AppActions from 'types/actions';
import { UPDATE_TIME_INTERVAL } from 'types/actions/globalTime';
export const UpdateTimeInterval = (
interval: Time,
@ -11,7 +12,7 @@ export const UpdateTimeInterval = (
const { maxTime, minTime } = GetMinMax(interval, dateTimeRange);
dispatch({
type: 'UPDATE_TIME_INTERVAL',
type: UPDATE_TIME_INTERVAL,
payload: {
maxTime,
minTime,