mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge remote-tracking branch 'origin/develop-addpanelpanel' into add-panel-rewrite
This commit is contained in:
commit
9d8d5b18ef
@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import classNames from 'classnames';
|
||||
import config from 'app/core/config';
|
||||
import { PanelModel } from '../panel_model';
|
||||
import { DashboardModel } from '../dashboard_model';
|
||||
@ -8,6 +7,8 @@ import ScrollBar from 'app/core/components/ScrollBar/ScrollBar';
|
||||
import store from 'app/core/store';
|
||||
import { LS_PANEL_COPY_KEY } from 'app/core/constants';
|
||||
import Highlighter from 'react-highlight-words';
|
||||
import { updateLocation } from 'app/core/actions';
|
||||
import { store as reduxStore } from 'app/store/store';
|
||||
|
||||
export interface AddPanelPanelProps {
|
||||
panel: PanelModel;
|
||||
@ -27,12 +28,11 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleCloseAddPanel = this.handleCloseAddPanel.bind(this);
|
||||
this.renderPanelItem = this.renderPanelItem.bind(this);
|
||||
this.panelSizeChanged = this.panelSizeChanged.bind(this);
|
||||
|
||||
this.state = {
|
||||
panelPlugins: this.getPanelPlugins(''),
|
||||
copiedPanelPlugins: this.getCopiedPanelPlugins(''),
|
||||
panelPlugins: this.getPanelPlugins(),
|
||||
copiedPanelPlugins: this.getCopiedPanelPlugins(),
|
||||
filter: '',
|
||||
tab: 'Add',
|
||||
};
|
||||
@ -52,27 +52,31 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
|
||||
});
|
||||
}
|
||||
|
||||
getPanelPlugins(filter) {
|
||||
let panels = _.chain(config.panels)
|
||||
getPanelPlugins() {
|
||||
const panelsList = _.chain(config.panels)
|
||||
.filter({ hideFromList: false })
|
||||
.map(item => item)
|
||||
.value();
|
||||
|
||||
const panels = [];
|
||||
|
||||
for (let i = 0; i < panelsList.length; i++) {
|
||||
if (panelsList[i].id === 'graph') {
|
||||
panels.push(panelsList[i]);
|
||||
}
|
||||
}
|
||||
// add special row type
|
||||
panels.push({ id: 'row', name: 'Row', sort: 8, info: { logos: { small: 'public/img/icn-row.svg' } } });
|
||||
|
||||
panels = this.filterPanels(panels, filter);
|
||||
|
||||
// add sort by sort property
|
||||
return _.sortBy(panels, 'sort');
|
||||
return panels;
|
||||
}
|
||||
|
||||
getCopiedPanelPlugins(filter) {
|
||||
getCopiedPanelPlugins() {
|
||||
const panels = _.chain(config.panels)
|
||||
.filter({ hideFromList: false })
|
||||
.map(item => item)
|
||||
.value();
|
||||
let copiedPanels = [];
|
||||
const copiedPanels = [];
|
||||
|
||||
const copiedPanelJson = store.get(LS_PANEL_COPY_KEY);
|
||||
if (copiedPanelJson) {
|
||||
@ -86,40 +90,9 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
|
||||
copiedPanels.push(pluginCopy);
|
||||
}
|
||||
}
|
||||
|
||||
copiedPanels = this.filterPanels(copiedPanels, filter);
|
||||
|
||||
return _.sortBy(copiedPanels, 'sort');
|
||||
}
|
||||
|
||||
onAddPanel = panelPluginInfo => {
|
||||
const dashboard = this.props.dashboard;
|
||||
const { gridPos } = this.props.panel;
|
||||
|
||||
const newPanel: any = {
|
||||
type: panelPluginInfo.id,
|
||||
title: 'Panel Title',
|
||||
gridPos: { x: gridPos.x, y: gridPos.y, w: gridPos.w, h: gridPos.h },
|
||||
};
|
||||
|
||||
if (panelPluginInfo.id === 'row') {
|
||||
newPanel.title = 'Row title';
|
||||
newPanel.gridPos = { x: 0, y: 0 };
|
||||
}
|
||||
|
||||
// apply panel template / defaults
|
||||
if (panelPluginInfo.defaults) {
|
||||
_.defaults(newPanel, panelPluginInfo.defaults);
|
||||
newPanel.gridPos.w = panelPluginInfo.defaults.gridPos.w;
|
||||
newPanel.gridPos.h = panelPluginInfo.defaults.gridPos.h;
|
||||
newPanel.title = panelPluginInfo.defaults.title;
|
||||
store.delete(LS_PANEL_COPY_KEY);
|
||||
}
|
||||
|
||||
dashboard.addPanel(newPanel);
|
||||
dashboard.removePanel(this.props.panel);
|
||||
};
|
||||
|
||||
handleCloseAddPanel(evt) {
|
||||
evt.preventDefault();
|
||||
this.props.dashboard.removePanel(this.props.dashboard.panels[0]);
|
||||
@ -130,82 +103,101 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
|
||||
return <Highlighter highlightClassName="highlight-search-match" textToHighlight={text} searchWords={searchWords} />;
|
||||
}
|
||||
|
||||
renderPanelItem(panel, index) {
|
||||
return (
|
||||
<div key={index} className="add-panel__item" onClick={() => this.onAddPanel(panel)} title={panel.name}>
|
||||
<img className="add-panel__item-img" src={panel.info.logos.small} />
|
||||
<div className="add-panel__item-name">{this.renderText(panel.name)}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
noCopiedPanelPlugins() {
|
||||
return <div className="add-panel__no-panels">No copied panels yet.</div>;
|
||||
}
|
||||
|
||||
filterChange(evt) {
|
||||
this.setState({
|
||||
filter: evt.target.value,
|
||||
panelPlugins: this.getPanelPlugins(evt.target.value),
|
||||
copiedPanelPlugins: this.getCopiedPanelPlugins(evt.target.value),
|
||||
});
|
||||
copyButton(panel) {
|
||||
return (
|
||||
<button className="btn-inverse btn" onClick={() => this.onPasteCopiedPanel(panel)} title={panel.name}>
|
||||
Paste copied Panel
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
filterKeyPress(evt) {
|
||||
if (evt.key === 'Enter') {
|
||||
const panel = _.head(this.state.panelPlugins);
|
||||
if (panel) {
|
||||
this.onAddPanel(panel);
|
||||
}
|
||||
}
|
||||
moveToEdit(panel) {
|
||||
reduxStore.dispatch(
|
||||
updateLocation({
|
||||
query: {
|
||||
panelId: panel.id,
|
||||
edit: true,
|
||||
fullscreen: true,
|
||||
},
|
||||
partial: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
filterPanels(panels, filter) {
|
||||
const regex = new RegExp(filter, 'i');
|
||||
return panels.filter(panel => {
|
||||
return regex.test(panel.name);
|
||||
});
|
||||
onCreateNewPanel = panelPluginInfo => {
|
||||
const dashboard = this.props.dashboard;
|
||||
const { gridPos } = this.props.panel;
|
||||
|
||||
const newPanel: any = {
|
||||
type: panelPluginInfo.id,
|
||||
title: 'Panel Title',
|
||||
gridPos: { x: gridPos.x, y: gridPos.y, w: gridPos.w, h: gridPos.h },
|
||||
};
|
||||
|
||||
// apply panel template / defaults
|
||||
if (panelPluginInfo.defaults) {
|
||||
_.defaults(newPanel, panelPluginInfo.defaults);
|
||||
newPanel.gridPos.w = panelPluginInfo.defaults.gridPos.w;
|
||||
newPanel.gridPos.h = panelPluginInfo.defaults.gridPos.h;
|
||||
newPanel.title = panelPluginInfo.defaults.title;
|
||||
store.delete(LS_PANEL_COPY_KEY);
|
||||
}
|
||||
|
||||
openCopy() {
|
||||
this.setState({
|
||||
tab: 'Copy',
|
||||
filter: '',
|
||||
panelPlugins: this.getPanelPlugins(''),
|
||||
copiedPanelPlugins: this.getCopiedPanelPlugins(''),
|
||||
});
|
||||
dashboard.addPanel(newPanel);
|
||||
this.moveToEdit(newPanel);
|
||||
|
||||
dashboard.removePanel(this.props.panel);
|
||||
};
|
||||
|
||||
onPasteCopiedPanel = panelPluginInfo => {
|
||||
const dashboard = this.props.dashboard;
|
||||
const { gridPos } = this.props.panel;
|
||||
|
||||
const newPanel: any = {
|
||||
type: panelPluginInfo.id,
|
||||
title: 'Panel Title',
|
||||
gridPos: { x: gridPos.x, y: gridPos.y, w: gridPos.w, h: gridPos.h },
|
||||
};
|
||||
|
||||
// apply panel template / defaults
|
||||
if (panelPluginInfo.defaults) {
|
||||
_.defaults(newPanel, panelPluginInfo.defaults);
|
||||
newPanel.gridPos.w = panelPluginInfo.defaults.gridPos.w;
|
||||
newPanel.gridPos.h = panelPluginInfo.defaults.gridPos.h;
|
||||
newPanel.title = panelPluginInfo.defaults.title;
|
||||
store.delete(LS_PANEL_COPY_KEY);
|
||||
}
|
||||
|
||||
openAdd() {
|
||||
this.setState({
|
||||
tab: 'Add',
|
||||
filter: '',
|
||||
panelPlugins: this.getPanelPlugins(''),
|
||||
copiedPanelPlugins: this.getCopiedPanelPlugins(''),
|
||||
});
|
||||
}
|
||||
dashboard.addPanel(newPanel);
|
||||
|
||||
dashboard.removePanel(this.props.panel);
|
||||
};
|
||||
|
||||
onCreateNewRow = panelPluginInfo => {
|
||||
const dashboard = this.props.dashboard;
|
||||
|
||||
const newRow: any = {
|
||||
type: panelPluginInfo.id,
|
||||
title: 'Row title',
|
||||
gridPos: { x: 0, y: 0 },
|
||||
};
|
||||
|
||||
dashboard.addPanel(newRow);
|
||||
dashboard.removePanel(this.props.panel);
|
||||
};
|
||||
|
||||
render() {
|
||||
const addClass = classNames({
|
||||
'active active--panel': this.state.tab === 'Add',
|
||||
'': this.state.tab === 'Copy',
|
||||
});
|
||||
const panel = this.state.panelPlugins[0];
|
||||
const row = this.state.panelPlugins[1];
|
||||
|
||||
const copyClass = classNames({
|
||||
'': this.state.tab === 'Add',
|
||||
'active active--panel': this.state.tab === 'Copy',
|
||||
});
|
||||
let addCopyButton;
|
||||
|
||||
let panelTab;
|
||||
|
||||
if (this.state.tab === 'Add') {
|
||||
panelTab = this.state.panelPlugins.map(this.renderPanelItem);
|
||||
} else if (this.state.tab === 'Copy') {
|
||||
if (this.state.copiedPanelPlugins.length > 0) {
|
||||
panelTab = this.state.copiedPanelPlugins.map(this.renderPanelItem);
|
||||
} else {
|
||||
panelTab = this.noCopiedPanelPlugins();
|
||||
}
|
||||
if (this.state.copiedPanelPlugins.length === 1) {
|
||||
addCopyButton = this.copyButton(this.state.copiedPanelPlugins[0]);
|
||||
}
|
||||
|
||||
return (
|
||||
@ -213,40 +205,21 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
|
||||
<div className="add-panel">
|
||||
<div className="add-panel__header">
|
||||
<i className="gicon gicon-add-panel" />
|
||||
<span className="add-panel__title">New Panel</span>
|
||||
<ul className="gf-tabs">
|
||||
<li className="gf-tabs-item">
|
||||
<div className={'gf-tabs-link pointer ' + addClass} onClick={this.openAdd.bind(this)}>
|
||||
Add
|
||||
</div>
|
||||
</li>
|
||||
<li className="gf-tabs-item">
|
||||
<div className={'gf-tabs-link pointer ' + copyClass} onClick={this.openCopy.bind(this)}>
|
||||
Paste
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<button className="add-panel__close" onClick={this.handleCloseAddPanel}>
|
||||
<i className="fa fa-close" />
|
||||
</button>
|
||||
</div>
|
||||
<ScrollBar ref={element => (this.scrollbar = element)} className="add-panel__items">
|
||||
<div className="add-panel__searchbar">
|
||||
<label className="gf-form gf-form--grow gf-form--has-input-icon">
|
||||
<input
|
||||
type="text"
|
||||
autoFocus
|
||||
className="gf-form-input gf-form--grow"
|
||||
placeholder="Panel Search Filter"
|
||||
value={this.state.filter}
|
||||
onChange={this.filterChange.bind(this)}
|
||||
onKeyPress={this.filterKeyPress.bind(this)}
|
||||
/>
|
||||
<i className="gf-form-input-icon fa fa-search" />
|
||||
</label>
|
||||
<div className="add-panel-btn-container">
|
||||
<div className="gf-form-button-row">
|
||||
<button className="btn-success btn" onClick={() => this.onCreateNewPanel(panel)} title={panel.name}>
|
||||
Create new Panel
|
||||
</button>
|
||||
{addCopyButton}
|
||||
<button className="btn-inverse btn" onClick={() => this.onCreateNewRow(row)} title={row.name}>
|
||||
Add new Row
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{panelTab}
|
||||
</ScrollBar>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -32,11 +32,6 @@ describe('AddPanelPanel', () => {
|
||||
wrapper = shallow(<AddPanelPanel panel={panel} dashboard={dashboardMock} />);
|
||||
});
|
||||
|
||||
it('should fetch all panels sorted with core plugins first', () => {
|
||||
expect(wrapper.find('.add-panel__item').get(1).props.title).toBe('singlestat');
|
||||
expect(wrapper.find('.add-panel__item').get(4).props.title).toBe('piechart');
|
||||
});
|
||||
|
||||
it('should filter', () => {
|
||||
wrapper.find('input').simulate('change', { target: { value: 'p' } });
|
||||
|
||||
|
@ -4,20 +4,17 @@
|
||||
|
||||
.add-panel {
|
||||
height: 100%;
|
||||
|
||||
.baron__root {
|
||||
height: calc(100% - 43px);
|
||||
}
|
||||
//display: flex;
|
||||
//flex-direction: column;
|
||||
}
|
||||
|
||||
.add-panel__header {
|
||||
top: 0;
|
||||
position: absolute;
|
||||
padding: 0 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: $page-header-bg;
|
||||
box-shadow: $page-header-shadow;
|
||||
border-bottom: 1px solid $page-header-border-color;
|
||||
|
||||
width: 100%;
|
||||
.gicon {
|
||||
font-size: 30px;
|
||||
margin-right: $spacer;
|
||||
@ -32,18 +29,6 @@
|
||||
margin-right: -10px;
|
||||
}
|
||||
|
||||
.add-panel__title {
|
||||
font-size: $font-size-md;
|
||||
margin-right: $spacer*2;
|
||||
}
|
||||
|
||||
.add-panel__sub-title {
|
||||
font-style: italic;
|
||||
color: $text-muted;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
.add-panel__items {
|
||||
padding: 3px 8px;
|
||||
display: flex;
|
||||
@ -97,3 +82,10 @@
|
||||
width: 100%;
|
||||
padding: 3px 8px;
|
||||
}
|
||||
|
||||
.add-panel-btn-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user