Commit 35403c18 by Torkel Ödegaard

wip: react panel makeover mini progress

parent 542da8dc
...@@ -10,9 +10,7 @@ coreModule.directive('dashClass', function($timeout) { ...@@ -10,9 +10,7 @@ coreModule.directive('dashClass', function($timeout) {
}); });
}); });
$scope.onAppEvent('panel-fullscreen-exit', function() { elem.toggleClass('panel-in-fullscreen', $scope.ctrl.dashboard.meta.fullscreen === true);
elem.toggleClass('panel-in-fullscreen', false);
});
$scope.$watch('ctrl.playlistSrv.isPlaying', function(newValue) { $scope.$watch('ctrl.playlistSrv.isPlaying', function(newValue) {
elem.toggleClass('playlist-active', newValue === true); elem.toggleClass('playlist-active', newValue === true);
......
...@@ -175,6 +175,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> { ...@@ -175,6 +175,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
const panelElements = []; const panelElements = [];
for (let panel of this.dashboard.panels) { for (let panel of this.dashboard.panels) {
console.log('panel.fullscreen', panel.fullscreen);
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}>
......
import React from 'react'; import React from 'react';
import $ from 'jquery';
import config from 'app/core/config'; import config from 'app/core/config';
import classNames from 'classnames'; import classNames from 'classnames';
import { PanelModel } from '../panel_model'; import { PanelModel } from '../panel_model';
...@@ -7,6 +8,11 @@ import { AttachedPanel } from './PanelLoader'; ...@@ -7,6 +8,11 @@ import { AttachedPanel } from './PanelLoader';
import { DashboardRow } from './DashboardRow'; import { DashboardRow } from './DashboardRow';
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 { store } from 'app/stores/store';
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN } from 'app/core/constants';
const TITLE_HEIGHT = 27;
const PANEL_BORDER = 2;
export interface DashboardPanelProps { export interface DashboardPanelProps {
panel: PanelModel; panel: PanelModel;
...@@ -61,13 +67,40 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> { ...@@ -61,13 +67,40 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
PanelComponent = this.pluginExports.PanelComponent; PanelComponent = this.pluginExports.PanelComponent;
} }
let panelContentStyle = {
height: this.getPanelHeight(),
};
return ( return (
<div className="panel-container"> <div>
<PanelHeader panel={this.props.panel} dashboard={this.props.dashboard} /> <div className="panel-container">
<div className="panel-content">{PanelComponent && <PanelComponent />}</div> <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> </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;
}
} }
interface PanelHeaderProps { interface PanelHeaderProps {
...@@ -77,7 +110,11 @@ interface PanelHeaderProps { ...@@ -77,7 +110,11 @@ interface PanelHeaderProps {
export class PanelHeader extends React.Component<PanelHeaderProps, any> { export class PanelHeader extends React.Component<PanelHeaderProps, any> {
onEditPanel = () => { onEditPanel = () => {
this.props.dashboard.setViewMode(this.props.panel, true, true); store.view.updateQuery({
panelId: this.props.panel.id,
edit: true,
fullscreen: true,
});
}; };
render() { render() {
...@@ -124,3 +161,35 @@ export class PanelHeader extends React.Component<PanelHeaderProps, any> { ...@@ -124,3 +161,35 @@ export class PanelHeader extends React.Component<PanelHeaderProps, any> {
); );
} }
} }
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>
);
}
}
...@@ -13,6 +13,7 @@ const notPersistedProperties: { [str: string]: boolean } = { ...@@ -13,6 +13,7 @@ const notPersistedProperties: { [str: string]: boolean } = {
events: true, events: true,
fullscreen: true, fullscreen: true,
isEditing: true, isEditing: true,
editModeInitiated: true,
}; };
export class PanelModel { export class PanelModel {
...@@ -36,6 +37,7 @@ export class PanelModel { ...@@ -36,6 +37,7 @@ export class PanelModel {
fullscreen: boolean; fullscreen: boolean;
isEditing: boolean; isEditing: boolean;
events: Emitter; events: Emitter;
editModeInitiated: boolean;
constructor(model) { constructor(model) {
this.events = new Emitter(); this.events = new Emitter();
...@@ -91,6 +93,10 @@ export class PanelModel { ...@@ -91,6 +93,10 @@ export class PanelModel {
this.events.emit('panel-size-changed'); this.events.emit('panel-size-changed');
} }
initEditMode() {
this.events.emit('panel-init-edit-mode');
}
destroy() { destroy() {
this.events.removeAllListeners(); this.events.removeAllListeners();
} }
......
...@@ -77,13 +77,8 @@ describe('AddPanelPanel', () => { ...@@ -77,13 +77,8 @@ describe('AddPanelPanel', () => {
dashboardMock = { toggleRow: jest.fn() }; dashboardMock = { toggleRow: jest.fn() };
getPanelContainer = jest.fn().mockReturnValue({
getDashboard: jest.fn().mockReturnValue(dashboardMock),
getPanelLoader: jest.fn(),
});
panel = new PanelModel({ collapsed: false }); panel = new PanelModel({ collapsed: false });
wrapper = shallow(<AddPanelPanel panel={panel} getPanelContainer={getPanelContainer} />); wrapper = shallow(<AddPanelPanel panel={panel} dashboard={dashboardMock} />);
}); });
it('should fetch all panels sorted with core plugins first', () => { it('should fetch all panels sorted with core plugins first', () => {
......
...@@ -33,10 +33,6 @@ export class DashboardViewState { ...@@ -33,10 +33,6 @@ export class DashboardViewState {
self.update(payload); self.update(payload);
}); });
$scope.onAppEvent('panel-initialized', function(evt, payload) {
self.registerPanel(payload.scope);
});
// this marks changes to location during this digest cycle as not to add history item // this marks changes to location during this digest cycle as not to add history item
// don't want url changes like adding orgId to add browser history // don't want url changes like adding orgId to add browser history
$location.replace(); $location.replace();
...@@ -124,102 +120,62 @@ export class DashboardViewState { ...@@ -124,102 +120,62 @@ export class DashboardViewState {
} }
syncState() { syncState() {
if (this.panelScopes.length === 0) {
return;
}
if (this.dashboard.meta.fullscreen) { if (this.dashboard.meta.fullscreen) {
var panelScope = this.getPanelScope(this.state.panelId); var panel = this.dashboard.getPanelById(this.state.panelId);
if (!panelScope) {
if (!panel) {
return; return;
} }
if (this.fullscreenPanel) { if (this.fullscreenPanel) {
// if already fullscreen // if already fullscreen
if (this.fullscreenPanel === panelScope && this.editStateChanged === false) { if (this.fullscreenPanel === panel && this.editStateChanged === false) {
return; return;
} else { } else {
this.leaveFullscreen(false); this.leaveFullscreen(false);
} }
} }
if (!panelScope.ctrl.editModeInitiated) { if (!panel.fullscreen) {
panelScope.ctrl.initEditMode(); this.enterFullscreen(panel);
}
if (!panelScope.ctrl.fullscreen) {
this.enterFullscreen(panelScope);
} }
} else if (this.fullscreenPanel) { } else if (this.fullscreenPanel) {
this.leaveFullscreen(true); this.leaveFullscreen(true);
} }
} }
getPanelScope(id) {
return _.find(this.panelScopes, function(panelScope) {
return panelScope.ctrl.panel.id === id;
});
}
leaveFullscreen(render) { leaveFullscreen(render) {
var self = this; var panel = this.fullscreenPanel;
var ctrl = self.fullscreenPanel.ctrl;
ctrl.editMode = false;
ctrl.fullscreen = false;
this.dashboard.setViewMode(ctrl.panel, false, false); this.dashboard.setViewMode(panel, false, false);
this.$scope.appEvent('panel-fullscreen-exit', { panelId: ctrl.panel.id });
this.$scope.appEvent('dash-scroll', { restore: true }); this.$scope.appEvent('dash-scroll', { restore: true });
if (!render) { if (!render) {
return false; return false;
} }
this.$timeout(function() { this.$timeout(() => {
if (self.oldTimeRange !== ctrl.range) { if (this.oldTimeRange !== this.dashboard.time) {
self.$rootScope.$broadcast('refresh'); this.$rootScope.$broadcast('refresh');
} else { } else {
self.$rootScope.$broadcast('render'); this.$rootScope.$broadcast('render');
} }
delete self.fullscreenPanel; delete this.fullscreenPanel;
}); });
return true; return true;
} }
enterFullscreen(panelScope) { enterFullscreen(panel) {
var ctrl = panelScope.ctrl; const isEditing = this.state.edit && this.dashboard.meta.canEdit;
ctrl.editMode = this.state.edit && this.dashboard.meta.canEdit;
ctrl.fullscreen = true;
this.oldTimeRange = ctrl.range; this.oldTimeRange = this.dashboard.time;
this.fullscreenPanel = panelScope; this.fullscreenPanel = panel;
// Firefox doesn't return scrollTop position properly if 'dash-scroll' is emitted after setViewMode() // Firefox doesn't return scrollTop position properly if 'dash-scroll' is emitted after setViewMode()
this.$scope.appEvent('dash-scroll', { animate: false, pos: 0 }); this.$scope.appEvent('dash-scroll', { animate: false, pos: 0 });
this.dashboard.setViewMode(ctrl.panel, true, ctrl.editMode); console.log('viewstatesrv.setViewMode');
this.$scope.appEvent('panel-fullscreen-enter', { panelId: ctrl.panel.id }); this.dashboard.setViewMode(panel, true, isEditing);
}
registerPanel(panelScope) {
var self = this;
self.panelScopes.push(panelScope);
if (!self.dashboard.meta.soloMode) {
if (self.state.panelId === panelScope.ctrl.panel.id) {
if (self.state.edit) {
panelScope.ctrl.editPanel();
} else {
panelScope.ctrl.viewPanel();
}
}
}
var unbind = panelScope.$on('$destroy', function() {
self.panelScopes = _.without(self.panelScopes, panelScope);
unbind();
});
} }
} }
......
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