Commit 23060614 by Torkel Ödegaard

wip: react panel minor progrss

parent 65b96e11
...@@ -10,6 +10,7 @@ import { createStore } from 'app/stores/store'; ...@@ -10,6 +10,7 @@ import { createStore } from 'app/stores/store';
import colors from 'app/core/utils/colors'; import colors from 'app/core/utils/colors';
import { BackendSrv } from 'app/core/services/backend_srv'; import { BackendSrv } from 'app/core/services/backend_srv';
import { DatasourceSrv } from 'app/features/plugins/datasource_srv'; import { DatasourceSrv } from 'app/features/plugins/datasource_srv';
import { AngularLoader, setAngularLoader } from 'app/core/services/angular_loader';
export class GrafanaCtrl { export class GrafanaCtrl {
/** @ngInject */ /** @ngInject */
...@@ -22,8 +23,12 @@ export class GrafanaCtrl { ...@@ -22,8 +23,12 @@ export class GrafanaCtrl {
contextSrv, contextSrv,
bridgeSrv, bridgeSrv,
backendSrv: BackendSrv, backendSrv: BackendSrv,
angularLoader: AngularLoader,
datasourceSrv: DatasourceSrv datasourceSrv: DatasourceSrv
) { ) {
// make angular loader service available to react components
setAngularLoader(angularLoader);
// create store with env services
createStore({ backendSrv, datasourceSrv }); createStore({ backendSrv, datasourceSrv });
$scope.init = function() { $scope.init = function() {
......
import angular from 'angular'; import angular from 'angular';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import _ from 'lodash';
export interface AttachedPanel { export interface AngularComponent {
destroy(); destroy();
} }
export class PanelLoader { export class AngularLoader {
/** @ngInject */ /** @ngInject */
constructor(private $compile, private $rootScope) {} constructor(private $compile, private $rootScope) {}
load(elem, panel, dashboard): AttachedPanel { load(elem, scopeProps, template): AngularComponent {
var template = '<plugin-component type="panel" class="panel-height-helper"></plugin-component>'; var scope = this.$rootScope.$new();
var panelScope = this.$rootScope.$new();
panelScope.panel = panel;
panelScope.dashboard = dashboard;
const compiledElem = this.$compile(template)(panelScope); _.assign(scope, scopeProps);
const compiledElem = this.$compile(template)(scope);
const rootNode = angular.element(elem); const rootNode = angular.element(elem);
rootNode.append(compiledElem); rootNode.append(compiledElem);
return { return {
destroy: () => { destroy: () => {
panelScope.$destroy(); scope.$destroy();
compiledElem.remove(); compiledElem.remove();
}, },
}; };
} }
} }
coreModule.service('panelLoader', PanelLoader); coreModule.service('angularLoader', AngularLoader);
let angularLoaderInstance: AngularLoader;
export function setAngularLoader(pl: AngularLoader) {
angularLoaderInstance = pl;
}
// away to access it from react
export function getAngularLoader(): AngularLoader {
return angularLoaderInstance;
}
...@@ -22,7 +22,6 @@ import './export_data/export_data_modal'; ...@@ -22,7 +22,6 @@ import './export_data/export_data_modal';
import './ad_hoc_filters'; import './ad_hoc_filters';
import './repeat_option/repeat_option'; import './repeat_option/repeat_option';
import './dashgrid/DashboardGridDirective'; import './dashgrid/DashboardGridDirective';
import './dashgrid/PanelLoader';
import './dashgrid/RowOptions'; import './dashgrid/RowOptions';
import './folder_picker/folder_picker'; import './folder_picker/folder_picker';
import './move_to_folder_modal/move_to_folder'; import './move_to_folder_modal/move_to_folder';
......
import config from 'app/core/config'; import config from 'app/core/config';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import { PanelContainer } from './dashgrid/PanelContainer';
import { DashboardModel } from './dashboard_model'; import { DashboardModel } from './dashboard_model';
import { PanelModel } from './panel_model'; import { PanelModel } from './panel_model';
export class DashboardCtrl implements PanelContainer { export class DashboardCtrl {
dashboard: DashboardModel; dashboard: DashboardModel;
dashboardViewState: any; dashboardViewState: any;
loadedFallbackDashboard: boolean; loadedFallbackDashboard: boolean;
...@@ -22,8 +21,7 @@ export class DashboardCtrl implements PanelContainer { ...@@ -22,8 +21,7 @@ export class DashboardCtrl implements PanelContainer {
private dashboardSrv, private dashboardSrv,
private unsavedChangesSrv, private unsavedChangesSrv,
private dashboardViewStateSrv, private dashboardViewStateSrv,
public playlistSrv, public playlistSrv
private panelLoader
) { ) {
// temp hack due to way dashboards are loaded // temp hack due to way dashboards are loaded
// can't use controllerAs on route yet // can't use controllerAs on route yet
...@@ -119,10 +117,6 @@ export class DashboardCtrl implements PanelContainer { ...@@ -119,10 +117,6 @@ export class DashboardCtrl implements PanelContainer {
return this.dashboard; return this.dashboard;
} }
getPanelLoader() {
return this.panelLoader;
}
timezoneChanged() { timezoneChanged() {
this.$rootScope.$broadcast('refresh'); this.$rootScope.$broadcast('refresh');
} }
......
...@@ -3,7 +3,6 @@ import ReactGridLayout from 'react-grid-layout'; ...@@ -3,7 +3,6 @@ import ReactGridLayout from 'react-grid-layout';
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT } from 'app/core/constants'; import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT } from 'app/core/constants';
import { DashboardPanel } from './DashboardPanel'; import { DashboardPanel } from './DashboardPanel';
import { DashboardModel } from '../dashboard_model'; import { DashboardModel } from '../dashboard_model';
import { PanelContainer } from './PanelContainer';
import { PanelModel } from '../panel_model'; import { PanelModel } from '../panel_model';
import classNames from 'classnames'; import classNames from 'classnames';
import sizeMe from 'react-sizeme'; import sizeMe from 'react-sizeme';
...@@ -60,18 +59,15 @@ function GridWrapper({ ...@@ -60,18 +59,15 @@ function GridWrapper({
const SizedReactLayoutGrid = sizeMe({ monitorWidth: true })(GridWrapper); const SizedReactLayoutGrid = sizeMe({ monitorWidth: true })(GridWrapper);
export interface DashboardGridProps { export interface DashboardGridProps {
getPanelContainer: () => PanelContainer; dashboard: DashboardModel;
} }
export class DashboardGrid extends React.Component<DashboardGridProps, any> { export class DashboardGrid extends React.Component<DashboardGridProps, any> {
gridToPanelMap: any; gridToPanelMap: any;
panelContainer: PanelContainer;
dashboard: DashboardModel;
panelMap: { [id: string]: PanelModel }; panelMap: { [id: string]: PanelModel };
constructor(props) { constructor(props) {
super(props); super(props);
this.panelContainer = this.props.getPanelContainer();
this.onLayoutChange = this.onLayoutChange.bind(this); this.onLayoutChange = this.onLayoutChange.bind(this);
this.onResize = this.onResize.bind(this); this.onResize = this.onResize.bind(this);
this.onResizeStop = this.onResizeStop.bind(this); this.onResizeStop = this.onResizeStop.bind(this);
...@@ -81,20 +77,20 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> { ...@@ -81,20 +77,20 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
this.state = { animated: false }; this.state = { animated: false };
// subscribe to dashboard events // subscribe to dashboard events
this.dashboard = this.panelContainer.getDashboard(); let dashboard = this.props.dashboard;
this.dashboard.on('panel-added', this.triggerForceUpdate.bind(this)); dashboard.on('panel-added', this.triggerForceUpdate.bind(this));
this.dashboard.on('panel-removed', this.triggerForceUpdate.bind(this)); dashboard.on('panel-removed', this.triggerForceUpdate.bind(this));
this.dashboard.on('repeats-processed', this.triggerForceUpdate.bind(this)); dashboard.on('repeats-processed', this.triggerForceUpdate.bind(this));
this.dashboard.on('view-mode-changed', this.onViewModeChanged.bind(this)); dashboard.on('view-mode-changed', this.onViewModeChanged.bind(this));
this.dashboard.on('row-collapsed', this.triggerForceUpdate.bind(this)); dashboard.on('row-collapsed', this.triggerForceUpdate.bind(this));
this.dashboard.on('row-expanded', this.triggerForceUpdate.bind(this)); dashboard.on('row-expanded', this.triggerForceUpdate.bind(this));
} }
buildLayout() { buildLayout() {
const layout = []; const layout = [];
this.panelMap = {}; this.panelMap = {};
for (let panel of this.dashboard.panels) { for (let panel of this.props.dashboard.panels) {
let stringId = panel.id.toString(); let stringId = panel.id.toString();
this.panelMap[stringId] = panel; this.panelMap[stringId] = panel;
...@@ -129,7 +125,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> { ...@@ -129,7 +125,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
this.panelMap[newPos.i].updateGridPos(newPos); this.panelMap[newPos.i].updateGridPos(newPos);
} }
this.dashboard.sortPanelsByGridPos(); this.props.dashboard.sortPanelsByGridPos();
} }
triggerForceUpdate() { triggerForceUpdate() {
...@@ -137,7 +133,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> { ...@@ -137,7 +133,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
} }
onWidthChange() { onWidthChange() {
for (const panel of this.dashboard.panels) { for (const panel of this.props.dashboard.panels) {
panel.resizeDone(); panel.resizeDone();
} }
} }
...@@ -176,11 +172,11 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> { ...@@ -176,11 +172,11 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
renderPanels() { renderPanels() {
const panelElements = []; const panelElements = [];
for (let panel of this.dashboard.panels) { for (let panel of this.props.dashboard.panels) {
const panelClasses = classNames({ panel: true, 'panel--fullscreen': panel.fullscreen }); const panelClasses = classNames({ panel: true, 'panel--fullscreen': panel.fullscreen });
panelElements.push( panelElements.push(
<div key={panel.id.toString()} className={panelClasses}> <div key={panel.id.toString()} className={panelClasses}>
<DashboardPanel panel={panel} dashboard={this.dashboard} panelContainer={this.panelContainer} /> <DashboardPanel panel={panel} dashboard={this.props.dashboard} />
</div> </div>
); );
} }
...@@ -193,8 +189,8 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> { ...@@ -193,8 +189,8 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
<SizedReactLayoutGrid <SizedReactLayoutGrid
className={classNames({ layout: true, animated: this.state.animated })} className={classNames({ layout: true, animated: this.state.animated })}
layout={this.buildLayout()} layout={this.buildLayout()}
isResizable={this.dashboard.meta.canEdit} isResizable={this.props.dashboard.meta.canEdit}
isDraggable={this.dashboard.meta.canEdit} isDraggable={this.props.dashboard.meta.canEdit}
onLayoutChange={this.onLayoutChange} onLayoutChange={this.onLayoutChange}
onWidthChange={this.onWidthChange} onWidthChange={this.onWidthChange}
onDragStop={this.onDragStop} onDragStop={this.onDragStop}
......
import { react2AngularDirective } from 'app/core/utils/react2angular'; import { react2AngularDirective } from 'app/core/utils/react2angular';
import { DashboardGrid } from './DashboardGrid'; import { DashboardGrid } from './DashboardGrid';
react2AngularDirective('dashboardGrid', DashboardGrid, [ react2AngularDirective('dashboardGrid', DashboardGrid, [['dashboard', { watchDepth: 'reference' }]]);
['getPanelContainer', { watchDepth: 'reference', wrapApply: false }],
]);
...@@ -2,9 +2,8 @@ import React from 'react'; ...@@ -2,9 +2,8 @@ import React from 'react';
import config from 'app/core/config'; import config from 'app/core/config';
import { PanelModel } from '../panel_model'; import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model'; import { DashboardModel } from '../dashboard_model';
import { AttachedPanel } from './PanelLoader'; import { getAngularLoader, AngularComponent } from 'app/core/services/angular_loader';
import { DashboardRow } from './DashboardRow'; import { DashboardRow } from './DashboardRow';
import { PanelContainer } from './PanelContainer';
import { AddPanelPanel } from './AddPanelPanel'; import { AddPanelPanel } from './AddPanelPanel';
import { importPluginModule } from 'app/features/plugins/plugin_loader'; import { importPluginModule } from 'app/features/plugins/plugin_loader';
import { PanelChrome } from './PanelChrome'; import { PanelChrome } from './PanelChrome';
...@@ -12,12 +11,11 @@ import { PanelChrome } from './PanelChrome'; ...@@ -12,12 +11,11 @@ import { PanelChrome } from './PanelChrome';
export interface DashboardPanelProps { export interface DashboardPanelProps {
panel: PanelModel; panel: PanelModel;
dashboard: DashboardModel; dashboard: DashboardModel;
panelContainer: PanelContainer;
} }
export class DashboardPanel extends React.Component<DashboardPanelProps, any> { export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
element: any; element: any;
attachedPanel: AttachedPanel; angularPanel: AngularComponent;
pluginInfo: any; pluginInfo: any;
pluginExports: any; pluginExports: any;
specialPanels = {}; specialPanels = {};
...@@ -55,17 +53,19 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> { ...@@ -55,17 +53,19 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
componentDidUpdate() { componentDidUpdate() {
// skip loading angular component if we have no element // skip loading angular component if we have no element
// or we have already loaded it // or we have already loaded it
if (!this.element || this.attachedPanel) { if (!this.element || this.angularPanel) {
return; return;
} }
const loader = this.props.panelContainer.getPanelLoader(); let loader = getAngularLoader();
this.attachedPanel = loader.load(this.element, this.props.panel, this.props.dashboard); var template = '<plugin-component type="panel" class="panel-height-helper"></plugin-component>';
let scopeProps = { panel: this.props.panel, dashboard: this.props.dashboard };
this.angularPanel = loader.load(this.element, scopeProps, template);
} }
componentWillUnmount() { componentWillUnmount() {
if (this.attachedPanel) { if (this.angularPanel) {
this.attachedPanel.destroy(); this.angularPanel.destroy();
} }
} }
......
...@@ -32,7 +32,6 @@ export class PanelChrome extends React.Component<PanelChromeProps, any> { ...@@ -32,7 +32,6 @@ export class PanelChrome extends React.Component<PanelChromeProps, any> {
}; };
let PanelComponent = this.props.component; let PanelComponent = this.props.component;
console.log('PanelChrome render');
return ( return (
<div className="panel-height-helper"> <div className="panel-height-helper">
...@@ -42,9 +41,7 @@ export class PanelChrome extends React.Component<PanelChromeProps, any> { ...@@ -42,9 +41,7 @@ export class PanelChrome extends React.Component<PanelChromeProps, any> {
{<PanelComponent />} {<PanelComponent />}
</div> </div>
</div> </div>
<div> {this.props.panel.isEditing && <PanelEditor panel={this.props.panel} dashboard={this.props.dashboard} />}
{this.props.panel.isEditing && <PanelEditor panel={this.props.panel} dashboard={this.props.dashboard} />}
</div>
</div> </div>
); );
} }
...@@ -55,7 +52,7 @@ export class PanelChrome extends React.Component<PanelChromeProps, any> { ...@@ -55,7 +52,7 @@ export class PanelChrome extends React.Component<PanelChromeProps, any> {
if (panel.fullscreen) { if (panel.fullscreen) {
var docHeight = $(window).height(); var docHeight = $(window).height();
var editHeight = Math.floor(docHeight * 0.4); var editHeight = Math.floor(docHeight * 0.3);
var fullscreenHeight = Math.floor(docHeight * 0.8); var fullscreenHeight = Math.floor(docHeight * 0.8);
height = panel.isEditing ? editHeight : fullscreenHeight; height = panel.isEditing ? editHeight : fullscreenHeight;
} else { } else {
......
import { DashboardModel } from '../dashboard_model';
import { PanelLoader } from './PanelLoader';
export interface PanelContainer {
getPanelLoader(): PanelLoader;
getDashboard(): DashboardModel;
}
import React from 'react'; import React from 'react';
import { PanelModel } from '../panel_model'; import { PanelModel } from '../panel_model';
import { DashboardModel } from '../dashboard_model'; import { DashboardModel } from '../dashboard_model';
import { getAngularLoader, AngularComponent } from 'app/core/services/angular_loader';
interface PanelEditorProps { interface PanelEditorProps {
panel: PanelModel; panel: PanelModel;
...@@ -8,9 +9,38 @@ interface PanelEditorProps { ...@@ -8,9 +9,38 @@ interface PanelEditorProps {
} }
export class PanelEditor extends React.Component<PanelEditorProps, any> { export class PanelEditor extends React.Component<PanelEditorProps, any> {
queryElement: any;
queryComp: AngularComponent;
constructor(props) {
super(props);
}
componentDidMount() {
if (!this.queryElement) {
return;
}
let loader = getAngularLoader();
var template = '<plugin-component type="query-ctrl" />';
let scopeProps = {
ctrl: {
panel: this.props.panel,
dashboard: this.props.dashboard,
panelCtrl: {
panel: this.props.panel,
dashboard: this.props.dashboard,
},
},
target: {},
};
this.queryComp = loader.load(this.queryElement, scopeProps, template);
}
render() { render() {
return ( return (
<div className="tabbed-view tabbed-view--panel-edit"> <div className="tabbed-view tabbed-view--panel-edit-new">
<div className="tabbed-view-header"> <div className="tabbed-view-header">
<ul className="gf-tabs"> <ul className="gf-tabs">
<li className="gf-tabs-item"> <li className="gf-tabs-item">
...@@ -26,7 +56,9 @@ export class PanelEditor extends React.Component<PanelEditorProps, any> { ...@@ -26,7 +56,9 @@ export class PanelEditor extends React.Component<PanelEditorProps, any> {
</button> </button>
</div> </div>
<div className="tabbed-view-body">testing</div> <div className="tabbed-view-body">
<div ref={element => (this.queryElement = element)} className="panel-height-helper" />
</div>
</div> </div>
); );
} }
......
...@@ -110,6 +110,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $ ...@@ -110,6 +110,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
let datasource = scope.target.datasource || scope.ctrl.panel.datasource; let datasource = scope.target.datasource || scope.ctrl.panel.datasource;
return datasourceSrv.get(datasource).then(ds => { return datasourceSrv.get(datasource).then(ds => {
scope.datasource = ds; scope.datasource = ds;
console.log('scope', scope);
return importPluginModule(ds.meta.module).then(dsModule => { return importPluginModule(ds.meta.module).then(dsModule => {
return { return {
......
...@@ -11,8 +11,7 @@ ...@@ -11,8 +11,7 @@
<dashboard-submenu ng-if="ctrl.dashboard.meta.submenuEnabled" dashboard="ctrl.dashboard"> <dashboard-submenu ng-if="ctrl.dashboard.meta.submenuEnabled" dashboard="ctrl.dashboard">
</dashboard-submenu> </dashboard-submenu>
<dashboard-grid get-panel-container="ctrl.getPanelContainer"> <dashboard-grid dashboard="ctrl.dashboard"></dashboard-grid>
</dashboard-grid>
</div> </div>
</div> </div>
</div> </div>
...@@ -10,6 +10,15 @@ ...@@ -10,6 +10,15 @@
background: none; background: none;
} }
} }
&.tabbed-view--panel-edit-new {
padding: 10px 0 0 0;
.tabbed-view-header {
padding: 0px;
background: none;
}
}
} }
.tabbed-view-header { .tabbed-view-header {
......
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