mirror of
https://github.com/grafana/grafana.git
synced 2025-02-14 01:23:32 -06:00
DashboardPage: refactored styles from sass to emotion (#32955)
* DashboardPage: refactored styles from sass to emotion * refactored dashboardPage component to be alot easier to read and understand * more refactoring... * more cleaning... * fixes frontend test * fixes frontend test- I hope * fixes frontend test- I hope * moves dashboard scss styles back to it's standalone file
This commit is contained in:
parent
d0ad2931fa
commit
99b85d8af3
@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import { css } from 'emotion';
|
||||
import { Alert, useStyles } from '@grafana/ui';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { DashboardInitError, AppNotificationSeverity } from 'app/types';
|
||||
import { getMessageFromError } from 'app/core/utils/errors';
|
||||
|
||||
export interface Props {
|
||||
initError?: DashboardInitError;
|
||||
}
|
||||
|
||||
export const DashboardFailed = ({ initError }: Props) => {
|
||||
const styles = useStyles(getStyles);
|
||||
if (!initError) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.dashboardLoading}>
|
||||
<Alert severity={AppNotificationSeverity.Error} title={initError.message}>
|
||||
{getMessageFromError(initError.error)}
|
||||
</Alert>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const getStyles = (theme: GrafanaTheme) => {
|
||||
return {
|
||||
dashboardLoading: css`
|
||||
height: 60vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`,
|
||||
};
|
||||
};
|
@ -0,0 +1,48 @@
|
||||
import React from 'react';
|
||||
import { css } from 'emotion';
|
||||
import { Button, HorizontalGroup, Spinner, useStyles, VerticalGroup } from '@grafana/ui';
|
||||
import { locationService } from '@grafana/runtime';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { DashboardInitPhase } from 'app/types';
|
||||
|
||||
export interface Props {
|
||||
initPhase: DashboardInitPhase;
|
||||
}
|
||||
|
||||
export const DashboardLoading = ({ initPhase }: Props) => {
|
||||
const styles = useStyles(getStyles);
|
||||
const cancelVariables = () => {
|
||||
locationService.push('/');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.dashboardLoading}>
|
||||
<div className={styles.dashboardLoadingText}>
|
||||
<VerticalGroup spacing="md">
|
||||
<HorizontalGroup align="center" justify="center" spacing="xs">
|
||||
<Spinner inline={true} /> {initPhase}
|
||||
</HorizontalGroup>{' '}
|
||||
<HorizontalGroup align="center" justify="center">
|
||||
<Button variant="secondary" size="md" icon="repeat" onClick={cancelVariables}>
|
||||
Cancel loading dashboard
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
</VerticalGroup>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const getStyles = (theme: GrafanaTheme) => {
|
||||
return {
|
||||
dashboardLoading: css`
|
||||
height: 60vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`,
|
||||
dashboardLoadingText: css`
|
||||
font-size: ${theme.typography.size.lg};
|
||||
`,
|
||||
};
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import { DashboardPage, mapStateToProps, Props, State } from './DashboardPage';
|
||||
import { UnthemedDashboardPage, mapStateToProps, Props, State } from './DashboardPage';
|
||||
import { DashboardModel } from '../state';
|
||||
import { mockToolkitActionCreator } from 'test/core/redux/mocks';
|
||||
import { DashboardInitPhase, DashboardRoutes } from 'app/types';
|
||||
@ -8,6 +8,7 @@ import { notifyApp } from 'app/core/actions';
|
||||
import { cleanUpDashboardAndVariables } from '../state/actions';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { getRouteComponentProps } from 'app/core/navigation/__mocks__/routeProps';
|
||||
import { getTheme } from '@grafana/ui';
|
||||
|
||||
jest.mock('app/features/dashboard/components/DashboardSettings/GeneralSettings', () => ({}));
|
||||
|
||||
@ -15,7 +16,7 @@ interface ScenarioContext {
|
||||
cleanUpDashboardAndVariablesMock: typeof cleanUpDashboardAndVariables;
|
||||
dashboard?: DashboardModel | null;
|
||||
setDashboardProp: (overrides?: any, metaOverrides?: any) => void;
|
||||
wrapper?: ShallowWrapper<Props, State, DashboardPage>;
|
||||
wrapper?: ShallowWrapper<Props, State, UnthemedDashboardPage>;
|
||||
mount: (propOverrides?: Partial<Props>) => void;
|
||||
setup: (fn: () => void) => void;
|
||||
}
|
||||
@ -67,12 +68,13 @@ function dashboardPageScenario(description: string, scenarioFn: (ctx: ScenarioCo
|
||||
cancelVariables: jest.fn(),
|
||||
templateVarsChangedInUrl: jest.fn(),
|
||||
dashboard: null,
|
||||
theme: getTheme(),
|
||||
};
|
||||
|
||||
Object.assign(props, propOverrides);
|
||||
|
||||
ctx.dashboard = props.dashboard;
|
||||
ctx.wrapper = shallow(<DashboardPage {...props} />);
|
||||
ctx.wrapper = shallow(<UnthemedDashboardPage {...props} />);
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1,13 +1,13 @@
|
||||
import $ from 'jquery';
|
||||
import React, { MouseEvent, PureComponent } from 'react';
|
||||
import { css } from 'emotion';
|
||||
import { hot } from 'react-hot-loader';
|
||||
import { connect } from 'react-redux';
|
||||
import { getLegacyAngularInjector, locationService } from '@grafana/runtime';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { Alert, Button, CustomScrollbar, HorizontalGroup, Spinner, VerticalGroup } from '@grafana/ui';
|
||||
import { CustomScrollbar, stylesFactory, withTheme, Themeable } from '@grafana/ui';
|
||||
|
||||
import { createErrorNotification } from 'app/core/copy/appNotification';
|
||||
import { getMessageFromError } from 'app/core/utils/errors';
|
||||
import { Branding } from 'app/core/components/Branding/Branding';
|
||||
import { DashboardGrid } from '../dashgrid/DashboardGrid';
|
||||
import { DashNav } from '../components/DashNav';
|
||||
@ -15,7 +15,7 @@ import { DashboardSettings } from '../components/DashboardSettings';
|
||||
import { PanelEditor } from '../components/PanelEditor/PanelEditor';
|
||||
import { initDashboard } from '../state/initDashboard';
|
||||
import { notifyApp } from 'app/core/actions';
|
||||
import { AppNotificationSeverity, DashboardInitError, DashboardInitPhase, KioskMode, StoreState } from 'app/types';
|
||||
import { DashboardInitError, DashboardInitPhase, KioskMode, StoreState } from 'app/types';
|
||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||
import { PanelInspector } from '../components/Inspector/PanelInspector';
|
||||
import { SubMenu } from '../components/SubMenu/SubMenu';
|
||||
@ -26,7 +26,9 @@ import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher';
|
||||
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
||||
import { getTimeSrv } from '../services/TimeSrv';
|
||||
import { getKioskMode } from 'app/core/navigation/kiosk';
|
||||
import { UrlQueryValue } from '@grafana/data';
|
||||
import { GrafanaTheme, UrlQueryValue } from '@grafana/data';
|
||||
import { DashboardLoading } from '../components/DashboardLoading/DashboardLoading';
|
||||
import { DashboardFailed } from '../components/DashboardLoading/DashboardFailed';
|
||||
|
||||
export interface DashboardPageRouteParams {
|
||||
uid?: string;
|
||||
@ -47,7 +49,9 @@ type DashboardPageRouteSearchParams = {
|
||||
refresh?: string;
|
||||
};
|
||||
|
||||
export interface Props extends GrafanaRouteComponentProps<DashboardPageRouteParams, DashboardPageRouteSearchParams> {
|
||||
export interface Props
|
||||
extends Themeable,
|
||||
GrafanaRouteComponentProps<DashboardPageRouteParams, DashboardPageRouteSearchParams> {
|
||||
initPhase: DashboardInitPhase;
|
||||
isInitSlow: boolean;
|
||||
dashboard: DashboardModel | null;
|
||||
@ -69,7 +73,7 @@ export interface State {
|
||||
showLoadingState: boolean;
|
||||
}
|
||||
|
||||
export class DashboardPage extends PureComponent<Props, State> {
|
||||
export class UnthemedDashboardPage extends PureComponent<Props, State> {
|
||||
private forceRouteReloadCounter = 0;
|
||||
state: State = this.getCleanState();
|
||||
|
||||
@ -265,45 +269,6 @@ export class DashboardPage extends PureComponent<Props, State> {
|
||||
this.setState({ updateScrollTop: 0 });
|
||||
};
|
||||
|
||||
cancelVariables = () => {
|
||||
locationService.push('/');
|
||||
};
|
||||
|
||||
renderSlowInitState() {
|
||||
return (
|
||||
<div className="dashboard-loading">
|
||||
<div className="dashboard-loading__text">
|
||||
<VerticalGroup spacing="md">
|
||||
<HorizontalGroup align="center" justify="center" spacing="xs">
|
||||
<Spinner inline={true} /> {this.props.initPhase}
|
||||
</HorizontalGroup>{' '}
|
||||
<HorizontalGroup align="center" justify="center">
|
||||
<Button variant="secondary" size="md" icon="repeat" onClick={this.cancelVariables}>
|
||||
Cancel loading dashboard
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
</VerticalGroup>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
renderInitFailedState() {
|
||||
const { initError } = this.props;
|
||||
|
||||
if (!initError) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="dashboard-loading">
|
||||
<Alert severity={AppNotificationSeverity.Error} title={initError.message}>
|
||||
{getMessageFromError(initError.error)}
|
||||
</Alert>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
getInspectPanel() {
|
||||
const { dashboard, queryParams } = this.props;
|
||||
|
||||
@ -324,12 +289,13 @@ export class DashboardPage extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { dashboard, isInitSlow, initError, isPanelEditorOpen, queryParams } = this.props;
|
||||
const { dashboard, isInitSlow, initError, isPanelEditorOpen, queryParams, theme } = this.props;
|
||||
const { editPanel, viewPanel, scrollTop, updateScrollTop } = this.state;
|
||||
const styles = getStyles(theme);
|
||||
|
||||
if (!dashboard) {
|
||||
if (isInitSlow) {
|
||||
return this.renderSlowInitState();
|
||||
return <DashboardLoading initPhase={this.props.initPhase} />;
|
||||
}
|
||||
|
||||
return null;
|
||||
@ -341,7 +307,7 @@ export class DashboardPage extends PureComponent<Props, State> {
|
||||
const kioskMode = getKioskMode(queryParams.kiosk);
|
||||
|
||||
return (
|
||||
<div className="dashboard-container">
|
||||
<div className={styles.dashboardContainer}>
|
||||
{kioskMode !== KioskMode.Full && (
|
||||
<div aria-label={selectors.pages.Dashboard.DashNav.nav}>
|
||||
<DashNav
|
||||
@ -354,7 +320,7 @@ export class DashboardPage extends PureComponent<Props, State> {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="dashboard-scroll">
|
||||
<div className={styles.dashboardScroll}>
|
||||
<CustomScrollbar
|
||||
autoHeightMin="100%"
|
||||
setScrollTop={this.setScrollTop}
|
||||
@ -362,8 +328,8 @@ export class DashboardPage extends PureComponent<Props, State> {
|
||||
hideHorizontalTrack={true}
|
||||
updateAfterMountMs={500}
|
||||
>
|
||||
<div className="dashboard-content">
|
||||
{initError && this.renderInitFailedState()}
|
||||
<div className={styles.dashboardContent}>
|
||||
{initError && <DashboardFailed />}
|
||||
{!editPanel && kioskMode === KioskMode.Off && (
|
||||
<div aria-label={selectors.pages.Dashboard.SubMenu.submenu}>
|
||||
<SubMenu dashboard={dashboard} annotations={dashboard.annotations.list} links={dashboard.links} />
|
||||
@ -405,4 +371,35 @@ const mapDispatchToProps = {
|
||||
templateVarsChangedInUrl,
|
||||
};
|
||||
|
||||
/*
|
||||
* Styles
|
||||
*/
|
||||
export const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
return {
|
||||
dashboardContainer: css`
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex: 1 1 0;
|
||||
flex-direction: column;
|
||||
`,
|
||||
dashboardScroll: css`
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
`,
|
||||
dashboardContent: css`
|
||||
padding: ${theme.spacing.md};
|
||||
flex-basis: 100%;
|
||||
flex-grow: 1;
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
export const DashboardPage = withTheme(UnthemedDashboardPage);
|
||||
DashboardPage.displayName = 'DashboardPage';
|
||||
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(DashboardPage));
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`] = `
|
||||
<div
|
||||
className="dashboard-container"
|
||||
className="css-1mwktlb"
|
||||
>
|
||||
<div
|
||||
aria-label="Dashboard navigation"
|
||||
@ -108,7 +108,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="dashboard-scroll"
|
||||
className="css-17x4n39"
|
||||
>
|
||||
<CustomScrollbar
|
||||
autoHeightMin="100%"
|
||||
@ -117,7 +117,7 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
||||
updateAfterMountMs={500}
|
||||
>
|
||||
<div
|
||||
className="dashboard-content"
|
||||
className="css-50qyg5"
|
||||
>
|
||||
<div
|
||||
aria-label="Dashboard submenu"
|
||||
@ -339,50 +339,16 @@ exports[`DashboardPage Dashboard init completed Should render dashboard grid 1`
|
||||
`;
|
||||
|
||||
exports[`DashboardPage Dashboard is fetching slowly Should render slow init state 1`] = `
|
||||
<div
|
||||
className="dashboard-loading"
|
||||
>
|
||||
<div
|
||||
className="dashboard-loading__text"
|
||||
>
|
||||
<VerticalGroup
|
||||
spacing="md"
|
||||
>
|
||||
<HorizontalGroup
|
||||
align="center"
|
||||
justify="center"
|
||||
spacing="xs"
|
||||
>
|
||||
<Spinner
|
||||
inline={true}
|
||||
/>
|
||||
|
||||
Fetching
|
||||
</HorizontalGroup>
|
||||
|
||||
<HorizontalGroup
|
||||
align="center"
|
||||
justify="center"
|
||||
>
|
||||
<Button
|
||||
icon="repeat"
|
||||
onClick={[Function]}
|
||||
size="md"
|
||||
variant="secondary"
|
||||
>
|
||||
Cancel loading dashboard
|
||||
</Button>
|
||||
</HorizontalGroup>
|
||||
</VerticalGroup>
|
||||
</div>
|
||||
</div>
|
||||
<DashboardLoading
|
||||
initPhase="Fetching"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`DashboardPage Given initial state Should render nothing 1`] = `""`;
|
||||
|
||||
exports[`DashboardPage When dashboard has editview url state should render settings view 1`] = `
|
||||
<div
|
||||
className="dashboard-container"
|
||||
className="css-1mwktlb"
|
||||
>
|
||||
<div
|
||||
aria-label="Dashboard navigation"
|
||||
@ -488,7 +454,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="dashboard-scroll"
|
||||
className="css-17x4n39"
|
||||
>
|
||||
<CustomScrollbar
|
||||
autoHeightMin="100%"
|
||||
@ -497,7 +463,7 @@ exports[`DashboardPage When dashboard has editview url state should render setti
|
||||
updateAfterMountMs={500}
|
||||
>
|
||||
<div
|
||||
className="dashboard-content"
|
||||
className="css-50qyg5"
|
||||
>
|
||||
<div
|
||||
aria-label="Dashboard submenu"
|
||||
|
@ -1,64 +1,7 @@
|
||||
.dashboard-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex: 1 1 0;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.dashboard-scroll {
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.dashboard-content {
|
||||
padding: $dashboard-padding;
|
||||
flex-basis: 100%;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
div.flot-text {
|
||||
color: $text-color !important;
|
||||
}
|
||||
|
||||
.panel {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.dashboard-solo {
|
||||
.footer,
|
||||
.sidemenu {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.template-variable {
|
||||
color: $variable;
|
||||
}
|
||||
|
||||
.panel-solo {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
||||
.panel-container {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.panel-menu-toggle,
|
||||
.panel-menu {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-height-helper {
|
||||
display: block;
|
||||
height: 100%;
|
||||
@ -109,31 +52,36 @@ div.flot-text {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
.dashboard-header {
|
||||
font-size: $font-size-h2;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
top: -10px;
|
||||
span {
|
||||
display: inline-block;
|
||||
@include brand-bottom-border();
|
||||
padding: $space-sm $space-sm $space-xxs $space-sm;
|
||||
|
||||
div.flot-text {
|
||||
color: $text-color !important;
|
||||
}
|
||||
|
||||
.dashboard-solo {
|
||||
.footer,
|
||||
.sidemenu {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-loading {
|
||||
height: 60vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.template-variable {
|
||||
color: $variable;
|
||||
}
|
||||
|
||||
.alert {
|
||||
max-width: 600px;
|
||||
min-width: 600px;
|
||||
.panel-solo {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
||||
.panel-container {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.panel-menu-toggle,
|
||||
.panel-menu {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-loading__text {
|
||||
font-size: $font-size-lg;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user