Commit 1a7b8a39 by Johannes Schill

Merge branch 'panel-edit-in-react' of https://github.com/grafana/grafana into panel-edit-in-react

parents 69e5584d 874ff4a7
import _ from 'lodash'; import _ from 'lodash';
import coreModule from 'app/core/core_module';
import { ThresholdMapper } from './state/ThresholdMapper'; import { ThresholdMapper } from './state/ThresholdMapper';
import { QueryPart } from 'app/core/components/query_part/query_part'; import { QueryPart } from 'app/core/components/query_part/query_part';
import alertDef from './state/alertDef'; import alertDef from './state/alertDef';
...@@ -430,3 +431,5 @@ export function alertTab() { ...@@ -430,3 +431,5 @@ export function alertTab() {
controller: AlertTabCtrl, controller: AlertTabCtrl,
}; };
} }
coreModule.directive('alertTab', alertTab);
import React, { PureComponent } from 'react';
import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
import { EditorTabBody } from './EditorTabBody';
import 'app/features/alerting/AlertTabCtrl';
interface Props {
angularPanel?: AngularComponent;
}
export class AlertTab extends PureComponent<Props> {
element: any;
component: AngularComponent;
constructor(props) {
super(props);
}
componentDidMount() {
if (this.shouldLoadAlertTab()) {
this.loadAlertTab();
}
}
componentDidUpdate(prevProps: Props) {
if (this.shouldLoadAlertTab()) {
this.loadAlertTab();
}
}
shouldLoadAlertTab() {
return this.props.angularPanel && this.element;
}
componentWillUnmount() {
if (this.component) {
this.component.destroy();
}
}
loadAlertTab() {
const { angularPanel } = this.props;
const scope = angularPanel.getScope();
// When full page reloading in edit mode the angular panel has on fully compiled & instantiated yet
if (!scope.$$childHead) {
setTimeout(() => {
this.forceUpdate();
});
return;
}
const panelCtrl = scope.$$childHead.ctrl;
const loader = getAngularLoader();
const template = '<alert-tab />';
const scopeProps = {
ctrl: panelCtrl,
};
this.component = loader.load(this.element, scopeProps, template);
}
render() {
return (
<EditorTabBody toolbarItems={[]}>
<div ref={element => (this.element = element)} />
</EditorTabBody>
);
}
}
...@@ -176,10 +176,9 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> { ...@@ -176,10 +176,9 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
renderPanels() { renderPanels() {
const panelElements = []; const panelElements = [];
console.log('render panels');
for (const panel of this.props.dashboard.panels) { for (const panel of this.props.dashboard.panels) {
const panelClasses = classNames({ panel: true, 'panel--fullscreen': panel.fullscreen }); const panelClasses = classNames({ 'react-grid-item--fullscreen': panel.fullscreen });
panelElements.push( panelElements.push(
<div key={panel.id.toString()} className={panelClasses} id={`panel-${panel.id}`}> <div key={panel.id.toString()} className={panelClasses} id={`panel-${panel.id}`}>
<DashboardPanel <DashboardPanel
......
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import config from 'app/core/config'; import config from 'app/core/config';
import classNames from 'classnames';
import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader'; import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader';
import { importPluginModule } from 'app/features/plugins/plugin_loader'; import { importPluginModule } from 'app/features/plugins/plugin_loader';
...@@ -136,7 +137,7 @@ export class DashboardPanel extends PureComponent<Props, State> { ...@@ -136,7 +137,7 @@ export class DashboardPanel extends PureComponent<Props, State> {
} }
render() { render() {
const { panel, dashboard } = this.props; const { panel, dashboard, isFullscreen, isEditing } = this.props;
const { plugin, angularPanel } = this.state; const { plugin, angularPanel } = this.state;
if (this.isSpecial()) { if (this.isSpecial()) {
...@@ -148,8 +149,12 @@ export class DashboardPanel extends PureComponent<Props, State> { ...@@ -148,8 +149,12 @@ export class DashboardPanel extends PureComponent<Props, State> {
return null; return null;
} }
const containerClass = this.props.isEditing ? 'panel-editor-container' : 'panel-height-helper'; const containerClass = classNames({ 'panel-editor-container': isEditing, 'panel-height-helper': !isEditing });
const panelWrapperClass = this.props.isEditing ? 'panel-editor-container__panel' : 'panel-height-helper'; const panelWrapperClass = classNames({
'panel-wrapper': true,
'panel-wrapper--edit': isEditing,
'panel-wrapper--view': isFullscreen && !isEditing,
});
return ( return (
<div className={containerClass}> <div className={containerClass}>
......
...@@ -51,7 +51,7 @@ export class GeneralTab extends PureComponent<Props> { ...@@ -51,7 +51,7 @@ export class GeneralTab extends PureComponent<Props> {
return ( return (
<EditorTabBody main={currentDataSource} toolbarItems={[]}> <EditorTabBody main={currentDataSource} toolbarItems={[]}>
<div ref={element => (this.element = element)} style={{ width: '100%' }} /> <div ref={element => (this.element = element)} />
</EditorTabBody> </EditorTabBody>
); );
} }
......
...@@ -4,7 +4,9 @@ import classNames from 'classnames'; ...@@ -4,7 +4,9 @@ import classNames from 'classnames';
import { QueriesTab } from './QueriesTab'; import { QueriesTab } from './QueriesTab';
import { VisualizationTab } from './VisualizationTab'; import { VisualizationTab } from './VisualizationTab';
import { GeneralTab } from './GeneralTab'; import { GeneralTab } from './GeneralTab';
import { AlertTab } from './AlertTab';
import config from 'app/core/config';
import { store } from 'app/store/store'; import { store } from 'app/store/store';
import { updateLocation } from 'app/core/actions'; import { updateLocation } from 'app/core/actions';
import { AngularComponent } from 'app/core/services/AngularLoader'; import { AngularComponent } from 'app/core/services/AngularLoader';
...@@ -28,16 +30,8 @@ interface PanelEditorTab { ...@@ -28,16 +30,8 @@ interface PanelEditorTab {
} }
export class PanelEditor extends PureComponent<PanelEditorProps> { export class PanelEditor extends PureComponent<PanelEditorProps> {
tabs: PanelEditorTab[];
constructor(props) { constructor(props) {
super(props); super(props);
this.tabs = [
{ id: 'general', text: 'General', icon: 'gicon gicon-preferences' },
{ id: 'queries', text: 'Queries', icon: 'fa fa-database' },
{ id: 'visualization', text: 'Visualization', icon: 'fa fa-line-chart' },
];
} }
onChangeTab = (tab: PanelEditorTab) => { onChangeTab = (tab: PanelEditorTab) => {
...@@ -50,19 +44,48 @@ export class PanelEditor extends PureComponent<PanelEditorProps> { ...@@ -50,19 +44,48 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
this.forceUpdate(); this.forceUpdate();
}; };
onClose = () => { renderCurrentTab(activeTab: string) {
store.dispatch( const { panel, dashboard, onTypeChanged, plugin, angularPanel } = this.props;
updateLocation({
query: { tab: null, fullscreen: null, edit: null }, switch (activeTab) {
partial: true, case 'general':
}) return <GeneralTab panel={panel} />;
case 'queries':
return <QueriesTab panel={panel} dashboard={dashboard} />;
case 'alert':
return <AlertTab angularPanel={angularPanel} />;
case 'visualization':
return (
<VisualizationTab
panel={panel}
dashboard={dashboard}
plugin={plugin}
onTypeChanged={onTypeChanged}
angularPanel={angularPanel}
/>
); );
}; default:
return null;
}
}
render() { render() {
const { panel, dashboard, onTypeChanged, plugin, angularPanel } = this.props; const { plugin } = this.props;
const { location } = store.getState(); const activeTab = store.getState().location.query.tab || 'queries';
const activeTab = location.query.tab || 'queries';
const tabs = [
{ id: 'general', text: 'General', icon: 'gicon gicon-preferences' },
{ id: 'queries', text: 'Queries', icon: 'fa fa-database' },
{ id: 'visualization', text: 'Visualization', icon: 'fa fa-line-chart' },
];
if (config.alertingEnabled && plugin.id === 'graph') {
tabs.push({
id: 'alert',
text: 'Alert',
icon: 'gicon gicon-alert',
});
}
return ( return (
<div className="panel-editor-container__editor"> <div className="panel-editor-container__editor">
...@@ -74,27 +97,12 @@ export class PanelEditor extends PureComponent<PanelEditorProps> { ...@@ -74,27 +97,12 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
<div className="panel-editor-tabs"> <div className="panel-editor-tabs">
<ul className="gf-tabs"> <ul className="gf-tabs">
{this.tabs.map(tab => { {tabs.map(tab => {
return <TabItem tab={tab} activeTab={activeTab} onClick={this.onChangeTab} key={tab.id} />; return <TabItem tab={tab} activeTab={activeTab} onClick={this.onChangeTab} key={tab.id} />;
})} })}
</ul> </ul>
<button className="panel-editor-tabs__close" onClick={this.onClose}>
<i className="fa fa-reply" />
</button>
</div> </div>
{this.renderCurrentTab(activeTab)}
{activeTab === 'general' && <GeneralTab panel={panel} />}
{activeTab === 'queries' && <QueriesTab panel={panel} dashboard={dashboard} />}
{activeTab === 'visualization' && (
<VisualizationTab
panel={panel}
dashboard={dashboard}
plugin={plugin}
onTypeChanged={onTypeChanged}
angularPanel={angularPanel}
/>
)}
</div> </div>
); );
} }
......
...@@ -138,11 +138,6 @@ class GraphCtrl extends MetricsPanelCtrl { ...@@ -138,11 +138,6 @@ class GraphCtrl extends MetricsPanelCtrl {
this.addEditorTab('Display options', 'public/app/plugins/panel/graph/tab_display.html'); this.addEditorTab('Display options', 'public/app/plugins/panel/graph/tab_display.html');
this.addEditorTab('Axes', axesEditorComponent); this.addEditorTab('Axes', axesEditorComponent);
this.addEditorTab('Legend', 'public/app/plugins/panel/graph/tab_legend.html'); this.addEditorTab('Legend', 'public/app/plugins/panel/graph/tab_legend.html');
// if (config.alertingEnabled) {
// this.addEditorTab('Alert', alertTab, 5);
// }
this.subTabIndex = 0; this.subTabIndex = 0;
} }
......
...@@ -9,18 +9,14 @@ ...@@ -9,18 +9,14 @@
.react-grid-item { .react-grid-item {
display: none !important; display: none !important;
transition-property: none !important; transition-property: none !important;
}
.panel--fullscreen { &--fullscreen {
display: block !important; display: block !important;
position: unset !important; position: unset !important;
width: 100% !important; width: 100% !important;
height: 100% !important; height: 100% !important;
transform: translate(0px, 0px) !important; transform: translate(0px, 0px) !important;
} }
.panel {
margin: 0 !important;
} }
// Disable grid interaction indicators in fullscreen panels // Disable grid interaction indicators in fullscreen panels
...@@ -83,10 +79,10 @@ ...@@ -83,10 +79,10 @@
} }
// Disable animation on initial rendering and enable it when component has been mounted. // Disable animation on initial rendering and enable it when component has been mounted.
.react-grid-item.cssTransforms.panel { .react-grid-item.cssTransforms {
transition-property: none; transition-property: none;
} }
.animated .react-grid-item.cssTransforms.panel { .animated .react-grid-item.cssTransforms {
transition-property: transform; transition-property: transform;
} }
...@@ -50,6 +50,10 @@ ...@@ -50,6 +50,10 @@
.navbar-page-btn .fa-caret-down { .navbar-page-btn .fa-caret-down {
display: none; display: none;
} }
.navbar-buttons--close {
display: flex;
}
} }
.navbar-page-btn { .navbar-page-btn {
......
...@@ -4,8 +4,21 @@ ...@@ -4,8 +4,21 @@
height: 100%; height: 100%;
} }
.panel-editor-container__panel { .panel-wrapper {
height: 100%;
&--edit {
flex: 1 1 0;
height: unset;
margin: 0 $dashboard-padding;
}
&--view {
flex: 1 1 0; flex: 1 1 0;
height: 80%;
margin: 0 $dashboard-padding;
padding-top: $dashboard-padding;
}
} }
.panel-editor-container__editor { .panel-editor-container__editor {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment