mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-11 18:48:59 +08:00
Fix(FE): dark mode (#301)
* fix: fav icon is fixed and bootstrap is removed * fix: return type is updated for the global time reducer * fix: theme.css is replaced with .min.css * update: useThemeSwitcher is removed from the graph component and value is grabed from the reducer * update: instrumentation page is updated * update: react-css-theme-switcher package is removed * update: darkMode is updated * fix: Sider component is updated
This commit is contained in:
parent
ea5b40c7ea
commit
93b347d25e
10
frontend/public/css/antd.dark.min.css
vendored
Normal file
10
frontend/public/css/antd.dark.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
10
frontend/public/css/antd.min.css
vendored
Normal file
10
frontend/public/css/antd.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Before Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB |
@ -1,5 +1,3 @@
|
|||||||
@import '~antd/dist/antd.dark.css';
|
|
||||||
|
|
||||||
.ant-space-item {
|
.ant-space-item {
|
||||||
margin-right: 0 !important;
|
margin-right: 0 !important;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,9 @@ import chartjsAdapter from 'chartjs-adapter-date-fns';
|
|||||||
// import { colors } from 'lib/getRandomColor';
|
// import { colors } from 'lib/getRandomColor';
|
||||||
// import stringToHTML from 'lib/stringToHTML';
|
// import stringToHTML from 'lib/stringToHTML';
|
||||||
import React, { useCallback, useEffect, useRef } from 'react';
|
import React, { useCallback, useEffect, useRef } from 'react';
|
||||||
import { useThemeSwitcher } from 'react-css-theme-switcher';
|
import { useSelector } from 'react-redux';
|
||||||
|
import { AppState } from 'store/reducers';
|
||||||
|
import AppReducer from 'types/reducer/app';
|
||||||
|
|
||||||
// import Legends from './Legend';
|
// import Legends from './Legend';
|
||||||
// import { LegendsContainer } from './styles';
|
// import { LegendsContainer } from './styles';
|
||||||
@ -55,8 +57,9 @@ const Graph = ({
|
|||||||
xAxisType,
|
xAxisType,
|
||||||
onClickHandler,
|
onClickHandler,
|
||||||
}: GraphProps): JSX.Element => {
|
}: GraphProps): JSX.Element => {
|
||||||
|
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||||
const chartRef = useRef<HTMLCanvasElement>(null);
|
const chartRef = useRef<HTMLCanvasElement>(null);
|
||||||
const { currentTheme } = useThemeSwitcher();
|
const currentTheme = isDarkMode ? 'dark' : 'light';
|
||||||
|
|
||||||
// const [tooltipVisible, setTooltipVisible] = useState<boolean>(false);
|
// const [tooltipVisible, setTooltipVisible] = useState<boolean>(false);
|
||||||
const lineChartRef = useRef<Chart>();
|
const lineChartRef = useRef<Chart>();
|
||||||
|
@ -1,28 +1,45 @@
|
|||||||
import { Layout, Menu, Switch as ToggleButton, Typography } from 'antd';
|
import { Menu, Switch as ToggleButton, Typography } from 'antd';
|
||||||
import ROUTES from 'constants/routes';
|
import ROUTES from 'constants/routes';
|
||||||
|
import history from 'lib/history';
|
||||||
import React, { useCallback, useState } from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
import { useThemeSwitcher } from 'react-css-theme-switcher';
|
import { connect, useSelector } from 'react-redux';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
|
import { bindActionCreators } from 'redux';
|
||||||
import { Logo, ThemeSwitcherWrapper } from './styles';
|
import { ThunkDispatch } from 'redux-thunk';
|
||||||
const { Sider } = Layout;
|
import { ToggleDarkMode } from 'store/actions';
|
||||||
import history from 'lib/history';
|
import { AppState } from 'store/reducers';
|
||||||
|
import AppActions from 'types/actions';
|
||||||
|
import AppReducer from 'types/reducer/app';
|
||||||
|
|
||||||
import menus from './menuItems';
|
import menus from './menuItems';
|
||||||
|
import { Logo, Sider, ThemeSwitcherWrapper } from './styles';
|
||||||
|
|
||||||
const SideNav = (): JSX.Element => {
|
const SideNav = ({ toggleDarkMode }: Props): JSX.Element => {
|
||||||
const { switcher, currentTheme, themes } = useThemeSwitcher();
|
|
||||||
|
|
||||||
const [collapsed, setCollapsed] = useState<boolean>(false);
|
const [collapsed, setCollapsed] = useState<boolean>(false);
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
|
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||||
|
|
||||||
const toggleTheme = useCallback(
|
const toggleTheme = useCallback(() => {
|
||||||
(isChecked: boolean) => {
|
const preMode: mode = isDarkMode ? 'lightMode' : 'darkMode';
|
||||||
switcher({ theme: isChecked ? themes.dark : themes.light });
|
const postMode: mode = isDarkMode ? 'darkMode' : 'lightMode';
|
||||||
},
|
|
||||||
[switcher, themes],
|
const id: mode = preMode;
|
||||||
);
|
const head = document.head;
|
||||||
|
const link = document.createElement('link');
|
||||||
|
link.rel = 'stylesheet';
|
||||||
|
link.type = 'text/css';
|
||||||
|
link.href = !isDarkMode ? './css/antd.dark.min.css' : './css/antd.min.css';
|
||||||
|
link.media = 'all';
|
||||||
|
link.id = id;
|
||||||
|
head.appendChild(link);
|
||||||
|
|
||||||
|
link.onload = (): void => {
|
||||||
|
toggleDarkMode();
|
||||||
|
const prevNode = document.getElementById(postMode);
|
||||||
|
prevNode?.remove();
|
||||||
|
};
|
||||||
|
}, [toggleDarkMode, isDarkMode]);
|
||||||
|
|
||||||
const onCollapse = useCallback(() => {
|
const onCollapse = useCallback(() => {
|
||||||
setCollapsed((collapsed) => !collapsed);
|
setCollapsed((collapsed) => !collapsed);
|
||||||
@ -33,12 +50,9 @@ const SideNav = (): JSX.Element => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sider collapsible collapsed={collapsed} onCollapse={onCollapse} width={160}>
|
<Sider collapsible collapsed={collapsed} onCollapse={onCollapse} width={200}>
|
||||||
<ThemeSwitcherWrapper>
|
<ThemeSwitcherWrapper>
|
||||||
<ToggleButton
|
<ToggleButton checked={isDarkMode} onChange={toggleTheme} />
|
||||||
checked={currentTheme === themes.dark}
|
|
||||||
onChange={toggleTheme}
|
|
||||||
/>
|
|
||||||
</ThemeSwitcherWrapper>
|
</ThemeSwitcherWrapper>
|
||||||
<NavLink to="/">
|
<NavLink to="/">
|
||||||
<Logo src={'/signoz.svg'} alt="SigNoz" collapsed={collapsed} />
|
<Logo src={'/signoz.svg'} alt="SigNoz" collapsed={collapsed} />
|
||||||
@ -62,4 +76,18 @@ const SideNav = (): JSX.Element => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SideNav;
|
type mode = 'darkMode' | 'lightMode';
|
||||||
|
|
||||||
|
interface DispatchProps {
|
||||||
|
toggleDarkMode: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (
|
||||||
|
dispatch: ThunkDispatch<unknown, unknown, AppActions>,
|
||||||
|
): DispatchProps => ({
|
||||||
|
toggleDarkMode: bindActionCreators(ToggleDarkMode, dispatch),
|
||||||
|
});
|
||||||
|
|
||||||
|
type Props = DispatchProps;
|
||||||
|
|
||||||
|
export default connect(null, mapDispatchToProps)(SideNav);
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
import { Layout } from 'antd';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
const { Sider: SiderComponent } = Layout;
|
||||||
|
|
||||||
export const ThemeSwitcherWrapper = styled.div`
|
export const ThemeSwitcherWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -16,3 +18,9 @@ export const Logo = styled.img<LogoProps>`
|
|||||||
interface LogoProps {
|
interface LogoProps {
|
||||||
collapsed: boolean;
|
collapsed: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const Sider = styled(SiderComponent)`
|
||||||
|
.ant-typography {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
<meta data-react-helmet="true" name="docusaurus_locale" content="en">
|
<meta data-react-helmet="true" name="docusaurus_locale" content="en">
|
||||||
<meta data-react-helmet="true" name="docusaurus_tag" content="default">
|
<meta data-react-helmet="true" name="docusaurus_tag" content="default">
|
||||||
<link data-react-helmet="true" rel="shortcut icon" href="/favicon.ico">
|
<link data-react-helmet="true" rel="shortcut icon" href="/favicon.ico">
|
||||||
|
|
||||||
|
<link id='darkMode' rel='stylesheet' type='text/css' href='./css/antd.dark.min.css' />
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
@ -2,18 +2,14 @@ import 'assets/index.css';
|
|||||||
|
|
||||||
import AppRoutes from 'AppRoutes';
|
import AppRoutes from 'AppRoutes';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ThemeSwitcherProvider } from 'react-css-theme-switcher';
|
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import store from 'store';
|
import store from 'store';
|
||||||
import themes from 'themes';
|
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<ThemeSwitcherProvider themeMap={themes} defaultTheme="dark">
|
<AppRoutes />
|
||||||
<AppRoutes />
|
|
||||||
</ThemeSwitcherProvider>
|
|
||||||
</React.StrictMode>
|
</React.StrictMode>
|
||||||
</Provider>,
|
</Provider>,
|
||||||
document.querySelector('#root'),
|
document.querySelector('#root'),
|
||||||
|
@ -1,25 +1,22 @@
|
|||||||
import { Space } from 'antd';
|
import { Space } from 'antd';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useThemeSwitcher } from 'react-css-theme-switcher';
|
import { useSelector } from 'react-redux';
|
||||||
import { connect } from 'react-redux';
|
|
||||||
import { AppState } from 'store/reducers';
|
import { AppState } from 'store/reducers';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import AppReducer from 'types/reducer/app';
|
||||||
|
|
||||||
const InstrumentCard = styled.div<{
|
const InstrumentCard = styled.div<{
|
||||||
currentThemeStatus: string | undefined;
|
isDarkMode: boolean;
|
||||||
}>`
|
}>`
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: ${({ currentThemeStatus }): string =>
|
background: ${({ isDarkMode }): string => (isDarkMode ? '#313131' : '#ddd')};
|
||||||
currentThemeStatus === 'dark' ? '#313131' : '#ddd'};
|
|
||||||
padding: 33px 23px;
|
padding: 33px 23px;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin-top: 40px;
|
margin-top: 40px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
interface InstrumentationPageProps {}
|
const InstrumentationPage = (): JSX.Element => {
|
||||||
|
const { isDarkMode } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||||
const InstrumentationPage = (props: InstrumentationPageProps) => {
|
|
||||||
const { currentTheme } = useThemeSwitcher();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
@ -27,7 +24,7 @@ const InstrumentationPage = (props: InstrumentationPageProps) => {
|
|||||||
<div>
|
<div>
|
||||||
<h2>Instrument your application</h2>
|
<h2>Instrument your application</h2>
|
||||||
</div>
|
</div>
|
||||||
<InstrumentCard currentThemeStatus={currentTheme}>
|
<InstrumentCard isDarkMode={isDarkMode}>
|
||||||
Congrats, you have successfully installed SigNoz!
|
Congrats, you have successfully installed SigNoz!
|
||||||
<br />
|
<br />
|
||||||
To start seeing YOUR application data here, follow the instructions in the
|
To start seeing YOUR application data here, follow the instructions in the
|
||||||
@ -61,8 +58,4 @@ const InstrumentationPage = (props: InstrumentationPageProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state: AppState): {} => {
|
export default InstrumentationPage;
|
||||||
return {};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, {})(InstrumentationPage);
|
|
||||||
|
1
frontend/src/store/actions/app/index.ts
Normal file
1
frontend/src/store/actions/app/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './toggleDarkMode';
|
12
frontend/src/store/actions/app/toggleDarkMode.ts
Normal file
12
frontend/src/store/actions/app/toggleDarkMode.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { Dispatch } from 'redux';
|
||||||
|
import AppActions from 'types/actions';
|
||||||
|
|
||||||
|
export const ToggleDarkMode = (): ((
|
||||||
|
dispatch: Dispatch<AppActions>,
|
||||||
|
) => void) => {
|
||||||
|
return (dispatch: Dispatch<AppActions>): void => {
|
||||||
|
dispatch({
|
||||||
|
type: 'SWITCH_DARK_MODE',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
@ -1,3 +1,4 @@
|
|||||||
|
export * from './app';
|
||||||
export * from './dashboard';
|
export * from './dashboard';
|
||||||
export * from './global';
|
export * from './global';
|
||||||
export * from './MetricsActions';
|
export * from './MetricsActions';
|
||||||
|
25
frontend/src/store/reducers/app.ts
Normal file
25
frontend/src/store/reducers/app.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { AppAction, SWITCH_DARK_MODE } from 'types/actions/app';
|
||||||
|
import InitialValueTypes from 'types/reducer/app';
|
||||||
|
|
||||||
|
const InitialValue: InitialValueTypes = {
|
||||||
|
isDarkMode: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const appReducer = (
|
||||||
|
state = InitialValue,
|
||||||
|
action: AppAction,
|
||||||
|
): InitialValueTypes => {
|
||||||
|
switch (action.type) {
|
||||||
|
case SWITCH_DARK_MODE: {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
isDarkMode: !state.isDarkMode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default appReducer;
|
@ -6,7 +6,7 @@ export const updateGlobalTimeReducer = (
|
|||||||
minTime: (Date.now() - 15 * 60 * 1000) * 1000000,
|
minTime: (Date.now() - 15 * 60 * 1000) * 1000000,
|
||||||
},
|
},
|
||||||
action: Action,
|
action: Action,
|
||||||
) => {
|
): GlobalTime => {
|
||||||
// Initial global state is time now and 15 minute interval
|
// Initial global state is time now and 15 minute interval
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ActionTypes.updateTimeInterval:
|
case ActionTypes.updateTimeInterval:
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { combineReducers } from 'redux';
|
import { combineReducers } from 'redux';
|
||||||
|
|
||||||
|
import appReducer from './app';
|
||||||
import dashboardReducer from './dashboard';
|
import dashboardReducer from './dashboard';
|
||||||
import { updateGlobalTimeReducer } from './global';
|
import { updateGlobalTimeReducer } from './global';
|
||||||
import { metricsReducer } from './metrics';
|
import { metricsReducer } from './metrics';
|
||||||
@ -17,6 +18,7 @@ const reducers = combineReducers({
|
|||||||
metricsData: metricsReducer,
|
metricsData: metricsReducer,
|
||||||
serviceMap: ServiceMapReducer,
|
serviceMap: ServiceMapReducer,
|
||||||
dashboards: dashboardReducer,
|
dashboards: dashboardReducer,
|
||||||
|
app: appReducer,
|
||||||
});
|
});
|
||||||
|
|
||||||
export type AppState = ReturnType<typeof reducers>;
|
export type AppState = ReturnType<typeof reducers>;
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
const themes = {
|
|
||||||
dark: '/dark-theme.css',
|
|
||||||
light: '/light-theme.css',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default themes;
|
|
7
frontend/src/types/actions/app.ts
Normal file
7
frontend/src/types/actions/app.ts
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
export const SWITCH_DARK_MODE = 'SWITCH_DARK_MODE';
|
||||||
|
|
||||||
|
export interface SwitchDarkMode {
|
||||||
|
type: typeof SWITCH_DARK_MODE;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AppAction = SwitchDarkMode;
|
@ -1,5 +1,6 @@
|
|||||||
|
import { AppAction } from './app';
|
||||||
import { DashboardActions } from './dashboard';
|
import { DashboardActions } from './dashboard';
|
||||||
|
|
||||||
type AppActions = DashboardActions;
|
type AppActions = DashboardActions | AppAction;
|
||||||
|
|
||||||
export default AppActions;
|
export default AppActions;
|
||||||
|
3
frontend/src/types/reducer/app.ts
Normal file
3
frontend/src/types/reducer/app.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export default interface AppReducer {
|
||||||
|
isDarkMode: boolean;
|
||||||
|
}
|
@ -11891,11 +11891,6 @@ react-chips@^0.8.0:
|
|||||||
react-autosuggest "^9.0.1"
|
react-autosuggest "^9.0.1"
|
||||||
react-themeable "^1.1.0"
|
react-themeable "^1.1.0"
|
||||||
|
|
||||||
react-css-theme-switcher@^0.1.6:
|
|
||||||
version "0.1.6"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-css-theme-switcher/-/react-css-theme-switcher-0.1.6.tgz#9b765e4ffa7d1ce092ff11c5524b1466990e9eaf"
|
|
||||||
integrity sha512-GG5OqeWTWJFH3Vbd42Tj0QVUwh/uBN/ki7EOTUL99wbzxulX8bof3NOdRHzY6j7746HNZ72s8Ko4TjO3GaWdxA==
|
|
||||||
|
|
||||||
react-dev-utils@^11.0.0:
|
react-dev-utils@^11.0.0:
|
||||||
version "11.0.4"
|
version "11.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-11.0.4.tgz#a7ccb60257a1ca2e0efe7a83e38e6700d17aa37a"
|
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-11.0.4.tgz#a7ccb60257a1ca2e0efe7a83e38e6700d17aa37a"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user