mirror of
https://github.com/prometheus/prometheus.git
synced 2025-03-05 20:59:13 -08:00
React UI: Move global /graph settings to navbar
This saves precious space at the top and makes the page look less awkward. Signed-off-by: Julius Volz <julius.volz@gmail.com>
This commit is contained in:
parent
d996ba20ec
commit
c36a781b1c
|
@ -1,4 +1,4 @@
|
||||||
import React, { FC } from 'react';
|
import React, { FC, useState } from 'react';
|
||||||
import Navigation from './Navbar';
|
import Navigation from './Navbar';
|
||||||
import { Container } from 'reactstrap';
|
import { Container } from 'reactstrap';
|
||||||
|
|
||||||
|
@ -8,9 +8,11 @@ import { Alerts, Config, Flags, Rules, Services, Status, Targets, TSDBStatus, Pa
|
||||||
import PathPrefixProps from './types/PathPrefixProps';
|
import PathPrefixProps from './types/PathPrefixProps';
|
||||||
|
|
||||||
const App: FC<PathPrefixProps> = ({ pathPrefix }) => {
|
const App: FC<PathPrefixProps> = ({ pathPrefix }) => {
|
||||||
|
const [extraNavItem, setExtraNavItem] = useState<React.ReactNode>(null);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Navigation pathPrefix={pathPrefix} />
|
<Navigation pathPrefix={pathPrefix} extraNavItem={extraNavItem} />
|
||||||
<Container fluid style={{ paddingTop: 70 }}>
|
<Container fluid style={{ paddingTop: 70 }}>
|
||||||
<Router basepath={`${pathPrefix}/new`}>
|
<Router basepath={`${pathPrefix}/new`}>
|
||||||
<Redirect from="/" to={`${pathPrefix}/new/graph`} />
|
<Redirect from="/" to={`${pathPrefix}/new/graph`} />
|
||||||
|
@ -19,7 +21,7 @@ const App: FC<PathPrefixProps> = ({ pathPrefix }) => {
|
||||||
NOTE: Any route added here needs to also be added to the list of
|
NOTE: Any route added here needs to also be added to the list of
|
||||||
React-handled router paths ("reactRouterPaths") in /web/web.go.
|
React-handled router paths ("reactRouterPaths") in /web/web.go.
|
||||||
*/}
|
*/}
|
||||||
<PanelList path="/graph" pathPrefix={pathPrefix} />
|
<PanelList path="/graph" pathPrefix={pathPrefix} setExtraNavItem={setExtraNavItem} />
|
||||||
<Alerts path="/alerts" pathPrefix={pathPrefix} />
|
<Alerts path="/alerts" pathPrefix={pathPrefix} />
|
||||||
<Config path="/config" pathPrefix={pathPrefix} />
|
<Config path="/config" pathPrefix={pathPrefix} />
|
||||||
<Flags path="/flags" pathPrefix={pathPrefix} />
|
<Flags path="/flags" pathPrefix={pathPrefix} />
|
||||||
|
|
|
@ -14,9 +14,14 @@ import {
|
||||||
} from 'reactstrap';
|
} from 'reactstrap';
|
||||||
import PathPrefixProps from './types/PathPrefixProps';
|
import PathPrefixProps from './types/PathPrefixProps';
|
||||||
|
|
||||||
const Navigation: FC<PathPrefixProps> = ({ pathPrefix }) => {
|
interface NavigationProps {
|
||||||
|
extraNavItem: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Navigation: FC<PathPrefixProps & NavigationProps> = ({ pathPrefix, extraNavItem }) => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const toggle = () => setIsOpen(!isOpen);
|
const toggle = () => setIsOpen(!isOpen);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Navbar className="mb-3" dark color="dark" expand="md" fixed="top">
|
<Navbar className="mb-3" dark color="dark" expand="md" fixed="top">
|
||||||
<NavbarToggler onClick={toggle} />
|
<NavbarToggler onClick={toggle} />
|
||||||
|
@ -70,6 +75,7 @@ const Navigation: FC<PathPrefixProps> = ({ pathPrefix }) => {
|
||||||
<NavLink href={`${pathPrefix}/`}>Classic UI</NavLink>
|
<NavLink href={`${pathPrefix}/`}>Classic UI</NavLink>
|
||||||
</NavItem>
|
</NavItem>
|
||||||
</Nav>
|
</Nav>
|
||||||
|
{extraNavItem}
|
||||||
</Collapse>
|
</Collapse>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
import React, { Component, ChangeEvent } from 'react';
|
import React, { Component, ChangeEvent, CSSProperties } from 'react';
|
||||||
import { RouteComponentProps } from '@reach/router';
|
import { RouteComponentProps } from '@reach/router';
|
||||||
|
|
||||||
import { Alert, Button, Col, Row } from 'reactstrap';
|
import { Alert, Button, Col, Row, DropdownToggle, DropdownMenu, UncontrolledDropdown } from 'reactstrap';
|
||||||
|
|
||||||
import Panel, { PanelOptions, PanelDefaultOptions } from './Panel';
|
import Panel, { PanelOptions, PanelDefaultOptions } from './Panel';
|
||||||
import Checkbox from '../../components/Checkbox';
|
import Checkbox from '../../components/Checkbox';
|
||||||
import PathPrefixProps from '../../types/PathPrefixProps';
|
import PathPrefixProps from '../../types/PathPrefixProps';
|
||||||
import { generateID, decodePanelOptionsFromQueryString, encodePanelOptionsToQueryString } from '../../utils';
|
import { generateID, decodePanelOptionsFromQueryString, encodePanelOptionsToQueryString } from '../../utils';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { faCog } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
export type MetricGroup = { title: string; items: string[] };
|
export type MetricGroup = { title: string; items: string[] };
|
||||||
export type PanelMeta = { key: string; options: PanelOptions; id: string };
|
export type PanelMeta = { key: string; options: PanelOptions; id: string };
|
||||||
|
|
||||||
|
interface PanelListProps {
|
||||||
|
setExtraNavItem: (item: React.ReactNode) => void;
|
||||||
|
}
|
||||||
|
|
||||||
interface PanelListState {
|
interface PanelListState {
|
||||||
panels: PanelMeta[];
|
panels: PanelMeta[];
|
||||||
pastQueries: string[];
|
pastQueries: string[];
|
||||||
|
@ -20,8 +26,8 @@ interface PanelListState {
|
||||||
useLocalTime: boolean;
|
useLocalTime: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PanelList extends Component<RouteComponentProps & PathPrefixProps, PanelListState> {
|
class PanelList extends Component<RouteComponentProps & PathPrefixProps & PanelListProps, PanelListState> {
|
||||||
constructor(props: RouteComponentProps & PathPrefixProps) {
|
constructor(props: RouteComponentProps & PathPrefixProps & PanelListProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -35,6 +41,8 @@ class PanelList extends Component<RouteComponentProps & PathPrefixProps, PanelLi
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
this.props.setExtraNavItem(this.panelSettingsDropdown());
|
||||||
|
|
||||||
!this.state.panels.length && this.addPanel();
|
!this.state.panels.length && this.addPanel();
|
||||||
fetch(`${this.props.pathPrefix}/api/v1/label/__name__/values`, { cache: 'no-store', credentials: 'same-origin' })
|
fetch(`${this.props.pathPrefix}/api/v1/label/__name__/values`, { cache: 'no-store', credentials: 'same-origin' })
|
||||||
.then(resp => {
|
.then(resp => {
|
||||||
|
@ -82,6 +90,10 @@ class PanelList extends Component<RouteComponentProps & PathPrefixProps, PanelLi
|
||||||
this.updatePastQueries();
|
this.updatePastQueries();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.props.setExtraNavItem(null);
|
||||||
|
}
|
||||||
|
|
||||||
isHistoryEnabled = () => JSON.parse(localStorage.getItem('enable-query-history') || 'false') as boolean;
|
isHistoryEnabled = () => JSON.parse(localStorage.getItem('enable-query-history') || 'false') as boolean;
|
||||||
|
|
||||||
getHistoryItems = () => JSON.parse(localStorage.getItem('history') || '[]') as string[];
|
getHistoryItems = () => JSON.parse(localStorage.getItem('history') || '[]') as string[];
|
||||||
|
@ -154,15 +166,18 @@ class PanelList extends Component<RouteComponentProps & PathPrefixProps, PanelLi
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
panelSettingsDropdown() {
|
||||||
const { metricNames, pastQueries, timeDriftError, fetchMetricsError, panels } = this.state;
|
const wrapperStyles: CSSProperties = { margin: '3px 15px', alignSelf: 'center', whiteSpace: 'nowrap' };
|
||||||
const { pathPrefix } = this.props;
|
|
||||||
return (
|
return (
|
||||||
<>
|
<UncontrolledDropdown className="float-right">
|
||||||
<Row className="mb-2">
|
<DropdownToggle>
|
||||||
|
<FontAwesomeIcon icon={faCog} fixedWidth />
|
||||||
|
</DropdownToggle>
|
||||||
|
<DropdownMenu right>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id="query-history-checkbox"
|
id="query-history-checkbox"
|
||||||
wrapperStyles={{ margin: '0 0 0 15px', alignSelf: 'center' }}
|
wrapperStyles={wrapperStyles}
|
||||||
onChange={this.toggleQueryHistory}
|
onChange={this.toggleQueryHistory}
|
||||||
defaultChecked={this.isHistoryEnabled()}
|
defaultChecked={this.isHistoryEnabled()}
|
||||||
>
|
>
|
||||||
|
@ -170,13 +185,22 @@ class PanelList extends Component<RouteComponentProps & PathPrefixProps, PanelLi
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id="use-local-time-checkbox"
|
id="use-local-time-checkbox"
|
||||||
wrapperStyles={{ margin: '0 0 0 15px', alignSelf: 'center' }}
|
wrapperStyles={wrapperStyles}
|
||||||
onChange={this.toggleUseLocalTime}
|
onChange={this.toggleUseLocalTime}
|
||||||
defaultChecked={this.useLocalTime()}
|
defaultChecked={this.useLocalTime()}
|
||||||
>
|
>
|
||||||
Use local time
|
Use local time
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
</Row>
|
</DropdownMenu>
|
||||||
|
</UncontrolledDropdown>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { metricNames, pastQueries, timeDriftError, fetchMetricsError, panels } = this.state;
|
||||||
|
const { pathPrefix } = this.props;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
<Row>
|
<Row>
|
||||||
<Col>
|
<Col>
|
||||||
{timeDriftError && (
|
{timeDriftError && (
|
||||||
|
|
Loading…
Reference in a new issue