New panel editor: Add title editor (#22030)

This commit is contained in:
Dominik Prokop 2020-02-08 19:31:17 +01:00 committed by GitHub
parent c75ca5cf06
commit b8e68efe70
2 changed files with 114 additions and 44 deletions

View File

@ -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>
); );
} }

View File

@ -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>
)}
</>
);
};