From d3c1f6c31a0c43abfdb874d5c3636b2f7235b219 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Wed, 22 Feb 2017 09:36:48 -0600 Subject: [PATCH] WIP persist dashboard position to server --- ui/src/dashboards/apis/index.js | 8 +++++ ui/src/dashboards/components/Dashboard.js | 24 +++++--------- ui/src/dashboards/containers/DashboardPage.js | 22 ++++++++----- ui/src/shared/components/LayoutRenderer.js | 31 +++++++++++++------ 4 files changed, 52 insertions(+), 33 deletions(-) diff --git a/ui/src/dashboards/apis/index.js b/ui/src/dashboards/apis/index.js index f0106f76bb..5e0a97d024 100644 --- a/ui/src/dashboards/apis/index.js +++ b/ui/src/dashboards/apis/index.js @@ -6,3 +6,11 @@ export function getDashboards() { url: `/chronograf/v1/dashboards`, }); } + +export function updateDashboardPosition(dashboard) { + return AJAX({ + method: 'PUT', + url: dashboard.links.self, + data: dashboard, + }); +} diff --git a/ui/src/dashboards/components/Dashboard.js b/ui/src/dashboards/components/Dashboard.js index d2afb9d6c4..678a03fcdf 100644 --- a/ui/src/dashboards/components/Dashboard.js +++ b/ui/src/dashboards/components/Dashboard.js @@ -8,6 +8,7 @@ const Dashboard = ({ dashboard, isEditMode, inPresentationMode, + onPositionChange, source, timeRange, }) => { @@ -19,29 +20,17 @@ const Dashboard = ({
{isEditMode ? : null} - {Dashboard.renderDashboard(dashboard, timeRange, source)} + {Dashboard.renderDashboard(dashboard, timeRange, source, onPositionChange)}
) } -Dashboard.renderDashboard = (dashboard, timeRange, source) => { +Dashboard.renderDashboard = (dashboard, timeRange, source, onPositionChange) => { const autoRefreshMs = 15000 - const cellWidth = 4 - const cellHeight = 4 - const pageWidth = 12 - const cells = dashboard.cells.map((cell, i) => { - const cellCount = i + 1; - const cellConversion = { - w: cellWidth, - h: cellHeight, - x: (cellCount * cellWidth % pageWidth), - y: Math.floor(cellCount * cellWidth / pageWidth) * cellHeight, - i: i.toString(), - } - - const dashboardCell = {...cell, ...cellConversion} + i = `${i}` + const dashboardCell = {...cell, i} dashboardCell.queries.forEach((q) => { q.text = q.query; q.database = source.telegraf; @@ -55,12 +44,14 @@ Dashboard.renderDashboard = (dashboard, timeRange, source) => { cells={cells} autoRefreshMs={autoRefreshMs} source={source.links.proxy} + onPositionChange={onPositionChange} /> ) } const { bool, + func, shape, string, } = PropTypes @@ -69,6 +60,7 @@ Dashboard.propTypes = { dashboard: shape({}).isRequired, isEditMode: bool, inPresentationMode: bool, + onPositionChange: func, source: shape({ links: shape({ proxy: string, diff --git a/ui/src/dashboards/containers/DashboardPage.js b/ui/src/dashboards/containers/DashboardPage.js index 077968ec83..a25dca2d67 100644 --- a/ui/src/dashboards/containers/DashboardPage.js +++ b/ui/src/dashboards/containers/DashboardPage.js @@ -1,14 +1,15 @@ -import React, {PropTypes} from 'react'; -import {Link} from 'react-router'; +import React, {PropTypes} from 'react' +import {Link} from 'react-router' import {connect} from 'react-redux' -import {bindActionCreators} from 'redux'; +import {bindActionCreators} from 'redux' -import Header from 'src/dashboards/components/DashboardHeader'; -import EditHeader from 'src/dashboards/components/DashboardHeaderEdit'; -import Dashboard from 'src/dashboards/components/Dashboard'; -import timeRanges from 'hson!../../shared/data/timeRanges.hson'; +import Header from 'src/dashboards/components/DashboardHeader' +import EditHeader from 'src/dashboards/components/DashboardHeaderEdit' +import Dashboard from 'src/dashboards/components/Dashboard' +import timeRanges from 'hson!../../shared/data/timeRanges.hson' -import * as dashboardActionCreators from 'src/dashboards/actions'; +import {updateDashboardPosition} from 'src/dashboards/apis' +import * as dashboardActionCreators from 'src/dashboards/actions' import {presentationButtonDispatcher} from 'shared/dispatchers' @@ -86,6 +87,10 @@ const DashboardPage = React.createClass({ this.props.dashboardActions.setTimeRange(timeRange) }, + handleUpdatePosition(cells) { + updateDashboardPosition({...this.props.dashboard, cells}) + }, + render() { const { dashboards, @@ -129,6 +134,7 @@ const DashboardPage = React.createClass({ inPresentationMode={inPresentationMode} source={source} timeRange={timeRange} + onPositionChange={this.handleUpdatePosition} /> ); diff --git a/ui/src/shared/components/LayoutRenderer.js b/ui/src/shared/components/LayoutRenderer.js index 5b49a71427..4d3fb55d22 100644 --- a/ui/src/shared/components/LayoutRenderer.js +++ b/ui/src/shared/components/LayoutRenderer.js @@ -10,8 +10,8 @@ const RefreshingLineGraph = AutoRefresh(LineGraph); const RefreshingSingleStat = AutoRefresh(SingleStat); const { - children, arrayOf, + func, node, number, shape, @@ -51,6 +51,7 @@ export const LayoutRenderer = React.createClass({ autoRefreshMs: number.isRequired, host: string, source: string, + onPositionChange: func, }, getInitialState() { @@ -121,6 +122,17 @@ export const LayoutRenderer = React.createClass({ }); }, + handleLayoutChange(layout) { + this.triggerWindowResize() + const newCells = this.props.cells.map((cell) => { + const l = layout.find((ly) => ly.i === cell.i) + const newLayout = {x: l.x, y: l.y, h: l.h, w: l.w} + return {...cell, ...newLayout} + }) + + this.props.onPositionChange(newCells) + }, + render() { const layoutMargin = 4; return ( @@ -131,19 +143,20 @@ export const LayoutRenderer = React.createClass({ margin={[layoutMargin, layoutMargin]} containerPadding={[0, 0]} useCSSTransforms={false} - onResize={triggerWindowResize} - onLayoutChange={triggerWindowResize} + onResize={this.triggerWindowResize} + onLayoutChange={this.handleLayoutChange} > {this.generateVisualizations()} ); + }, - function triggerWindowResize() { - // Hack to get dygraphs to fit properly during and after resize (dispatchEvent is a global method on window). - const evt = document.createEvent('CustomEvent'); // MUST be 'CustomEvent' - evt.initCustomEvent('resize', false, false, null); - dispatchEvent(evt); - } + + triggerWindowResize() { + // Hack to get dygraphs to fit properly during and after resize (dispatchEvent is a global method on window). + const evt = document.createEvent('CustomEvent'); // MUST be 'CustomEvent' + evt.initCustomEvent('resize', false, false, null); + dispatchEvent(evt); }, });