react panel minor progress

This commit is contained in:
Torkel Ödegaard 2018-06-19 14:51:57 +02:00
parent 35403c1875
commit aa5c9f199a
6 changed files with 200 additions and 136 deletions

View File

@ -175,11 +175,10 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
const panelElements = [];
for (let panel of this.dashboard.panels) {
console.log('panel.fullscreen', panel.fullscreen);
const panelClasses = classNames({ panel: true, 'panel--fullscreen': panel.fullscreen });
panelElements.push(
<div key={panel.id.toString()} className={panelClasses}>
<DashboardPanel panel={panel} dashboard={this.dashboard} />
<DashboardPanel panel={panel} dashboard={this.dashboard} panelContainer={this.panelContainer} />
</div>
);
}

View File

@ -1,22 +1,18 @@
import React from 'react';
import $ from 'jquery';
import config from 'app/core/config';
import classNames from 'classnames';
import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model';
import { AttachedPanel } from './PanelLoader';
import { DashboardRow } from './DashboardRow';
import { PanelContainer } from './PanelContainer';
import { AddPanelPanel } from './AddPanelPanel';
import { importPluginModule } from 'app/features/plugins/plugin_loader';
import { store } from 'app/stores/store';
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN } from 'app/core/constants';
const TITLE_HEIGHT = 27;
const PANEL_BORDER = 2;
import { PanelChrome } from './PanelChrome';
export interface DashboardPanelProps {
panel: PanelModel;
dashboard: DashboardModel;
panelContainer: PanelContainer;
}
export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
@ -56,140 +52,44 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
return <AddPanelPanel panel={this.props.panel} dashboard={this.props.dashboard} />;
}
componentDidUpdate() {
// skip loading angular component if we have no element
// or we have already loaded it
if (!this.element || this.attachedPanel) {
return;
}
const loader = this.props.panelContainer.getPanelLoader();
this.attachedPanel = loader.load(this.element, this.props.panel, this.props.dashboard);
}
componentWillUnmount() {
if (this.attachedPanel) {
this.attachedPanel.destroy();
}
}
render() {
if (this.isSpecial()) {
return this.specialPanels[this.props.panel.type]();
}
let PanelComponent = null;
if (this.pluginExports && this.pluginExports.PanelComponent) {
PanelComponent = this.pluginExports.PanelComponent;
if (!this.pluginExports) {
console.log('render null');
return null;
}
let panelContentStyle = {
height: this.getPanelHeight(),
};
return (
<div>
<div className="panel-container">
<PanelHeader panel={this.props.panel} dashboard={this.props.dashboard} />
<div className="panel-content" style={panelContentStyle}>
{PanelComponent && <PanelComponent />}
</div>
</div>
<div>
{this.props.panel.isEditing && <PanelEditor panel={this.props.panel} dashboard={this.props.dashboard} />}
</div>
</div>
);
}
getPanelHeight() {
const panel = this.props.panel;
let height = 0;
if (panel.fullscreen) {
var docHeight = $(window).height();
var editHeight = Math.floor(docHeight * 0.4);
var fullscreenHeight = Math.floor(docHeight * 0.8);
height = panel.isEditing ? editHeight : fullscreenHeight;
} else {
height = panel.gridPos.h * GRID_CELL_HEIGHT + (panel.gridPos.h - 1) * GRID_CELL_VMARGIN;
if (this.pluginExports.PanelComponent) {
return (
<PanelChrome
component={this.pluginExports.PanelComponent}
panel={this.props.panel}
dashboard={this.props.dashboard}
/>
);
}
return height - PANEL_BORDER + TITLE_HEIGHT;
}
}
interface PanelHeaderProps {
panel: PanelModel;
dashboard: DashboardModel;
}
export class PanelHeader extends React.Component<PanelHeaderProps, any> {
onEditPanel = () => {
store.view.updateQuery({
panelId: this.props.panel.id,
edit: true,
fullscreen: true,
});
};
render() {
let isFullscreen = false;
let isLoading = false;
let panelHeaderClass = classNames({ 'panel-header': true, 'grid-drag-handle': !isFullscreen });
return (
<div className={panelHeaderClass}>
<span className="panel-info-corner">
<i className="fa" />
<span className="panel-info-corner-inner" />
</span>
{isLoading && (
<span className="panel-loading">
<i className="fa fa-spinner fa-spin" />
</span>
)}
<div className="panel-title-container">
<span className="panel-title">
<span className="icon-gf panel-alert-icon" />
<span className="panel-title-text">{this.props.panel.title}</span>
<span className="panel-menu-container dropdown">
<span className="fa fa-caret-down panel-menu-toggle" data-toggle="dropdown" />
<ul className="dropdown-menu dropdown-menu--menu panel-menu" role="menu">
<li>
<a onClick={this.onEditPanel}>
<i className="fa fa-fw fa-edit" /> Edit
</a>
</li>
<li>
<a href="asd">asd</a>
</li>
</ul>
</span>
<span className="panel-time-info">
<i className="fa fa-clock-o" /> 4m
</span>
</span>
</div>
</div>
);
}
}
interface PanelEditorProps {
panel: PanelModel;
dashboard: DashboardModel;
}
export class PanelEditor extends React.Component<PanelEditorProps, any> {
render() {
return (
<div className="tabbed-view tabbed-view--panel-edit">
<div className="tabbed-view-header">
<h3 className="tabbed-view-panel-title">{this.props.panel.type}</h3>
<ul className="gf-tabs">
<li className="gf-tabs-item">
<a className="gf-tabs-link active">Queries</a>
</li>
<li className="gf-tabs-item">
<a className="gf-tabs-link">Visualization</a>
</li>
</ul>
<button className="tabbed-view-close-btn" ng-click="ctrl.exitFullscreen();">
<i className="fa fa-remove" />
</button>
</div>
<div className="tabbed-view-body">testing</div>
</div>
);
// legacy angular rendering
return <div ref={element => (this.element = element)} className="panel-height-helper" />;
}
}

View File

@ -0,0 +1,66 @@
import React from 'react';
import $ from 'jquery';
import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model';
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN } from 'app/core/constants';
import { PanelHeader } from './PanelHeader';
import { PanelEditor } from './PanelEditor';
const TITLE_HEIGHT = 27;
const PANEL_BORDER = 2;
export interface PanelChromeProps {
panel: PanelModel;
dashboard: DashboardModel;
component: any;
}
export class PanelChrome extends React.Component<PanelChromeProps, any> {
constructor(props) {
super(props);
this.props.panel.events.on('panel-size-changed', this.triggerForceUpdate.bind(this));
}
triggerForceUpdate() {
this.forceUpdate();
}
render() {
let panelContentStyle = {
height: this.getPanelHeight(),
};
let PanelComponent = this.props.component;
return (
<div className="panel-height-helper">
<div className="panel-container">
<PanelHeader panel={this.props.panel} dashboard={this.props.dashboard} />
<div className="panel-content" style={panelContentStyle}>
{<PanelComponent />}
</div>
</div>
<div>
{this.props.panel.isEditing && <PanelEditor panel={this.props.panel} dashboard={this.props.dashboard} />}
</div>
</div>
);
}
getPanelHeight() {
const panel = this.props.panel;
let height = 0;
if (panel.fullscreen) {
var docHeight = $(window).height();
var editHeight = Math.floor(docHeight * 0.4);
var fullscreenHeight = Math.floor(docHeight * 0.8);
height = panel.isEditing ? editHeight : fullscreenHeight;
} else {
height = panel.gridPos.h * GRID_CELL_HEIGHT + (panel.gridPos.h - 1) * GRID_CELL_VMARGIN;
}
return height - PANEL_BORDER + TITLE_HEIGHT;
}
}

View File

@ -0,0 +1,35 @@
import React from 'react';
import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model';
interface PanelEditorProps {
panel: PanelModel;
dashboard: DashboardModel;
}
export class PanelEditor extends React.Component<PanelEditorProps, any> {
render() {
return (
<div className="tabbed-view tabbed-view--panel-edit">
<div className="tabbed-view-header">
<h3 className="tabbed-view-panel-title">{this.props.panel.type}</h3>
<ul className="gf-tabs">
<li className="gf-tabs-item">
<a className="gf-tabs-link active">Queries</a>
</li>
<li className="gf-tabs-item">
<a className="gf-tabs-link">Visualization</a>
</li>
</ul>
<button className="tabbed-view-close-btn" ng-click="ctrl.exitFullscreen();">
<i className="fa fa-remove" />
</button>
</div>
<div className="tabbed-view-body">testing</div>
</div>
);
}
}

View File

@ -0,0 +1,64 @@
import React from 'react';
import classNames from 'classnames';
import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model';
import { store } from 'app/stores/store';
interface PanelHeaderProps {
panel: PanelModel;
dashboard: DashboardModel;
}
export class PanelHeader extends React.Component<PanelHeaderProps, any> {
onEditPanel = () => {
store.view.updateQuery({
panelId: this.props.panel.id,
edit: true,
fullscreen: true,
});
};
render() {
let isFullscreen = false;
let isLoading = false;
let panelHeaderClass = classNames({ 'panel-header': true, 'grid-drag-handle': !isFullscreen });
return (
<div className={panelHeaderClass}>
<span className="panel-info-corner">
<i className="fa" />
<span className="panel-info-corner-inner" />
</span>
{isLoading && (
<span className="panel-loading">
<i className="fa fa-spinner fa-spin" />
</span>
)}
<div className="panel-title-container">
<span className="panel-title">
<span className="icon-gf panel-alert-icon" />
<span className="panel-title-text">{this.props.panel.title}</span>
<span className="panel-menu-container dropdown">
<span className="fa fa-caret-down panel-menu-toggle" data-toggle="dropdown" />
<ul className="dropdown-menu dropdown-menu--menu panel-menu" role="menu">
<li>
<a onClick={this.onEditPanel}>
<i className="fa fa-fw fa-edit" /> Edit
</a>
</li>
<li>
<a href="asd">asd</a>
</li>
</ul>
</span>
<span className="panel-time-info">
<i className="fa fa-clock-o" /> 4m
</span>
</span>
</div>
</div>
);
}
}

View File

@ -14,7 +14,7 @@ jest.mock('app/core/store', () => ({
}));
describe('AddPanelPanel', () => {
let wrapper, dashboardMock, getPanelContainer, panel;
let wrapper, dashboardMock, panel;
beforeEach(() => {
config.panels = [