Commit 207773e0 by Torkel Ödegaard

grid: minor progress

parent a867dc06
export interface PanelModel {
id: number;
x: number;
y: number;
width: number;
height: number;
type: string;
title: string;
}
import config from 'app/core/config'; import config from 'app/core/config';
import angular from 'angular';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import {PanelContainer} from './dashgrid/PanelContainer';
import {DashboardModel} from './model';
import {PanelModel} from './PanelModel';
export class DashboardCtrl { export class DashboardCtrl implements PanelContainer {
dashboard: DashboardModel;
dashboardViewState: any;
loadedFallbackDashboard: boolean;
/** @ngInject */ /** @ngInject */
constructor( constructor(
private $scope, private $scope,
$rootScope, private $rootScope,
keybindingSrv, private keybindingSrv,
timeSrv, private timeSrv,
variableSrv, private variableSrv,
alertingSrv, private alertingSrv,
dashboardSrv, private dashboardSrv,
unsavedChangesSrv, private unsavedChangesSrv,
dynamicDashboardSrv, private dynamicDashboardSrv,
dashboardViewStateSrv, private dashboardViewStateSrv,
panelLoader, private panelLoader) {
contextSrv, // temp hack due to way dashboards are loaded
alertSrv, // can't use controllerAs on route yet
$timeout) { $scope.ctrl = this;
$scope.editor = { index: 0 }; // funcs called from React component bindings and needs this binding
this.getPanelContainer = this.getPanelContainer.bind(this);
var resizeEventTimeout; }
$scope.setupDashboard = function(data) { setupDashboard(data) {
try { try {
$scope.setupDashboardInternal(data); this.setupDashboardInternal(data);
} catch (err) { } catch (err) {
$scope.onInitFailed(err, 'Dashboard init failed', true); this.onInitFailed(err, 'Dashboard init failed', true);
} }
}; }
$scope.setupDashboardInternal = function(data) { setupDashboardInternal(data) {
var dashboard = dashboardSrv.create(data.dashboard, data.meta); const dashboard = this.dashboardSrv.create(data.dashboard, data.meta);
dashboardSrv.setCurrent(dashboard); this.dashboardSrv.setCurrent(dashboard);
// init services // init services
timeSrv.init(dashboard); this.timeSrv.init(dashboard);
alertingSrv.init(dashboard, data.alerts); this.alertingSrv.init(dashboard, data.alerts);
// template values service needs to initialize completely before // template values service needs to initialize completely before
// the rest of the dashboard can load // the rest of the dashboard can load
variableSrv.init(dashboard) this.variableSrv.init(dashboard)
// template values failes are non fatal // template values failes are non fatal
.catch($scope.onInitFailed.bind(this, 'Templating init failed', false)) .catch(this.onInitFailed.bind(this, 'Templating init failed', false))
// continue // continue
.finally(function() { .finally(() => {
dynamicDashboardSrv.init(dashboard); this.dashboard = dashboard;
dynamicDashboardSrv.process();
this.dynamicDashboardSrv.init(dashboard);
unsavedChangesSrv.init(dashboard, $scope); this.dynamicDashboardSrv.process();
$scope.dashboard = dashboard; this.unsavedChangesSrv.init(dashboard, this.$scope);
$scope.dashboardMeta = dashboard.meta;
$scope.dashboardViewState = dashboardViewStateSrv.create($scope); // TODO refactor ViewStateSrv
this.$scope.dashboard = dashboard;
keybindingSrv.setupDashboardBindings($scope, dashboard); this.dashboardViewState = this.dashboardViewStateSrv.create(this.$scope);
$scope.dashboard.updateSubmenuVisibility(); this.keybindingSrv.setupDashboardBindings(this.$scope, dashboard);
$scope.setWindowTitleAndTheme();
this.dashboard.updateSubmenuVisibility();
$scope.appEvent("dashboard-initialized", $scope.dashboard); this.setWindowTitleAndTheme();
})
.catch($scope.onInitFailed.bind(this, 'Dashboard init failed', true)); this.$scope.appEvent("dashboard-initialized", dashboard);
}; })
.catch(this.onInitFailed.bind(this, 'Dashboard init failed', true));
$scope.onInitFailed = function(msg, fatal, err) { }
console.log(msg, err);
onInitFailed(msg, fatal, err) {
if (err.data && err.data.message) { console.log(msg, err);
err.message = err.data.message;
} else if (!err.message) { if (err.data && err.data.message) {
err = {message: err.toString()}; err.message = err.data.message;
} } else if (!err.message) {
err = {message: err.toString()};
$scope.appEvent("alert-error", [msg, err.message]); }
// protect against recursive fallbacks this.$scope.appEvent("alert-error", [msg, err.message]);
if (fatal && !$scope.loadedFallbackDashboard) {
$scope.loadedFallbackDashboard = true; // protect against recursive fallbacks
$scope.setupDashboard({dashboard: {title: 'Dashboard Init failed'}}); if (fatal && !this.loadedFallbackDashboard) {
} this.loadedFallbackDashboard = true;
}; this.setupDashboard({dashboard: {title: 'Dashboard Init failed'}});
}
$scope.templateVariableUpdated = function() { }
dynamicDashboardSrv.process();
}; templateVariableUpdated() {
this.dynamicDashboardSrv.process();
$scope.setWindowTitleAndTheme = function() { }
window.document.title = config.window_title_prefix + $scope.dashboard.title;
}; setWindowTitleAndTheme() {
window.document.title = config.window_title_prefix + this.dashboard.title;
$scope.broadcastRefresh = function() { }
$rootScope.$broadcast('refresh');
}; showJsonEditor(evt, options) {
var editScope = this.$rootScope.$new();
$scope.addRowDefault = function() { editScope.object = options.object;
$scope.dashboard.addEmptyRow(); editScope.updateHandler = options.updateHandler;
}; this.$scope.appEvent('show-dash-editor', { src: 'public/app/partials/edit_json.html', scope: editScope });
}
$scope.showJsonEditor = function(evt, options) {
var editScope = $rootScope.$new(); getDashboard() {
editScope.object = options.object; return this.dashboard;
editScope.updateHandler = options.updateHandler; }
$scope.appEvent('show-dash-editor', { src: 'public/app/partials/edit_json.html', scope: editScope });
}; getPanelLoader() {
return this.panelLoader;
$scope.registerWindowResizeEvent = function() { }
angular.element(window).bind('resize', function() {
$timeout.cancel(resizeEventTimeout); getPanels() {
resizeEventTimeout = $timeout(function() { $scope.$broadcast('render'); }, 200); return this.dashboard.panels;
}); }
$scope.$on('$destroy', function() { panelPossitionUpdated(panel: PanelModel) {
angular.element(window).unbind('resize'); console.log('panel pos updated', panel);
$scope.dashboard.destroy(); }
});
}; timezoneChanged() {
this.$rootScope.$broadcast("refresh");
$scope.timezoneChanged = function() { }
$rootScope.$broadcast("refresh");
}; onFolderChange(folder) {
this.dashboard.folderId = folder.id;
$scope.onFolderChange = function(folder) { this.dashboard.meta.folderId = folder.id;
$scope.dashboard.folderId = folder.id; this.dashboard.meta.folderTitle= folder.title;
$scope.dashboard.meta.folderId = folder.id; }
$scope.dashboard.meta.folderTitle= folder.title;
}; getPanelContainer() {
console.log('DashboardCtrl:getPanelContainer()');
$scope.getPanelLoader = function() { return this;
return panelLoader;
};
} }
init(dashboard) { init(dashboard) {
this.$scope.onAppEvent('show-json-editor', this.$scope.showJsonEditor); this.$scope.onAppEvent('show-json-editor', this.$scope.showJsonEditor);
this.$scope.onAppEvent('template-variable-value-updated', this.$scope.templateVariableUpdated); this.$scope.onAppEvent('template-variable-value-updated', this.$scope.templateVariableUpdated);
this.$scope.setupDashboard(dashboard); this.setupDashboard(dashboard);
this.$scope.registerWindowResizeEvent();
} }
} }
......
import React from 'react'; import React from 'react';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import ReactGridLayout from 'react-grid-layout'; import ReactGridLayout from 'react-grid-layout';
import {DashboardModel} from '../model'; import {CELL_HEIGHT, CELL_VMARGIN} from '../model';
import {DashboardPanel} from './DashboardPanel'; import {DashboardPanel} from './DashboardPanel';
import {PanelLoader} from './PanelLoader'; import {PanelContainer} from './PanelContainer';
import sizeMe from 'react-sizeme'; import sizeMe from 'react-sizeme';
const COLUMN_COUNT = 12; const COLUMN_COUNT = 12;
const ROW_HEIGHT = 30;
function GridWrapper({size, layout, onLayoutChange, children}) { function GridWrapper({size, layout, onLayoutChange, children}) {
if (size.width === 0) { if (size.width === 0) {
...@@ -23,9 +22,9 @@ function GridWrapper({size, layout, onLayoutChange, children}) { ...@@ -23,9 +22,9 @@ function GridWrapper({size, layout, onLayoutChange, children}) {
isDraggable={true} isDraggable={true}
isResizable={true} isResizable={true}
measureBeforeMount={false} measureBeforeMount={false}
margin={[10, 10]} margin={[CELL_VMARGIN, CELL_VMARGIN]}
cols={COLUMN_COUNT} cols={COLUMN_COUNT}
rowHeight={ROW_HEIGHT} rowHeight={CELL_HEIGHT}
draggableHandle=".grid-drag-handle" draggableHandle=".grid-drag-handle"
layout={layout} layout={layout}
onLayoutChange={onLayoutChange}> onLayoutChange={onLayoutChange}>
...@@ -37,21 +36,24 @@ function GridWrapper({size, layout, onLayoutChange, children}) { ...@@ -37,21 +36,24 @@ function GridWrapper({size, layout, onLayoutChange, children}) {
const SizedReactLayoutGrid = sizeMe({monitorWidth: true})(GridWrapper); const SizedReactLayoutGrid = sizeMe({monitorWidth: true})(GridWrapper);
export interface DashboardGridProps { export interface DashboardGridProps {
dashboard: DashboardModel; getPanelContainer: () => PanelContainer;
getPanelLoader: () => PanelLoader;
} }
export class DashboardGrid extends React.Component<DashboardGridProps, any> { export class DashboardGrid extends React.Component<DashboardGridProps, any> {
gridToPanelMap: any; gridToPanelMap: any;
panelContainer: PanelContainer;
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);
} }
buildLayout() { buildLayout() {
const layout = []; const layout = [];
for (let panel of this.props.dashboard.panels) { const panels = this.panelContainer.getPanels();
for (let panel of panels) {
layout.push({ layout.push({
i: panel.id.toString(), i: panel.id.toString(),
x: panel.x, x: panel.x,
...@@ -60,21 +62,28 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> { ...@@ -60,21 +62,28 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
h: panel.height, h: panel.height,
}); });
} }
console.log(layout);
console.log('layout', layout);
return layout; return layout;
} }
onLayoutChange() {} onLayoutChange() {}
renderPanels() { renderPanels() {
const panels = this.panelContainer.getPanels();
const panelElements = []; const panelElements = [];
for (let panel of this.props.dashboard.panels) {
for (let panel of panels) {
panelElements.push( panelElements.push(
<div key={panel.id.toString()} className="panel"> <div key={panel.id.toString()} className="panel">
<DashboardPanel panel={panel} getPanelLoader={this.props.getPanelLoader} dashboard={this.props.dashboard} /> <DashboardPanel
panel={panel}
getPanelContainer={this.props.getPanelContainer}
/>
</div>, </div>,
); );
} }
return panelElements; return panelElements;
} }
...@@ -88,8 +97,5 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> { ...@@ -88,8 +97,5 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
} }
coreModule.directive('dashboardGrid', function(reactDirective) { coreModule.directive('dashboardGrid', function(reactDirective) {
return reactDirective(DashboardGrid, [ return reactDirective(DashboardGrid, [['getPanelContainer', {watchDepth: 'reference', wrapApply: false}]]);
['dashboard', {watchDepth: 'reference'}],
['getPanelLoader', {watchDepth: 'reference', wrapApply: false}],
]);
}); });
import React from 'react'; import React from 'react';
import {PanelLoader} from './PanelLoader'; import {PanelModel} from '../PanelModel';
import {PanelContainer} from './PanelContainer';
import {AttachedPanel} from './PanelLoader';
export interface DashboardPanelProps { export interface DashboardPanelProps {
panel: any; panel: PanelModel;
dashboard: any; getPanelContainer: () => PanelContainer;
getPanelLoader: () => PanelLoader;
} }
export class DashboardPanel extends React.Component<DashboardPanelProps, any> { export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
private element: any; element: any;
attachedPanel: AttachedPanel;
constructor(props) { constructor(props) {
super(props); super(props);
...@@ -16,8 +18,17 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> { ...@@ -16,8 +18,17 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
} }
componentDidMount() { componentDidMount() {
var loader = this.props.getPanelLoader(); const panelContainer = this.props.getPanelContainer();
loader.load(this.element, this.props.panel, this.props.dashboard); const dashboard = panelContainer.getDashboard();
const loader = panelContainer.getPanelLoader();
this.attachedPanel = loader.load(this.element, this.props.panel, dashboard);
}
componentWillUnmount() {
if (this.attachedPanel) {
this.attachedPanel.destroy();
}
} }
render() { render() {
......
import {PanelModel} from '../PanelModel';
import {DashboardModel}  from '../model';
import {PanelLoader} from './PanelLoader';
export interface PanelContainer {
getPanels(): PanelModel[];
getPanelLoader(): PanelLoader;
getDashboard(): DashboardModel;
panelPossitionUpdated(panel: PanelModel);
}
...@@ -23,6 +23,7 @@ export class PanelLoader { ...@@ -23,6 +23,7 @@ export class PanelLoader {
return { return {
destroy: () => { destroy: () => {
console.log('AttachedPanel:Destroy, id' + panel.id);
panelScope.$destroy(); panelScope.$destroy();
compiledElem.remove(); compiledElem.remove();
} }
......
///<reference path="../../headers/common.d.ts" />
import angular from 'angular'; import angular from 'angular';
import moment from 'moment'; import moment from 'moment';
import _ from 'lodash'; import _ from 'lodash';
...@@ -8,18 +6,9 @@ import $ from 'jquery'; ...@@ -8,18 +6,9 @@ import $ from 'jquery';
import {DEFAULT_ANNOTATION_COLOR} from 'app/core/utils/colors'; import {DEFAULT_ANNOTATION_COLOR} from 'app/core/utils/colors';
import {Emitter, contextSrv, appEvents} from 'app/core/core'; import {Emitter, contextSrv, appEvents} from 'app/core/core';
import {DashboardRow} from './row/row_model'; import {DashboardRow} from './row/row_model';
import {PanelModel} from './PanelModel';
import sortByKeys from 'app/core/utils/sort_by_keys'; import sortByKeys from 'app/core/utils/sort_by_keys';
export interface Panel {
id: number;
x: number;
y: number;
width: number;
height: number;
type: string;
title: string;
}
export const CELL_HEIGHT = 30; export const CELL_HEIGHT = 30;
export const CELL_VMARGIN = 15; export const CELL_VMARGIN = 15;
...@@ -50,7 +39,7 @@ export class DashboardModel { ...@@ -50,7 +39,7 @@ export class DashboardModel {
events: any; events: any;
editMode: boolean; editMode: boolean;
folderId: number; folderId: number;
panels: Panel[]; panels: PanelModel[];
constructor(data, meta?) { constructor(data, meta?) {
if (!data) { if (!data) {
......
<div dash-class ng-if="dashboard"> <div dash-class ng-if="ctrl.dashboard">
<dashnav dashboard="dashboard"></dashnav> <dashnav dashboard="ctrl.dashboard"></dashnav>
<div class="scroll-canvas scroll-canvas--dashboard"> <div class="scroll-canvas scroll-canvas--dashboard">
<div gemini-scrollbar> <div gemini-scrollbar>
<div dash-editor-view class="dash-edit-view"></div> <div dash-editor-view class="dash-edit-view"></div>
<div class="dashboard-container"> <div class="dashboard-container">
<dashboard-submenu ng-if="dashboard.meta.submenuEnabled" dashboard="dashboard"></dashboard-submenu> <dashboard-submenu ng-if="ctrl.dashboard.meta.submenuEnabled" dashboard="ctrl.dashboard">
</dashboard-submenu>
<!-- <dash&#45;grid dashboard="dashboard"></dash&#45;grid> --> <dashboard-grid get-panel-container="ctrl.getPanelContainer">
<dashboard-grid dashboard="dashboard" get-panel-loader="getPanelLoader">
</dashboard-grid> </dashboard-grid>
</div> </div>
......
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