From 65942efb95a22e77a91d4f7d5f828e0cc376a4e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 25 Nov 2019 13:26:18 -0800 Subject: [PATCH] Panels: Add support for panels with no padding (#20012) * Panels: Added support to set panel padding to zero * WIP: fullChromeControl work * Tweaks to header position * Reverted some overlay mechanic and now back to no title only * Fixed test * Fixed transparent flag * Added show title * Added font weight to value * Reverted back to no padding option * Fixed issue with border and width and height --- devenv/datasources.yaml | 2 +- packages/grafana-data/src/types/panel.ts | 6 +++ .../src/components/BigValue/BigValue.tsx | 9 +++-- .../components/VizRepeater/VizRepeater.tsx | 23 +++++++++-- .../dashboard/dashgrid/PanelChrome.tsx | 39 ++++++++++++++++--- .../dashgrid/PanelHeader/PanelHeader.tsx | 2 - .../features/dashboard/utils/panel.test.ts | 19 ++++++++- public/app/features/dashboard/utils/panel.ts | 9 ++--- .../panel/singlestat2/SingleStatEditor.tsx | 22 ++++------- .../app/plugins/panel/singlestat2/module.tsx | 1 + public/app/plugins/panel/singlestat2/types.ts | 13 ------- public/sass/pages/_dashboard.scss | 9 +++-- 12 files changed, 100 insertions(+), 54 deletions(-) diff --git a/devenv/datasources.yaml b/devenv/datasources.yaml index 2fbab0f06da..8634382bac7 100644 --- a/devenv/datasources.yaml +++ b/devenv/datasources.yaml @@ -20,8 +20,8 @@ datasources: url: http://localhost:3011 - name: gdev-testdata - type: testdata isDefault: true + type: testdata - name: gdev-influxdb type: influxdb diff --git a/packages/grafana-data/src/types/panel.ts b/packages/grafana-data/src/types/panel.ts index 7e5df1e6307..e111224429a 100644 --- a/packages/grafana-data/src/types/panel.ts +++ b/packages/grafana-data/src/types/panel.ts @@ -74,6 +74,7 @@ export class PanelPlugin extends GrafanaPlugin defaults?: TOptions; onPanelMigration?: PanelMigrationHandler; onPanelTypeChanged?: PanelTypeChangedHandler; + noPadding?: boolean; /** * Legacy angular ctrl. If this exists it will be used instead of the panel @@ -95,6 +96,11 @@ export class PanelPlugin extends GrafanaPlugin return this; } + setNoPadding() { + this.noPadding = true; + return this; + } + /** * This function is called before the panel first loads if * the current version is different than the version that was saved. diff --git a/packages/grafana-ui/src/components/BigValue/BigValue.tsx b/packages/grafana-ui/src/components/BigValue/BigValue.tsx index a7b0cb42321..992ab74e283 100644 --- a/packages/grafana-ui/src/components/BigValue/BigValue.tsx +++ b/packages/grafana-ui/src/components/BigValue/BigValue.tsx @@ -160,7 +160,7 @@ export function calculateLayout(props: Props): LayoutResult { export function getTitleStyles(layout: LayoutResult) { const styles: CSSProperties = { fontSize: `${layout.titleFontSize}px`, - textShadow: '#333 1px 1px 5px', + textShadow: '#333 0px 0px 1px', color: '#EEE', }; @@ -175,7 +175,8 @@ export function getValueStyles(layout: LayoutResult) { const styles: CSSProperties = { fontSize: `${layout.valueFontSize}px`, color: '#EEE', - textShadow: '#333 1px 1px 5px', + textShadow: '#333 0px 0px 1px', + fontWeight: 500, lineHeight: LINE_HEIGHT, }; @@ -347,7 +348,7 @@ function renderLineGeom(layout: LayoutResult) { const lineStyle: any = { stroke: '#CCC', lineWidth: 2, - shadowBlur: 15, + shadowBlur: 10, shadowColor: '#444', shadowOffsetY: 7, }; @@ -359,7 +360,7 @@ function renderVibrant2Geom(layout: LayoutResult) { const lineStyle: any = { stroke: '#CCC', lineWidth: 2, - shadowBlur: 15, + shadowBlur: 10, shadowColor: '#444', shadowOffsetY: -5, }; diff --git a/packages/grafana-ui/src/components/VizRepeater/VizRepeater.tsx b/packages/grafana-ui/src/components/VizRepeater/VizRepeater.tsx index 597440fc6cb..ac2c4235de7 100644 --- a/packages/grafana-ui/src/components/VizRepeater/VizRepeater.tsx +++ b/packages/grafana-ui/src/components/VizRepeater/VizRepeater.tsx @@ -1,4 +1,4 @@ -import React, { PureComponent } from 'react'; +import React, { PureComponent, CSSProperties } from 'react'; import { VizOrientation } from '@grafana/data'; interface Props { @@ -87,12 +87,13 @@ export class VizRepeater extends PureComponent, State> repeaterStyle.flexDirection = 'column'; itemStyles.marginBottom = `${itemSpacing}px`; vizWidth = width; - vizHeight = height / values.length - itemSpacing; + vizHeight = height / values.length - itemSpacing + itemSpacing / values.length; } else { repeaterStyle.flexDirection = 'row'; + repeaterStyle.justifyContent = 'space-between'; itemStyles.marginRight = `${itemSpacing}px`; vizHeight = height; - vizWidth = width / values.length - itemSpacing; + vizWidth = width / values.length - itemSpacing + itemSpacing / values.length; } itemStyles.width = `${vizWidth}px`; @@ -103,7 +104,7 @@ export class VizRepeater extends PureComponent, State>
{values.map((value, index) => { return ( -
+
{renderValue(value, vizWidth, vizHeight, dims)}
); @@ -112,3 +113,17 @@ export class VizRepeater extends PureComponent, State> ); } } + +/* + * Removes any padding on the last item + */ +function getItemStylesForIndex(itemStyles: CSSProperties, index: number, length: number): CSSProperties { + if (index === length - 1) { + return { + ...itemStyles, + marginRight: 0, + marginBottom: 0, + }; + } + return itemStyles; +} diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 159a1b8e280..c36ce68157e 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -7,13 +7,14 @@ import { PanelHeader } from './PanelHeader/PanelHeader'; import { ErrorBoundary } from '@grafana/ui'; // Utils & Services import { getTimeSrv, TimeSrv } from '../services/TimeSrv'; -import { applyPanelTimeOverrides, calculateInnerPanelHeight } from 'app/features/dashboard/utils/panel'; +import { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel'; import { profiler } from 'app/core/profiler'; import { getProcessedDataFrames } from '../state/runRequest'; import templateSrv from 'app/features/templating/template_srv'; import config from 'app/core/config'; // Types import { DashboardModel, PanelModel } from '../state'; +import { PANEL_BORDER } from 'app/core/constants'; import { LoadingState, ScopedVars, @@ -260,13 +261,22 @@ export class PanelChrome extends PureComponent { } const PanelComponent = plugin.panel; - const innerPanelHeight = calculateInnerPanelHeight(panel, height); const timeRange = data.timeRange || this.timeSrv.timeRange(); + const headerHeight = this.hasOverlayHeader() ? 0 : theme.panelHeaderHeight; + const chromePadding = plugin.noPadding ? 0 : theme.panelPadding; + const panelWidth = width - chromePadding * 2 - PANEL_BORDER; + const innerPanelHeight = height - headerHeight - chromePadding * 2 - PANEL_BORDER; + + const panelContentClassNames = classNames({ + 'panel-content': true, + 'panel-content--no-padding': plugin.noPadding, + }); + return ( <> {loading === LoadingState.Loading && this.renderLoadingState()} -
+
{ timeZone={this.props.dashboard.getTimezone()} options={panel.getOptions()} transparent={panel.transparent} - width={width - theme.panelPadding * 2} + width={panelWidth} height={innerPanelHeight} renderCounter={renderCounter} replaceVariables={this.replaceVariables} @@ -294,6 +304,23 @@ export class PanelChrome extends PureComponent { ); } + hasOverlayHeader() { + const { panel } = this.props; + const { errorMessage, data } = this.state; + + // always show normal header if we have an error message + if (errorMessage) { + return false; + } + + // always show normal header if we have time override + if (data.request && data.request.timeInfo) { + return false; + } + + return !panel.hasTitle(); + } + render() { const { dashboard, panel, isFullscreen, width, height } = this.props; const { errorMessage, data } = this.state; @@ -302,8 +329,8 @@ export class PanelChrome extends PureComponent { const containerClassNames = classNames({ 'panel-container': true, 'panel-container--absolute': true, - 'panel-container--no-title': !panel.hasTitle(), - 'panel-transparent': transparent, + 'panel-container--transparent': transparent, + 'panel-container--no-title': this.hasOverlayHeader(), }); return ( diff --git a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx index b38c22408c5..06656ce614f 100644 --- a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx +++ b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx @@ -103,13 +103,11 @@ export class PanelHeader extends Component { {title} - {this.state.panelMenuOpen && ( )} - {timeInfo && ( {timeInfo} diff --git a/public/app/features/dashboard/utils/panel.test.ts b/public/app/features/dashboard/utils/panel.test.ts index 0874eaa939e..1ce0fcf5d5c 100644 --- a/public/app/features/dashboard/utils/panel.test.ts +++ b/public/app/features/dashboard/utils/panel.test.ts @@ -1,7 +1,9 @@ import { TimeRange } from '@grafana/data'; -import { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel'; +import { applyPanelTimeOverrides, calculateInnerPanelHeight } from 'app/features/dashboard/utils/panel'; import { advanceTo, clear } from 'jest-date-mock'; import { dateTime, DateTime } from '@grafana/data'; +import { PanelModel } from '../state'; +import { getPanelPlugin } from '../../plugins/__mocks__/pluginMocks'; const dashboardTimeRange: TimeRange = { from: dateTime([2019, 1, 11, 12, 0]), @@ -71,4 +73,19 @@ describe('applyPanelTimeOverrides', () => { expect((overrides.timeRange.raw.from as DateTime).toISOString()).toEqual(expectedFromDate.toISOString()); expect((overrides.timeRange.raw.to as DateTime).toISOString()).toEqual(expectedToDate.toISOString()); }); + + it('Calculate panel height', () => { + const panelModel = new PanelModel({}); + const height = calculateInnerPanelHeight(panelModel, 100); + + expect(height).toBe(82); + }); + + it('Calculate panel height with panel plugin zeroChromePadding', () => { + const panelModel = new PanelModel({}); + panelModel.pluginLoaded(getPanelPlugin({ id: 'table' }, null, null).setNoPadding()); + + const height = calculateInnerPanelHeight(panelModel, 100); + expect(height).toBe(98); + }); }); diff --git a/public/app/features/dashboard/utils/panel.ts b/public/app/features/dashboard/utils/panel.ts index a641f490d83..fe50a158c8a 100644 --- a/public/app/features/dashboard/utils/panel.ts +++ b/public/app/features/dashboard/utils/panel.ts @@ -173,10 +173,7 @@ export function getResolution(panel: PanelModel): number { } export function calculateInnerPanelHeight(panel: PanelModel, containerHeight: number): number { - return ( - containerHeight - - (panel.hasTitle() ? config.theme.panelHeaderHeight : 0) - - config.theme.panelPadding * 2 - - PANEL_BORDER - ); + const chromePadding = panel.plugin && panel.plugin.noPadding ? 0 : config.theme.panelPadding * 2; + const headerHeight = panel.hasTitle() ? config.theme.panelHeaderHeight : 0; + return containerHeight - headerHeight - chromePadding - PANEL_BORDER; } diff --git a/public/app/plugins/panel/singlestat2/SingleStatEditor.tsx b/public/app/plugins/panel/singlestat2/SingleStatEditor.tsx index 83ab33f5d4a..4e1845ab8b0 100644 --- a/public/app/plugins/panel/singlestat2/SingleStatEditor.tsx +++ b/public/app/plugins/panel/singlestat2/SingleStatEditor.tsx @@ -15,7 +15,7 @@ import { import { Threshold, ValueMapping, FieldConfig, DataLink, PanelEditorProps, FieldDisplayOptions } from '@grafana/data'; -import { SingleStatOptions, SparklineOptions, displayModes, colorModes } from './types'; +import { SingleStatOptions, SparklineOptions, displayModes } from './types'; import { SparklineEditor } from './SparklineEditor'; import { getDataLinksVariableSuggestions, @@ -52,7 +52,6 @@ export class SingleStatEditor extends PureComponent this.props.onOptionsChange({ ...this.props.options, displayMode: value }); - onColorModeChange = ({ value }: any) => this.props.onOptionsChange({ ...this.props.options, colorMode: value }); onDefaultsChange = (field: FieldConfig) => { this.onDisplayOptionsChanged({ @@ -91,21 +90,16 @@ export class SingleStatEditor extends PureComponent item.value === options.displayMode)} />
-
- Color by -