mirror of
https://github.com/grafana/grafana.git
synced 2025-01-08 15:13:30 -06:00
grid: progress on react grid
This commit is contained in:
parent
10a3504309
commit
2e77bd0cb1
@ -123,7 +123,7 @@ function ($, angular, coreModule, _) {
|
||||
}, 10);
|
||||
}
|
||||
|
||||
scope.$watch("dashboardViewState.state.editview", function(newValue, oldValue) {
|
||||
scope.$watch("ctrl.dashboardViewState.state.editview", function(newValue, oldValue) {
|
||||
if (newValue) {
|
||||
showEditorPane(null, {editview: newValue});
|
||||
} else if (oldValue) {
|
||||
|
@ -8,7 +8,6 @@ export interface GridPos {
|
||||
}
|
||||
|
||||
const notPersistedProperties: {[str: string]: boolean} = {
|
||||
"model": true,
|
||||
"events": true,
|
||||
};
|
||||
|
||||
@ -19,26 +18,26 @@ export class PanelModel {
|
||||
title: string;
|
||||
events: Emitter;
|
||||
|
||||
constructor(private model) {
|
||||
constructor(model) {
|
||||
this.events = new Emitter();
|
||||
|
||||
// copy properties from persisted model
|
||||
for (var property in model) {
|
||||
this[property] = model[property];
|
||||
}
|
||||
|
||||
this.events = new Emitter();
|
||||
}
|
||||
|
||||
getSaveModel() {
|
||||
this.model = {};
|
||||
const model: any = {};
|
||||
for (var property in this) {
|
||||
if (notPersistedProperties[property] || !this.hasOwnProperty(property)) {
|
||||
console.log('PanelModel.getSaveModel() skiping property', property);
|
||||
continue;
|
||||
}
|
||||
|
||||
this.model[property] = this[property];
|
||||
model[property] = this[property];
|
||||
}
|
||||
return this.model;
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
updateGridPos(newPos: GridPos) {
|
||||
|
@ -25,6 +25,7 @@ define([
|
||||
'./repeat_option/repeat_option',
|
||||
'./dashgrid/DashboardGrid',
|
||||
'./dashgrid/PanelLoader',
|
||||
'./row/add_panel',
|
||||
'./acl/acl',
|
||||
'./folder_picker/picker',
|
||||
'./folder_modal/folder'
|
||||
|
@ -3,12 +3,12 @@ import config from 'app/core/config';
|
||||
import coreModule from 'app/core/core_module';
|
||||
import {PanelContainer} from './dashgrid/PanelContainer';
|
||||
import {DashboardModel} from './model';
|
||||
import {PanelModel} from './PanelModel';
|
||||
|
||||
export class DashboardCtrl implements PanelContainer {
|
||||
dashboard: DashboardModel;
|
||||
dashboardViewState: any;
|
||||
loadedFallbackDashboard: boolean;
|
||||
editTab: number;
|
||||
|
||||
/** @ngInject */
|
||||
constructor(
|
||||
@ -27,6 +27,9 @@ export class DashboardCtrl implements PanelContainer {
|
||||
// can't use controllerAs on route yet
|
||||
$scope.ctrl = this;
|
||||
|
||||
// TODO: break out settings view to separate view & controller
|
||||
this.editTab = 0;
|
||||
|
||||
// funcs called from React component bindings and needs this binding
|
||||
this.getPanelContainer = this.getPanelContainer.bind(this);
|
||||
}
|
||||
@ -116,15 +119,6 @@ export class DashboardCtrl implements PanelContainer {
|
||||
return this.panelLoader;
|
||||
}
|
||||
|
||||
getPanels() {
|
||||
return this.dashboard.panels;
|
||||
}
|
||||
|
||||
panelPossitionUpdated(panel: PanelModel) {
|
||||
//console.log('panel pos updated', panel);
|
||||
//this.$rootScope.$broadcast('render');
|
||||
}
|
||||
|
||||
timezoneChanged() {
|
||||
this.$rootScope.$broadcast("refresh");
|
||||
}
|
||||
|
@ -3,13 +3,14 @@ import coreModule from 'app/core/core_module';
|
||||
import ReactGridLayout from 'react-grid-layout';
|
||||
import {CELL_HEIGHT, CELL_VMARGIN} from '../model';
|
||||
import {DashboardPanel} from './DashboardPanel';
|
||||
import {DashboardModel} from '../model';
|
||||
import {PanelContainer} from './PanelContainer';
|
||||
import {PanelModel} from '../PanelModel';
|
||||
import sizeMe from 'react-sizeme';
|
||||
|
||||
const COLUMN_COUNT = 12;
|
||||
|
||||
function GridWrapper({size, layout, onLayoutChange, children}) {
|
||||
function GridWrapper({size, layout, onLayoutChange, children, onResize}) {
|
||||
if (size.width === 0) {
|
||||
console.log('size is zero!');
|
||||
}
|
||||
@ -30,6 +31,7 @@ function GridWrapper({size, layout, onLayoutChange, children}) {
|
||||
rowHeight={CELL_HEIGHT}
|
||||
draggableHandle=".grid-drag-handle"
|
||||
layout={layout}
|
||||
onResize={onResize}
|
||||
onLayoutChange={onLayoutChange}>
|
||||
{children}
|
||||
</ReactGridLayout>
|
||||
@ -45,20 +47,25 @@ export interface DashboardGridProps {
|
||||
export class DashboardGrid extends React.Component<DashboardGridProps, any> {
|
||||
gridToPanelMap: any;
|
||||
panelContainer: PanelContainer;
|
||||
dashboard: DashboardModel;
|
||||
panelMap: {[id: string]: PanelModel};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.panelContainer = this.props.getPanelContainer();
|
||||
this.onLayoutChange = this.onLayoutChange.bind(this);
|
||||
this.onResize = this.onResize.bind(this);
|
||||
|
||||
// subscribe to dashboard events
|
||||
this.dashboard = this.panelContainer.getDashboard();
|
||||
this.dashboard.on('panel-added', this.panelAdded.bind(this));
|
||||
}
|
||||
|
||||
buildLayout() {
|
||||
const layout = [];
|
||||
const panels = this.panelContainer.getPanels();
|
||||
this.panelMap = {};
|
||||
|
||||
for (let panel of panels) {
|
||||
for (let panel of this.dashboard.panels) {
|
||||
let stringId = panel.id.toString();
|
||||
this.panelMap[stringId] = panel;
|
||||
|
||||
@ -85,11 +92,18 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
|
||||
}
|
||||
}
|
||||
|
||||
panelAdded() {
|
||||
this.forceUpdate();
|
||||
}
|
||||
|
||||
onResize(layout, oldItem, newItem) {
|
||||
this.panelMap[newItem.i].updateGridPos(newItem);
|
||||
}
|
||||
|
||||
renderPanels() {
|
||||
const panels = this.panelContainer.getPanels();
|
||||
const panelElements = [];
|
||||
|
||||
for (let panel of panels) {
|
||||
for (let panel of this.dashboard.panels) {
|
||||
panelElements.push(
|
||||
<div key={panel.id.toString()} className="panel">
|
||||
<DashboardPanel panel={panel} getPanelContainer={this.props.getPanelContainer} />
|
||||
@ -101,8 +115,9 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log('DashboardGrid.render()');
|
||||
return (
|
||||
<SizedReactLayoutGrid layout={this.buildLayout()} onLayoutChange={this.onLayoutChange}>
|
||||
<SizedReactLayoutGrid layout={this.buildLayout()} onLayoutChange={this.onLayoutChange} onResize={this.onResize}>
|
||||
{this.renderPanels()}
|
||||
</SizedReactLayoutGrid>
|
||||
);
|
||||
|
@ -1,11 +1,8 @@
|
||||
import {PanelModel} from '../PanelModel';
|
||||
import {DashboardModel} from '../model';
|
||||
import {PanelLoader} from './PanelLoader';
|
||||
|
||||
export interface PanelContainer {
|
||||
getPanels(): PanelModel[];
|
||||
getPanelLoader(): PanelLoader;
|
||||
getDashboard(): DashboardModel;
|
||||
panelPossitionUpdated(panel: PanelModel);
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@
|
||||
</ul>
|
||||
</li>
|
||||
<li class="navbar-mini-btn-wrapper" ng-show="::ctrl.dashboard.meta.canSave">
|
||||
<button class="btn btn-secondary btn-mini" ng-click="ctrl.openEditView('add-panel')">
|
||||
<button class="btn btn-secondary btn-mini" ng-click="ctrl.addPanel()">
|
||||
<i class="fa fa-plus-circle"></i> Add Panel
|
||||
</button>
|
||||
</li>
|
||||
|
@ -145,6 +145,14 @@ export class DashNavCtrl {
|
||||
this.$rootScope.appEvent('show-dash-search');
|
||||
}
|
||||
|
||||
addPanel() {
|
||||
this.dashboard.addPanel({
|
||||
type: 'graph',
|
||||
gridPos: {x: 0, y: 0, w: 6, h: 5},
|
||||
title: 'New Graph',
|
||||
});
|
||||
}
|
||||
|
||||
navItemClicked(navItem, evt) {
|
||||
if (navItem.clickHandler) {
|
||||
navItem.clickHandler();
|
||||
|
@ -180,7 +180,8 @@ export class DashboardModel {
|
||||
|
||||
addPanel(panel) {
|
||||
panel.id = this.getNextPanelId();
|
||||
this.panels.push(panel);
|
||||
this.panels.unshift(new PanelModel(panel));
|
||||
this.events.emit('panel-added', panel);
|
||||
}
|
||||
|
||||
removePanel(panel, ask?) {
|
||||
@ -282,6 +283,14 @@ export class DashboardModel {
|
||||
}
|
||||
}
|
||||
|
||||
on(eventName, callback) {
|
||||
this.events.on(eventName, callback);
|
||||
}
|
||||
|
||||
off(eventName, callback?) {
|
||||
this.events.off(eventName, callback);
|
||||
}
|
||||
|
||||
cycleGraphTooltip() {
|
||||
this.graphTooltip = (this.graphTooltip + 1) % 3;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
<ul class="gf-tabs">
|
||||
<li class="gf-tabs-item" ng-repeat="tab in ::['General', 'Links', 'Time picker']">
|
||||
<a class="gf-tabs-link" ng-click="editor.index = $index" ng-class="{active: editor.index === $index}">
|
||||
<a class="gf-tabs-link" ng-click="ctrl.editTab = $index" ng-class="{active: ctrl.editTab === $index}">
|
||||
{{::tab}}
|
||||
</a>
|
||||
</li>
|
||||
@ -17,30 +17,30 @@
|
||||
</div>
|
||||
|
||||
<div class="tabbed-view-body">
|
||||
<div ng-if="editor.index == 0">
|
||||
<div ng-if="ctrl.editTab == 0">
|
||||
|
||||
<div class="gf-form-group section">
|
||||
<h5 class="section-heading">Details</h5>
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label width-7">Name</label>
|
||||
<input type="text" class="gf-form-input width-30" ng-model='dashboard.title'></input>
|
||||
<input type="text" class="gf-form-input width-30" ng-model='ctrl.dashboard.title'></input>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label width-7">Description</label>
|
||||
<input type="text" class="gf-form-input width-30" ng-model='dashboard.description'></input>
|
||||
<input type="text" class="gf-form-input width-30" ng-model='ctrl.dashboard.description'></input>
|
||||
</div>
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label width-7">
|
||||
Tags
|
||||
<info-popover mode="right-normal">Press enter to add a tag</info-popover>
|
||||
</label>
|
||||
<bootstrap-tagsinput ng-model="dashboard.tags" tagclass="label label-tag" placeholder="add tags">
|
||||
<bootstrap-tagsinput ng-model="ctrl.dashboard.tags" tagclass="label label-tag" placeholder="add tags">
|
||||
</bootstrap-tagsinput>
|
||||
</div>
|
||||
|
||||
<folder-picker ng-if="!dashboardMeta.isFolder"
|
||||
initial-title="dashboardMeta.folderTitle"
|
||||
on-change="onFolderChange($folder)"
|
||||
<folder-picker ng-if="!ctrl.dashboard.meta.isFolder"
|
||||
initial-title="ctrl.dashboard.meta.folderTitle"
|
||||
on-change="ctrl.onFolderChange($folder)"
|
||||
label-class="width-7">
|
||||
</folder-picker>
|
||||
</div>
|
||||
@ -51,19 +51,19 @@
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label width-11">Timezone</label>
|
||||
<div class="gf-form-select-wrapper">
|
||||
<select ng-model="dashboard.timezone" class='gf-form-input' ng-options="f.value as f.text for f in [{value: '', text: 'Default'}, {value: 'browser', text: 'Local browser time'},{value: 'utc', text: 'UTC'}]" ng-change="timezoneChanged()"></select>
|
||||
<select ng-model="ctrl.dashboard.timezone" class='gf-form-input' ng-options="f.value as f.text for f in [{value: '', text: 'Default'}, {value: 'browser', text: 'Local browser time'},{value: 'utc', text: 'UTC'}]" ng-change="timezoneChanged()"></select>
|
||||
</div>
|
||||
</div>
|
||||
<gf-form-switch class="gf-form"
|
||||
label="Editable"
|
||||
tooltip="Uncheck, then save and reload to disable all dashboard editing"
|
||||
checked="dashboard.editable"
|
||||
checked="ctrl.dashboard.editable"
|
||||
label-class="width-11">
|
||||
</gf-form-switch>
|
||||
<gf-form-switch class="gf-form"
|
||||
label="Hide Controls"
|
||||
tooltip="Hide row controls. Shortcut: CTRL+H or CMD+H"
|
||||
checked="dashboard.hideControls"
|
||||
checked="ctrl.dashboard.hideControls"
|
||||
label-class="width-11">
|
||||
</gf-form-switch>
|
||||
</div>
|
||||
@ -79,7 +79,7 @@
|
||||
</info-popover>
|
||||
</label>
|
||||
<div class="gf-form-select-wrapper">
|
||||
<select ng-model="dashboard.graphTooltip" class='gf-form-input' ng-options="f.value as f.text for f in [{value: 0, text: 'Default'}, {value: 1, text: 'Shared crosshair'},{value: 2, text: 'Shared Tooltip'}]"></select>
|
||||
<select ng-model="ctrl.dashboard.graphTooltip" class='gf-form-input' ng-options="f.value as f.text for f in [{value: 0, text: 'Default'}, {value: 1, text: 'Shared crosshair'},{value: 2, text: 'Shared Tooltip'}]"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -90,7 +90,7 @@
|
||||
</div>
|
||||
|
||||
<div ng-if="editor.index == 2">
|
||||
<gf-time-picker-settings dashboard="dashboard"></gf-time-picker-settings>
|
||||
<gf-time-picker-settings dashboard="ctrl.dashboard"></gf-time-picker-settings>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -178,7 +178,7 @@ export class PanelCtrl {
|
||||
this.calculatePanelHeight();
|
||||
this.$timeout(() => {
|
||||
this.render();
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
duplicate() {
|
||||
|
@ -105,9 +105,9 @@ $tight-form-bg: $dark-3;
|
||||
$tight-form-func-bg: #333;
|
||||
$tight-form-func-highlight-bg: #444;
|
||||
|
||||
$modal-background: $black;
|
||||
$code-tag-bg: $gray-1;
|
||||
$code-tag-border: lighten($code-tag-bg, 2%);
|
||||
$modal-backdrop-bg: $dark-3;
|
||||
$code-tag-bg: $gray-1;
|
||||
$code-tag-border: lighten($code-tag-bg, 2%);
|
||||
|
||||
|
||||
// Lists
|
||||
|
@ -112,9 +112,9 @@ $tight-form-bg: $gray-6;
|
||||
$tight-form-func-bg: $gray-5;
|
||||
$tight-form-func-highlight-bg: $gray-6;
|
||||
|
||||
$modal-background: $body-bg;
|
||||
$code-tag-bg: $gray-6;
|
||||
$code-tag-border: darken($code-tag-bg, 3%);
|
||||
$modal-backdrop-bg: $body-bg;
|
||||
$code-tag-bg: $gray-6;
|
||||
$code-tag-border: darken($code-tag-bg, 3%);
|
||||
|
||||
// Lists
|
||||
$grafanaListBackground: $gray-6;
|
||||
|
@ -10,7 +10,7 @@
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: $zindex-modal-backdrop;
|
||||
background-color: $black;
|
||||
background-color: $modal-backdrop-bg;
|
||||
}
|
||||
|
||||
.modal-backdrop,
|
||||
|
Loading…
Reference in New Issue
Block a user