mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
New panel editor: Add title editor (#22030)
This commit is contained in:
parent
c75ca5cf06
commit
b8e68efe70
@ -1,6 +1,6 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { GrafanaTheme, FieldConfigSource, PanelData, LoadingState, DefaultTimeRange, PanelEvents } from '@grafana/data';
|
import { GrafanaTheme, FieldConfigSource, PanelData, LoadingState, DefaultTimeRange, PanelEvents } from '@grafana/data';
|
||||||
import { stylesFactory, Forms, FieldConfigEditor, CustomScrollbar } from '@grafana/ui';
|
import { stylesFactory, Forms, FieldConfigEditor, CustomScrollbar, selectThemeVariant } from '@grafana/ui';
|
||||||
import { css, cx } from 'emotion';
|
import { css, cx } from 'emotion';
|
||||||
import config from 'app/core/config';
|
import config from 'app/core/config';
|
||||||
|
|
||||||
@ -13,14 +13,23 @@ import { StoreState } from '../../../../types/store';
|
|||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { updateLocation } from '../../../../core/reducers/location';
|
import { updateLocation } from '../../../../core/reducers/location';
|
||||||
import { Unsubscribable } from 'rxjs';
|
import { Unsubscribable } from 'rxjs';
|
||||||
|
import { PanelTitle } from './PanelTitle';
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||||
|
const handleColor = selectThemeVariant(
|
||||||
|
{
|
||||||
|
dark: theme.colors.dark9,
|
||||||
|
light: theme.colors.gray6,
|
||||||
|
},
|
||||||
|
theme.type
|
||||||
|
);
|
||||||
|
|
||||||
const resizer = css`
|
const resizer = css`
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
background: ${theme.colors.panelBg};
|
background: ${theme.colors.panelBg};
|
||||||
&:hover {
|
&:hover {
|
||||||
background: ${theme.colors.headingColor};
|
background: ${handleColor};
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -54,8 +63,23 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
|||||||
),
|
),
|
||||||
noScrollPaneContent: css`
|
noScrollPaneContent: css`
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
`,
|
`,
|
||||||
|
toolbar: css`
|
||||||
|
padding: ${theme.spacing.sm};
|
||||||
|
height: 48px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
`,
|
||||||
|
panes: css`
|
||||||
|
height: calc(100% - 48px);
|
||||||
|
position: relative;
|
||||||
|
`,
|
||||||
|
toolbarLeft: css`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
`,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -204,6 +228,11 @@ export class PanelEditor extends PureComponent<Props, State> {
|
|||||||
console.log('TODO, save splitter settings');
|
console.log('TODO, save splitter settings');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onPanelTitleChange = (title: string) => {
|
||||||
|
this.state.panel.title = title;
|
||||||
|
this.forceUpdate();
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { dashboard } = this.props;
|
const { dashboard } = this.props;
|
||||||
const { panel } = this.state;
|
const { panel } = this.state;
|
||||||
@ -215,56 +244,62 @@ export class PanelEditor extends PureComponent<Props, State> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.wrapper}>
|
<div className={styles.wrapper}>
|
||||||
<div>
|
<div className={styles.toolbar}>
|
||||||
<button className="navbar-edit__back-btn" onClick={this.onPanelExit}>
|
<div className={styles.toolbarLeft}>
|
||||||
<i className="fa fa-arrow-left"></i>
|
<button className="navbar-edit__back-btn" onClick={this.onPanelExit}>
|
||||||
</button>
|
<i className="fa fa-arrow-left"></i>
|
||||||
{panel.title}
|
</button>
|
||||||
<Forms.Button variant="destructive" onClick={this.onDiscard}>
|
<PanelTitle value={panel.title} onChange={this.onPanelTitleChange} />
|
||||||
Discard
|
</div>
|
||||||
</Forms.Button>
|
<div>
|
||||||
|
<Forms.Button variant="destructive" onClick={this.onDiscard}>
|
||||||
|
Discard
|
||||||
|
</Forms.Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<SplitPane
|
<div className={styles.panes}>
|
||||||
split="vertical"
|
|
||||||
primary="second"
|
|
||||||
minSize={50}
|
|
||||||
defaultSize={350}
|
|
||||||
resizerClassName={styles.resizerV}
|
|
||||||
onDragStarted={() => (document.body.style.cursor = 'col-resize')}
|
|
||||||
onDragFinished={this.onDragFinished}
|
|
||||||
>
|
|
||||||
<SplitPane
|
<SplitPane
|
||||||
split="horizontal"
|
split="vertical"
|
||||||
minSize={50}
|
|
||||||
primary="second"
|
primary="second"
|
||||||
defaultSize="40%"
|
minSize={50}
|
||||||
resizerClassName={styles.resizerH}
|
defaultSize={350}
|
||||||
onDragStarted={() => (document.body.style.cursor = 'row-resize')}
|
resizerClassName={styles.resizerV}
|
||||||
|
onDragStarted={() => (document.body.style.cursor = 'col-resize')}
|
||||||
onDragFinished={this.onDragFinished}
|
onDragFinished={this.onDragFinished}
|
||||||
>
|
>
|
||||||
<div className={styles.fill}>
|
<SplitPane
|
||||||
<DashboardPanel
|
split="horizontal"
|
||||||
dashboard={dashboard}
|
minSize={50}
|
||||||
panel={panel}
|
primary="second"
|
||||||
isEditing={false}
|
defaultSize="40%"
|
||||||
isInEditMode
|
resizerClassName={styles.resizerH}
|
||||||
isFullscreen={false}
|
onDragStarted={() => (document.body.style.cursor = 'row-resize')}
|
||||||
isInView={true}
|
onDragFinished={this.onDragFinished}
|
||||||
/>
|
>
|
||||||
</div>
|
<div className={styles.fill}>
|
||||||
|
<DashboardPanel
|
||||||
|
dashboard={dashboard}
|
||||||
|
panel={panel}
|
||||||
|
isEditing={false}
|
||||||
|
isInEditMode
|
||||||
|
isFullscreen={false}
|
||||||
|
isInView={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={styles.noScrollPaneContent}>
|
||||||
|
<QueriesTab panel={panel} dashboard={dashboard} />
|
||||||
|
</div>
|
||||||
|
</SplitPane>
|
||||||
<div className={styles.noScrollPaneContent}>
|
<div className={styles.noScrollPaneContent}>
|
||||||
<QueriesTab panel={panel} dashboard={dashboard} />
|
<CustomScrollbar>
|
||||||
|
<div style={{ padding: '10px' }}>
|
||||||
|
{this.renderFieldOptions()}
|
||||||
|
{this.renderVisSettings()}
|
||||||
|
</div>
|
||||||
|
</CustomScrollbar>
|
||||||
</div>
|
</div>
|
||||||
</SplitPane>
|
</SplitPane>
|
||||||
<div className={styles.noScrollPaneContent}>
|
</div>
|
||||||
<CustomScrollbar>
|
|
||||||
<div style={{ padding: '10px' }}>
|
|
||||||
{this.renderFieldOptions()}
|
|
||||||
{this.renderVisSettings()}
|
|
||||||
</div>
|
|
||||||
</CustomScrollbar>
|
|
||||||
</div>
|
|
||||||
</SplitPane>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { css } from 'emotion';
|
||||||
|
import { Forms, useTheme } from '@grafana/ui';
|
||||||
|
|
||||||
|
interface PanelTitleProps {
|
||||||
|
value: string;
|
||||||
|
onChange: (value: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PanelTitle: React.FC<PanelTitleProps> = ({ value, onChange }) => {
|
||||||
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
|
const theme = useTheme();
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{isEditing ? (
|
||||||
|
<Forms.Input
|
||||||
|
value={value || ''}
|
||||||
|
onChange={e => onChange(e.currentTarget.value)}
|
||||||
|
onBlur={() => setIsEditing(false)}
|
||||||
|
placeholder="Panel Title"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<span
|
||||||
|
className={css`
|
||||||
|
font-size: ${theme.typography.size.lg};
|
||||||
|
margin-left: ${theme.spacing.sm};
|
||||||
|
`}
|
||||||
|
onClick={() => setIsEditing(true)}
|
||||||
|
>
|
||||||
|
{value}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user