Merge remote-tracking branch 'origin/develop-addpanelpanel' into add-panel-rewrite

This commit is contained in:
Torkel Ödegaard 2018-12-14 17:04:33 +01:00
commit 9d8d5b18ef
3 changed files with 119 additions and 159 deletions

View File

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

View File

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

View File

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