Commit cd10be0f by Torkel Ödegaard

newgrid: row progress

parent a9797674
......@@ -82,9 +82,11 @@ export class DashboardModel {
this.folderId = data.folderId || null;
this.panels = _.map(data.panels || [], panelData => new PanelModel(panelData));
this.addBuiltInAnnotationQuery();
this.initMeta(meta);
this.updateSchema(data);
this.addBuiltInAnnotationQuery();
this.sortPanelsByGridPos();
}
addBuiltInAnnotationQuery() {
......@@ -200,10 +202,12 @@ export class DashboardModel {
return null;
}
addPanel(panel) {
panel.id = this.getNextPanelId();
addPanel(panelData) {
panelData.id = this.getNextPanelId();
let panel = new PanelModel(panelData);
this.panels.unshift(new PanelModel(panel));
this.panels.unshift(panel);
this.sortPanelsByGridPos();
......@@ -395,9 +399,51 @@ export class DashboardModel {
destroy() {
this.events.removeAllListeners();
for (let row of this.rows) {
row.destroy();
for (let panel of this.panels) {
panel.destroy();
}
}
toggleRow(row) {
let rowPanels = [];
let rowFound = false;
// if already collapsed
if (row.collapse) {
row.collapse = false;
for (let panel of row.panels) {
this.panels.push(new PanelModel(panel));
}
row.panels = [];
} else {
for (let index = 0; index < this.panels.length; index++) {
let panel = this.panels[index];
if (rowFound) {
// break when encountering another row
if (panel.type === 'row') {
break;
}
// this panel must belong to row
rowPanels.push(panel);
} else if (panel === row) {
rowFound = true;
}
}
// remove panels
_.pull(this.panels, ...rowPanels);
// save panel models inside row panel
row.panels = _.map(rowPanels, panel => panel.getSaveModel());
row.collapse = true;
}
// emit change event
this.events.emit('row-collapse-changed');
}
on(eventName, callback) {
......
......@@ -4,7 +4,6 @@ import _ from 'lodash';
import config from 'app/core/config';
import {PanelModel} from '../panel_model';
import {PanelContainer} from './PanelContainer';
import {GRID_COLUMN_COUNT} from 'app/core/constants';
export interface AddPanelPanelProps {
panel: PanelModel;
......@@ -46,9 +45,6 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
const dashboard = panelContainer.getDashboard();
const {gridPos} = this.props.panel;
// remove add-panel panel
dashboard.removePanel(this.props.panel);
var newPanel: any = {
type: panelPluginInfo.id,
title: 'Panel Title',
......@@ -57,10 +53,11 @@ export class AddPanelPanel extends React.Component<AddPanelPanelProps, AddPanelP
if (panelPluginInfo.id === 'row') {
newPanel.title = 'Row title';
newPanel.gridPos = {x: 0, y: 0, w: GRID_COLUMN_COUNT, h: 1, static: true};
newPanel.gridPos = {x: 0, y: 0};
}
dashboard.addPanel(newPanel);
dashboard.removePanel(this.props.panel);
}
renderPanelItem(panel) {
......
......@@ -70,6 +70,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
this.dashboard.on('panel-removed', this.triggerForceUpdate.bind(this));
this.dashboard.on('repeats-processed', this.triggerForceUpdate.bind(this));
this.dashboard.on('view-mode-changed', this.triggerForceUpdate.bind(this));
this.dashboard.on('row-collapse-changed', this.triggerForceUpdate.bind(this));
}
buildLayout() {
......@@ -85,14 +86,22 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
continue;
}
layout.push({
let panelPos: any = {
i: stringId,
x: panel.gridPos.x,
y: panel.gridPos.y,
w: panel.gridPos.w,
h: panel.gridPos.h,
static: panel.gridPos.static,
});
};
if (panel.type === 'row') {
panelPos.w = GRID_COLUMN_COUNT;
panelPos.h = 1;
panelPos.isResizable = false;
panelPos.isDraggable = panel.collapse;
}
layout.push(panelPos);
}
return layout;
......@@ -109,7 +118,6 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
}
onWidthChange() {
console.log('width change');
for (const panel of this.dashboard.panels) {
panel.resizeDone();
}
......
......@@ -39,7 +39,7 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
render() {
// special handling for rows
if (this.props.panel.type === 'row') {
return <DashboardRow panel={this.props.panel} />;
return <DashboardRow panel={this.props.panel} getPanelContainer={this.props.getPanelContainer} />;
}
if (this.props.panel.type === 'add-panel') {
......
import React from 'react';
import classNames from 'classnames';
import {PanelModel} from '../panel_model';
import {PanelContainer} from './PanelContainer';
export interface DashboardRowProps {
panel: PanelModel;
getPanelContainer: () => PanelContainer;
}
export class DashboardRow extends React.Component<DashboardRowProps, any> {
constructor(props) {
super(props);
this.state = {
collapse: this.props.panel.collapse,
};
this.toggle = this.toggle.bind(this);
this.openSettings = this.openSettings.bind(this);
}
toggle() {}
toggle() {
const panelContainer = this.props.getPanelContainer();
const dashboard = panelContainer.getDashboard();
dashboard.toggleRow(this.props.panel);
this.setState(prevState => {
return {collapse: !prevState.collapse};
});
}
openSettings() {}
render() {
const classes = classNames({'dashboard-row': true, 'dashboard-row--collapse': this.state.collapse});
const chevronClass = classNames({'fa': true, 'fa-chevron-down': !this.state.collapse, 'fa-chevron-right': this.state.collapse});
return (
<div className="dashboard-row">
<div className={classes}>
<a className="dashboard-row__title pointer" onClick={this.toggle}>
<i className="fa fa-chevron-down" />
<i className={chevronClass} />
{this.props.panel.title}
</a>
<div className="dashboard-row__actions">
......
<div class="navbar">
<div class="navbar-inner">
<a class="navbar-page-icon" ng-click="ctrl.starDashboard()">
<i class="gicon gicon-dashboard-starred"></i>
<a class="navbar-page-icon" ng-click="ctrl.starDashboard()" bs-tooltip="'Mark as favorite'" data-placement="bottom">
<i class="fa" ng-class="{'fa-star-o': !ctrl.dashboard.meta.isStarred, 'fa-star': ctrl.dashboard.meta.isStarred}"></i>
</a>
<a class="navbar-page-btn" ng-click="ctrl.showSearch()">
......
......@@ -27,6 +27,7 @@ export class PanelModel {
repeatPanelId?: number;
repeatDirection?: string;
minSpan?: number;
collapse?: boolean;
// non persisted
fullscreen: boolean;
......@@ -86,5 +87,9 @@ export class PanelModel {
resizeDone() {
this.events.emit('panel-size-changed');
}
destroy() {
this.events.removeAllListeners();
}
}
......@@ -168,7 +168,7 @@ describe('DashboardModel', function() {
});
it('should move pulldowns to new schema', function() {
expect(model.annotations.list[0].name).to.be('old');
expect(model.annotations.list[1].name).to.be('old');
});
it('table panel should only have two thresholds values', function() {
......@@ -560,4 +560,27 @@ describe('DashboardModel', function() {
});
});
describe('When collapsing row', function(ctx) {
var dashboard;
beforeEach(function() {
dashboard = new DashboardModel({
panels: [
{id: 1, type: 'graph', gridPos: {x: 0, y: 0, w: 24, h: 2}},
{id: 2, type: 'row', gridPos: {x: 0, y: 2, w: 24, h: 2}},
{id: 3, type: 'graph', gridPos: {x: 0, y: 4, w: 12, h: 2}},
{id: 4, type: 'graph', gridPos: {x: 12, y: 4, w: 12, h: 2}},
{id: 5, type: 'row', gridPos: {x: 0, y: 6, w: 24, h: 2}},
],
});
dashboard.toggleRow(dashboard.panels[1]);
});
it('should remove panels and put them inside collapsed row', function() {
expect(dashboard.panels.length).to.eql(3);
expect(dashboard.panels[1].panels.length).to.eql(2);
});
});
});
$dashboard-row-height: 30px;
.dashboard-row {
display: flex;
height: 100%;
......@@ -31,7 +29,6 @@ $dashboard-row-height: 30px;
flex-grow: 0;
font-size: 1.15rem;
font-weight: $font-weight-semi-bold;
padding: 0rem 1rem 0.3rem 1rem;
color: $text-color;
.fa {
......@@ -53,6 +50,8 @@ $dashboard-row-height: 30px;
color: $link-hover-color;
}
}
flex-grow: 1;
}
.dashboard-row__panel_count {
......@@ -61,15 +60,12 @@ $dashboard-row-height: 30px;
font-size: $font-size-sm;
font-weight: normal;
display: none;
position: absolute;
right: 30px;
top: 0;
}
.dashboard-row__drag {
cursor: move;
width: 1rem;
height: $dashboard-row-height;
height: 100%;
background: url("../img/grab_dark.svg") no-repeat 50% 50%;
background-size: 8px;
visibility: hidden;
......
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