diff --git a/CHANGELOG.md b/CHANGELOG.md index 85274b2445..054caf1086 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ 1. [14059](https://github.com/influxdata/influxdb/pull/14059): Enable formatting line graph y ticks with binary prefix 1. [14052](https://github.com/influxdata/influxdb/pull/14052): Add x and y column pickers to graph types +1. [14128](https://github.com/influxdata/influxdb/pull/14128): Add option to shade area below line graphs ### Bug Fixes diff --git a/dashboard.go b/dashboard.go index 54cc2d8a06..42ea0e0275 100644 --- a/dashboard.go +++ b/dashboard.go @@ -593,6 +593,7 @@ type LinePlusSingleStatProperties struct { ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"` XColumn string `json:"xColumn"` YColumn string `json:"yColumn"` + ShadeBelow bool `json:"shadeBelow"` } // XYViewProperties represents options for line, bar, step, or stacked view in Chronograf @@ -607,6 +608,7 @@ type XYViewProperties struct { ShowNoteWhenEmpty bool `json:"showNoteWhenEmpty"` XColumn string `json:"xColumn"` YColumn string `json:"yColumn"` + ShadeBelow bool `json:"shadeBelow"` } // SingleStatViewProperties represents options for single stat view in Chronograf diff --git a/dashboard_test.go b/dashboard_test.go index bff5e514fd..50af78f9a1 100644 --- a/dashboard_test.go +++ b/dashboard_test.go @@ -45,11 +45,12 @@ func TestView_MarshalJSON(t *testing.T) { "type": "xy", "colors": null, "legend": {}, - "geom": "", + "geom": "", "note": "", - "showNoteWhenEmpty": false, - "xColumn": "", - "yColumn": "" + "showNoteWhenEmpty": false, + "xColumn": "", + "yColumn": "", + "shadeBelow": false } } `, diff --git a/ui/package-lock.json b/ui/package-lock.json index 2f30e5ad35..01f4688655 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -1030,9 +1030,9 @@ } }, "@influxdata/giraffe": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/@influxdata/giraffe/-/giraffe-0.11.1.tgz", - "integrity": "sha512-Jwpfl7shKOHgJ5S/ZAw2my8zlPh20CcfeFzGZdTZ2kdPUX+YxMTj3fOhLw6i0Ksh9qp0JMc/Mm0SUAkRYMz+wA==", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@influxdata/giraffe/-/giraffe-0.12.0.tgz", + "integrity": "sha512-sVVABC9+isYSJ9OGX0ZpDXDkOa9cIgQAAdNo6PIo8qdIeTzP6uVGWP/NM6GqjFZtfS4Hqyj1jybKAf4i+QH8yQ==", "requires": { "d3-array": "^2.0.3", "d3-color": "^1.2.3", diff --git a/ui/package.json b/ui/package.json index 0971346011..6f5ca5cfa3 100644 --- a/ui/package.json +++ b/ui/package.json @@ -143,7 +143,7 @@ "@influxdata/influx": "github:influxdata/influxdb2-js#dev", "@influxdata/influxdb-templates": "influxdata/influxdb-templates", "@influxdata/react-custom-scrollbars": "4.3.8", - "@influxdata/giraffe": "0.11.1", + "@influxdata/giraffe": "0.12.0", "axios": "^0.18.0", "babel-polyfill": "^6.26.0", "bignumber.js": "^4.0.2", diff --git a/ui/src/shared/components/Checkbox.scss b/ui/src/shared/components/Checkbox.scss new file mode 100644 index 0000000000..e0a3315829 --- /dev/null +++ b/ui/src/shared/components/Checkbox.scss @@ -0,0 +1,58 @@ +$checkbox--size: 14px; +$checkbox--dot-size: 6px; +$checkbox--h-padding: $ix-marg-c; + +.fancy-checkbox { + color: $g11-sidewalk; + font-size: 12px; + font-weight: 600; + position: relative; + padding-left: $checkbox--size + $ix-marg-b; + position: relative; + cursor: pointer; + + input { + position: absolute; + left: -9999px; + } + + &:before, + &:after { + content: ''; + position: absolute; + top: 50%; + transform: translate(-50%, -50%); + transition: background-color 0.25s ease; + } + + &:before { + left: $checkbox--size / 2; + z-index: 2; + width: $checkbox--size; + height: $checkbox--size; + background-color: $g2-kevlar; + border-radius: 3px; + } + + &:after { + left: $checkbox--size / 2; + z-index: 3; + width: $checkbox--dot-size; + height: $checkbox--dot-size; + background-color: $c-hydrogen; + transition: opacity 0.25s ease, transform 0.25s ease; + border-radius: 50%; + opacity: 0; + transform: translate(-50%, -50%) scale(1.8,1.8); + } + + &.checked { + &:before { + background-color: $c-sapphire; + } + &:after { + opacity: 1; + transform: translate(-50%, -50%) scale(1,1); + } + } +} diff --git a/ui/src/shared/components/Checkbox.tsx b/ui/src/shared/components/Checkbox.tsx new file mode 100644 index 0000000000..8607a213a5 --- /dev/null +++ b/ui/src/shared/components/Checkbox.tsx @@ -0,0 +1,26 @@ +// Libraries +import React, {FunctionComponent} from 'react' + +interface Props { + label: string + checked: boolean + onSetChecked: (checked: boolean) => void +} + +// TODO: Replace this with the Clockface checkbox once available +// +// See https://github.com/influxdata/influxdb/issues/14125. +const Checkbox: FunctionComponent = ({label, checked, onSetChecked}) => { + return ( + + ) +} + +export default Checkbox diff --git a/ui/src/shared/components/XYContainer.tsx b/ui/src/shared/components/XYContainer.tsx index edf566363f..9c44c822f9 100644 --- a/ui/src/shared/components/XYContainer.tsx +++ b/ui/src/shared/components/XYContainer.tsx @@ -43,6 +43,7 @@ const XYContainer: FunctionComponent = ({ colors, xColumn: storedXColumn, yColumn: storedYColumn, + shadeBelow, axes: { x: {label: xAxisLabel, bounds: xBounds}, y: { @@ -125,6 +126,8 @@ const XYContainer: FunctionComponent = ({ fill: groupKey, interpolation, colors: colorHexes, + shadeBelow: !!shadeBelow, + shadeBelowOpacity: 0.08, }, ], } diff --git a/ui/src/shared/utils/featureFlag.ts b/ui/src/shared/utils/featureFlag.ts index f9da158225..ffbc9ba86e 100644 --- a/ui/src/shared/utils/featureFlag.ts +++ b/ui/src/shared/utils/featureFlag.ts @@ -4,11 +4,13 @@ import {CLOUD} from 'src/shared/constants' const OSS_FLAGS = { heatmap: true, scatter: true, + lineGraphShading: true, } const CLOUD_FLAGS = { heatmap: false, // We need to ensure the API updates have been deployed before enabling scatter: false, // ditto ^^ + lineGraphShading: false, // ditto! ^^ } export const isFlagEnabled = (flagName: string) => { diff --git a/ui/src/style/chronograf.scss b/ui/src/style/chronograf.scss index 9916545567..826c61f8df 100644 --- a/ui/src/style/chronograf.scss +++ b/ui/src/style/chronograf.scss @@ -105,6 +105,7 @@ @import 'src/dataLoaders/components/DataLoadersOverlay.scss'; @import 'src/shared/components/EmptyGraphError.scss'; @import 'src/shared/components/AutoDomainInput.scss'; +@import 'src/shared/components/Checkbox.scss'; @import 'src/shared/components/dapperScrollbars/DapperScrollbars.scss'; @import 'src/templates/components/createFromTemplateOverlay/CreateFromTemplateOverlay.scss'; @import 'src/onboarding/components/SigninForm.scss'; diff --git a/ui/src/timeMachine/actions/index.ts b/ui/src/timeMachine/actions/index.ts index f0a2735cde..983d520717 100644 --- a/ui/src/timeMachine/actions/index.ts +++ b/ui/src/timeMachine/actions/index.ts @@ -71,6 +71,7 @@ export type Action = | SetXDomainAction | SetYDomainAction | SetXAxisLabelAction + | SetShadeBelowAction interface SetActiveTimeMachineAction { type: 'SET_ACTIVE_TIME_MACHINE' @@ -486,6 +487,16 @@ export const setYColumn = (yColumn: string): SetYColumnAction => ({ payload: {yColumn}, }) +interface SetShadeBelowAction { + type: 'SET_SHADE_BELOW' + payload: {shadeBelow} +} + +export const setShadeBelow = (shadeBelow: boolean): SetShadeBelowAction => ({ + type: 'SET_SHADE_BELOW', + payload: {shadeBelow}, +}) + interface SetBinSizeAction { type: 'SET_BIN_SIZE' payload: {binSize: number} diff --git a/ui/src/timeMachine/components/view_options/LineOptions.tsx b/ui/src/timeMachine/components/view_options/LineOptions.tsx index 6d36e333c8..ea20ec59e6 100644 --- a/ui/src/timeMachine/components/view_options/LineOptions.tsx +++ b/ui/src/timeMachine/components/view_options/LineOptions.tsx @@ -11,6 +11,8 @@ import ColorSelector from 'src/timeMachine/components/view_options/ColorSelector import AutoDomainInput from 'src/shared/components/AutoDomainInput' import YAxisBase from 'src/timeMachine/components/view_options/YAxisBase' import ColumnSelector from 'src/shared/components/ColumnSelector' +import Checkbox from 'src/shared/components/Checkbox' +import {FeatureFlag} from 'src/shared/utils/featureFlag' // Actions import { @@ -23,6 +25,7 @@ import { setGeom, setXColumn, setYColumn, + setShadeBelow, } from 'src/timeMachine/actions' // Utils @@ -45,6 +48,7 @@ interface OwnProps { axes: Axes geom?: XYViewGeom colors: Color[] + shadeBelow?: boolean } interface StateProps { @@ -60,6 +64,7 @@ interface DispatchProps { onUpdateYAxisBounds: typeof setYAxisBounds onUpdateYAxisBase: typeof setYAxisBase onUpdateColors: typeof setColors + onSetShadeBelow: typeof setShadeBelow onSetXColumn: typeof setXColumn onSetYColumn: typeof setYColumn onSetGeom: typeof setGeom @@ -75,11 +80,13 @@ class LineOptions extends PureComponent { }, colors, geom, + shadeBelow, onUpdateColors, onUpdateYAxisLabel, onUpdateAxisPrefix, onUpdateAxisSuffix, onUpdateYAxisBase, + onSetShadeBelow, onSetGeom, onSetYColumn, yColumn, @@ -114,6 +121,15 @@ class LineOptions extends PureComponent { colors={colors.filter(c => c.type === 'scale')} onUpdateColors={onUpdateColors} /> + + + + +
Y Axis
@@ -170,6 +186,7 @@ const mdtp: DispatchProps = { onUpdateYAxisBase: setYAxisBase, onSetXColumn: setXColumn, onSetYColumn: setYColumn, + onSetShadeBelow: setShadeBelow, onUpdateColors: setColors, onSetGeom: setGeom, } diff --git a/ui/src/timeMachine/reducers/index.ts b/ui/src/timeMachine/reducers/index.ts index 09b71e30ea..147dfa7df0 100644 --- a/ui/src/timeMachine/reducers/index.ts +++ b/ui/src/timeMachine/reducers/index.ts @@ -438,6 +438,12 @@ export const timeMachineReducer = ( return setViewProperties(state, {decimalPlaces}) } + case 'SET_SHADE_BELOW': { + const {shadeBelow} = action.payload + + return setViewProperties(state, {shadeBelow}) + } + case 'SET_BACKGROUND_THRESHOLD_COLORING': { const viewColors = state.view.properties.colors as Color[] diff --git a/ui/src/types/dashboards.ts b/ui/src/types/dashboards.ts index 21aa697ff1..67e9364ef2 100644 --- a/ui/src/types/dashboards.ts +++ b/ui/src/types/dashboards.ts @@ -116,12 +116,6 @@ export type NewView = Omit< 'id' | 'links' > -export interface ViewLinks { - self: string -} - -export type DygraphViewProperties = XYView | LinePlusSingleStatView - export type ViewProperties = | XYView | LinePlusSingleStatView @@ -173,8 +167,9 @@ export interface XYView { queries: DashboardQuery[] shape: ViewShape.ChronografV2 axes: Axes - xColumn: string - yColumn: string + xColumn?: string + yColumn?: string + shadeBelow?: boolean colors: Color[] legend: Legend note: string @@ -190,8 +185,9 @@ export interface LinePlusSingleStatView { legend: Legend prefix: string suffix: string - xColumn: string - yColumn: string + xColumn?: string + yColumn?: string + shadeBelow?: boolean decimalPlaces: DecimalPlaces note: string showNoteWhenEmpty: boolean