@influxdata/giraffe
Advanced tools
Comparing version 0.30.1 to 0.31.0
@@ -1,15 +0,4 @@ | ||
import { FunctionComponent, CSSProperties, ReactNode } from 'react'; | ||
import { FunctionComponent } from 'react'; | ||
import { StandardFunctionProps } from '../types'; | ||
import { InfluxColors } from '../constants/colorSchemes'; | ||
export interface StandardFunctionProps { | ||
/** Unique identifier for getting an element */ | ||
id?: string; | ||
/** Useful for setting common attributes like width or height */ | ||
style?: CSSProperties; | ||
/** ID for Integration Tests */ | ||
testID?: string; | ||
/** Children */ | ||
children?: ReactNode; | ||
/** Useful for overriding styles of the component and its constituent elements */ | ||
className?: string; | ||
} | ||
interface DapperScrollbarsProps extends StandardFunctionProps { | ||
@@ -16,0 +5,0 @@ /** Toggle display of tracks when no scrolling is necessary */ |
@@ -0,15 +1,17 @@ | ||
export declare const COUNT = "count"; | ||
export declare const X_MAX = "xMax"; | ||
export declare const X_MIN = "xMin"; | ||
export declare const X_MAX = "xMax"; | ||
export declare const Y_MAX = "yMax"; | ||
export declare const Y_MIN = "yMin"; | ||
export declare const Y_MAX = "yMax"; | ||
export declare const COUNT = "count"; | ||
export declare const TIME = "_time"; | ||
export declare const VALUE = "_value"; | ||
export declare const FILL = "__fill"; | ||
export declare const SYMBOL = "__symbol"; | ||
export declare const STACKED_LINE_CUMULATIVE = "cumulative"; | ||
export declare const LINE_COUNT = "lines"; | ||
export declare const SERIES = "series"; | ||
export declare const RESULT = "result"; | ||
export declare const STACKED_LINE_CUMULATIVE = "cumulative"; | ||
export declare const SYMBOL = "__symbol"; | ||
export declare const TIME = "_time"; | ||
export declare const VALUE = "_value"; | ||
export declare const LOWER = "lower"; | ||
export declare const MAX = "max"; | ||
export declare const MIN = "min"; | ||
export declare const RESULT = "result"; | ||
export declare const UPPER = "upper"; |
@@ -23,1 +23,16 @@ import { Config, LayerConfig, SymbolType } from '../types'; | ||
export declare const ALL_SYMBOL_TYPES: SymbolType[]; | ||
/**************************************************************** | ||
* Band Plot uses up to 3 "lines" of data: | ||
* upper, middle, lower | ||
* which will have the same color when shaded. | ||
* | ||
* When there are multiple bands on the same plot, | ||
* we want to contrast the bands to make them easily | ||
* distinguishable. | ||
* | ||
* Allow each band to take up 3 colors on the color scale, | ||
* even though only the first color is used. This is a simple way | ||
* to scale the band colors, and takes up the same scale with | ||
* the same number of total lines as Line Plot. | ||
*/ | ||
export declare const BAND_COLOR_SCALE_CONSTANT = 3; |
export { Plot } from './components/Plot'; | ||
export { HoverTimeProvider } from './components/hoverTime'; | ||
export { fromFlux, fromFluxWithSchema, FromFluxResult } from './utils/fromFlux'; | ||
@@ -11,2 +12,3 @@ export { fromRows } from './utils/fromRows'; | ||
export * from './constants/gaugeStyles'; | ||
export { ColumnData, ColumnType, Config, DomainLabel, Formatter, GaugeTheme, GaugeLayerConfig, HistogramLayerConfig, HistogramPosition, LayerConfig, LayerTypes, LineInterpolation, LineLayerConfig, LinePosition, Margins, NumericColumnData, RawFluxDataTableLayerConfig, Scale, Schema, SchemaValues, SingleStatLayerConfig, Table, Tag, } from './types'; | ||
export { DEFAULT_TABLE_COLORS } from './constants/tableGraph'; | ||
export { BandLayerConfig, ColumnData, ColumnType, Config, DomainLabel, Formatter, GaugeTheme, GaugeLayerConfig, HistogramLayerConfig, HistogramPosition, LayerConfig, LayerTypes, LineInterpolation, LineLayerConfig, LinePosition, Margins, NumericColumnData, RawFluxDataTableLayerConfig, Scale, Schema, SchemaValues, SingleStatLayerConfig, Table, Tag, } from './types'; |
import { BandLayerSpec, Band, ColumnGroupMap, LineData, Table, BandIndexMap } from '../types'; | ||
export declare const getBands: (fill: ColumnGroupMap, lineData: LineData, bandFillColors: string[]) => Band[]; | ||
export declare const getBandIndexMap: (fillColumnMap: ColumnGroupMap) => BandIndexMap; | ||
export declare const groupLineIndicesIntoBands: (fill: ColumnGroupMap) => {}; | ||
export declare const getBandName: (fillColumnMap: ColumnGroupMap) => string; | ||
export declare const getBands: (fill: ColumnGroupMap, lineData: LineData, fillScale: Function, lowerColumnName: string, rowColumnName: string, upperColumnName: string) => Band[]; | ||
export declare const getBandIndexMap: (fillColumnMap: ColumnGroupMap, lowerColumnName: string, rowColumnName: string, upperColumnName: string) => BandIndexMap; | ||
export declare const groupLineIndicesIntoBands: (fill: ColumnGroupMap, lowerColumnName: string, rowColumnName: string, upperColumnName: string) => {}; | ||
export declare const alignMinMaxWithBand: (lineData: LineData, bandIndexMap: BandIndexMap) => LineData; | ||
export declare const bandTransform: (inputTable: Table, xColumnKey: string, yColumnKey: string, fillColKeys: string[], colors: string[]) => BandLayerSpec; | ||
export declare const bandTransform: (inputTable: Table, xColumnKey: string, yColumnKey: string, fillColKeys: string[], colors: string[], lowerColumnName: string, rowColumnName: string, upperColumnName: string) => BandLayerSpec; |
@@ -1,3 +0,4 @@ | ||
/// <reference types="react" /> | ||
import CSS from 'csstype'; | ||
import { CSSProperties, ReactNode } from 'react'; | ||
import { TimeZone } from './timeZones'; | ||
export declare type SizedConfig = Config & { | ||
@@ -83,5 +84,6 @@ width: number; | ||
Scatter = "scatter", | ||
Mosaic = "mosaic" | ||
Mosaic = "mosaic", | ||
Table = "table" | ||
} | ||
export declare type LayerConfig = CustomLayerConfig | RawFluxDataTableLayerConfig | GaugeLayerConfig | SingleStatLayerConfig | HeatmapLayerConfig | HistogramLayerConfig | LineLayerConfig | BandLayerConfig | ScatterLayerConfig | MosaicLayerConfig; | ||
export declare type LayerConfig = CustomLayerConfig | RawFluxDataTableLayerConfig | GaugeLayerConfig | SingleStatLayerConfig | HeatmapLayerConfig | HistogramLayerConfig | LineLayerConfig | BandLayerConfig | ScatterLayerConfig | MosaicLayerConfig | TableGraphLayerConfig; | ||
export interface CustomLayerConfig { | ||
@@ -121,3 +123,3 @@ type: 'custom'; | ||
gaugeSize?: number; | ||
theme?: GaugeTheme; | ||
gaugeTheme?: GaugeTheme; | ||
} | ||
@@ -227,2 +229,3 @@ export interface GaugeTheme { | ||
shadeOpacity?: number; | ||
name: string; | ||
upperColumnName?: string; | ||
@@ -239,2 +242,9 @@ lowerColumnName?: string; | ||
} | ||
export interface TableGraphLayerConfig { | ||
type: 'table'; | ||
tables?: FluxTable[]; | ||
timeZone: TimeZone; | ||
tableTheme?: Theme; | ||
properties: TableViewProperties; | ||
} | ||
export interface FluxTable { | ||
@@ -252,2 +262,84 @@ id: string; | ||
} | ||
export interface DashboardQuery { | ||
text?: string; | ||
editMode?: QueryEditMode; | ||
name?: string; | ||
builderConfig?: BuilderConfig; | ||
} | ||
export declare type QueryEditMode = 'builder' | 'advanced'; | ||
export interface BuilderConfig { | ||
buckets?: string[]; | ||
tags?: BuilderTagsType[]; | ||
functions?: BuilderFunctionsType[]; | ||
aggregateWindow?: { | ||
period?: string; | ||
}; | ||
} | ||
export interface BuilderTagsType { | ||
key?: string; | ||
values?: string[]; | ||
aggregateFunctionType?: BuilderAggregateFunctionType; | ||
} | ||
export declare type BuilderAggregateFunctionType = 'filter' | 'group'; | ||
export interface BuilderFunctionsType { | ||
name?: string; | ||
} | ||
export interface RenamableField { | ||
readonly internalName?: string; | ||
displayName?: string; | ||
visible?: boolean; | ||
} | ||
export * from './timeZones'; | ||
export declare type Theme = 'light' | 'dark'; | ||
export interface TableViewProperties { | ||
type?: string; | ||
shape?: string; | ||
note?: string; | ||
showNoteWhenEmpty?: boolean; | ||
queries?: DashboardQuery[]; | ||
colors: Color[]; | ||
tableOptions: { | ||
wrapping?: 'truncate' | 'wrap' | 'single-line'; | ||
fixFirstColumn?: boolean; | ||
verticalTimeAxis?: boolean; | ||
sortBy?: RenamableField; | ||
}; | ||
fieldOptions: RenamableField[]; | ||
timeFormat: string; | ||
decimalPlaces: DecimalPlaces; | ||
} | ||
export interface ColumnWidths { | ||
totalWidths: number; | ||
widths: { | ||
[x: string]: number; | ||
}; | ||
} | ||
export interface TransformTableDataReturnType { | ||
transformedData: string[][]; | ||
sortedTimeVals: string[]; | ||
columnWidths: ColumnWidths; | ||
resolvedRenamableFields: RenamableField[]; | ||
sortOptions: SortOptions; | ||
} | ||
export interface SortOptions { | ||
field: string; | ||
direction: string; | ||
} | ||
export interface TimeField { | ||
internalName: string; | ||
displayName: string; | ||
visible: boolean; | ||
} | ||
export interface FluxTable { | ||
id: string; | ||
name: string; | ||
data: string[][]; | ||
result: string; | ||
groupKey: { | ||
[columnName: string]: string; | ||
}; | ||
dataTypes: { | ||
[columnName: string]: string; | ||
}; | ||
} | ||
export declare type LayerSpec = LineLayerSpec | BandLayerSpec | ScatterLayerSpec | RectLayerSpec | MosaicLayerSpec; | ||
@@ -259,3 +351,4 @@ export declare enum SpecTypes { | ||
Rect = "rect", | ||
Mosaic = "mosaic" | ||
Mosaic = "mosaic", | ||
Table = "table" | ||
} | ||
@@ -300,3 +393,2 @@ export interface MosaicLayerSpec { | ||
type: 'band'; | ||
bandFillColors: string[]; | ||
bandIndexMap: BandIndexMap; | ||
@@ -441,4 +533,4 @@ bandName: string; | ||
lineName: string; | ||
min: BandBorder; | ||
max: BandBorder; | ||
lower: BandBorder; | ||
upper: BandBorder; | ||
xs: Array<number>; | ||
@@ -450,4 +542,4 @@ ys: Array<number>; | ||
rowIndices: number[]; | ||
minIndices: number[]; | ||
maxIndices: number[]; | ||
lowerIndices: number[]; | ||
upperIndices: number[]; | ||
} | ||
@@ -465,1 +557,8 @@ export interface Tag { | ||
} | ||
export interface StandardFunctionProps { | ||
id?: string; | ||
style?: CSSProperties; | ||
testID?: string; | ||
children?: ReactNode; | ||
className?: string; | ||
} |
import { ColumnGroupMap, LineData, LineInterpolation } from '../types'; | ||
interface DrawBandsOptions { | ||
bandFillColors: string[]; | ||
context: CanvasRenderingContext2D; | ||
fill: ColumnGroupMap; | ||
fillScale: Function; | ||
interpolation: LineInterpolation; | ||
@@ -10,5 +10,8 @@ lineData: LineData; | ||
lineOpacity: number; | ||
lowerColumnName: string; | ||
rowColumnName: string; | ||
shadeOpacity: number; | ||
upperColumnName: string; | ||
} | ||
export declare const drawBands: ({ bandFillColors, context, fill, interpolation, lineData, lineWidth, lineOpacity, shadeOpacity, }: DrawBandsOptions) => void; | ||
export declare const drawBands: ({ context, fill, fillScale, interpolation, lineData, lineWidth, lineOpacity, lowerColumnName, rowColumnName, shadeOpacity, upperColumnName, }: DrawBandsOptions) => void; | ||
export {}; |
import { NumericColumnData, BandIndexMap, LineData } from '../types'; | ||
interface MinMaxOfBands { | ||
interface BandBoundaries { | ||
[index: string]: { | ||
maxCol: number; | ||
minCol: number; | ||
maxIndex: number; | ||
minIndex: number; | ||
upperCol: number; | ||
lowerCol: number; | ||
upperIndex: number; | ||
lowerIndex: number; | ||
}; | ||
@@ -18,8 +18,8 @@ } | ||
rowIndices: number[]; | ||
minIndices: number[]; | ||
maxIndices: number[]; | ||
lowerIndices: number[]; | ||
upperIndices: number[]; | ||
} | ||
export declare const getMinMaxOfBands: (hoverRowIndices: number[], hoverGroupData: NumericColumnData, bandLineIndexMap: object) => MinMaxOfBands; | ||
export declare const getBandBoundaries: (hoverRowIndices: number[], hoverGroupData: NumericColumnData, bandLineIndexMap: object) => BandBoundaries; | ||
export declare const getLineLengths: (lineData: LineData) => LineLengths; | ||
export declare const getBandHoverIndices: (lineLengths: LineLengths, hoverRowIndices: number[], hoverGroupData: NumericColumnData, minMaxOfBands: MinMaxOfBands) => BandIndexMap; | ||
export declare const getBandHoverIndices: (lineLengths: LineLengths, hoverRowIndices: number[], hoverGroupData: NumericColumnData, bandBoundaries: BandBoundaries) => BandIndexMap; | ||
export {}; |
import { Table, Scale } from '../types'; | ||
export declare const getBandHoverPoints: (table: Table, hoverRowIndices: number[], xColKey: string, yColKey: string, xScale: Scale<number, number>, yScale: Scale<number, number>, fillColors: string[]) => { | ||
export declare const getBandHoverPoints: (table: Table, hoverRowIndices: number[], xColKey: string, yColKey: string, xScale: Scale<number, number>, yScale: Scale<number, number>, fillScale: Function) => { | ||
x: number; | ||
@@ -4,0 +4,0 @@ y: number; |
@@ -5,2 +5,2 @@ import { LinePosition, LineData, TooltipData, Scale, Table } from '../types'; | ||
export declare const getPointsTooltipData: (hoveredRowIndices: number[], table: Table, xColKey: string, yColKey: string, groupColKey: string, getValueFormatter: (colKey: string) => (x: any) => string, fillColKeys: string[], fillScale: Scale<number, string>, position?: LinePosition, lineData?: LineData) => TooltipData; | ||
export declare const getBandTooltipData: (bandHoverIndices: BandHoverIndices, table: Table, xColKey: string, yColKey: string, bandName: string, getValueFormatter: (colKey: string) => (x: any) => string, fillColKeys: string[], colors: string[], position?: LinePosition, lineData?: LineData) => TooltipData; | ||
export declare const getBandTooltipData: (bandHoverIndices: BandHoverIndices, table: Table, xColKey: string, yColKey: string, bandName: string, lowerColumnName: string, upperColumnName: string, getValueFormatter: (colKey: string) => (x: any) => string, fillColKeys: string[], colors: string[], lineData: LineData) => TooltipData; |
{ | ||
"name": "@influxdata/giraffe", | ||
"version": "0.30.1", | ||
"version": "0.31.0", | ||
"main": "dist/index.js", | ||
@@ -18,2 +18,3 @@ "license": "MIT", | ||
"data", | ||
"gauge", | ||
"giraffe", | ||
@@ -30,2 +31,3 @@ "graph", | ||
"stat", | ||
"table", | ||
"time series", | ||
@@ -51,2 +53,3 @@ "timescale", | ||
"@typescript-eslint/parser": "^2.10.0", | ||
"chroma-js": "^1.3.6", | ||
"classnames": "^2.2.3", | ||
@@ -86,2 +89,3 @@ "d3-array": "^2.0.3", | ||
"unraw": "2.0.0", | ||
"uuid": "^3.2.1", | ||
"version-bump-prompt": "^5.0.0" | ||
@@ -88,0 +92,0 @@ }, |
@@ -327,2 +327,36 @@ # Giraffe | ||
- **BandLayerConfig**: _Object_. Maximum one per `<Plot>`. Properties are: | ||
- **type**: _"band". **Required**_. Specifies that this LayerConfig and `<Plot>` is a band chart. | ||
- **x**: _string. **Required**_. The column key name of the column that should be visualized on the x-axis. | ||
- **y**: _string. **Required**_. The column key name of the column that should be visualized on the y-axis. | ||
- **fill**: _array[string, ...]. Optional._ An array of column key names of column filters that should be visualized. If this option is not included, the data in the graph will be interpreted as belonging to a single column. | ||
- **hoverDimension**: _"x" | "y" | "xy". Optional. Defaults to "x" when not included._ Indicates whether the legend (tooltip) should display all data points along an entire axis during mouse hover. | ||
- "x" means the legend will display all data points along the y-axis that have the same x-axis value | ||
- "y" means the legend will display all data points along the x-axis that have the same y-axis value | ||
- "xy" means the legend will display for a single data point nearest the mouse | ||
- **maxTooltipRows**: _number. Optional. Defaults to 24 when not included._ The maximum number of data rows to display in the legend (tooltip). Subject to screen size limitations and is not responsive or adaptive. Scrolling not implemented. | ||
- **interpolation**: _string. Optional. Defaults to "linear" when not included._ The style of the path between two data points on the same line. For example, "linear" is a straight path between two data points. The options are [linear](https://github.com/d3/d3-shape#curveLinear), [natural](https://github.com/d3/d3-shape#curveNatural), [monotoneX](https://github.com/d3/d3-shape#curveMonotoneX), [monotoneY](https://github.com/d3/d3-shape#curveMonotoneY), [cubic](https://github.com/d3/d3-shape#curveBasis), [step](https://github.com/d3/d3-shape#curveStep), [stepBefore](https://github.com/d3/d3-shape#curveStepBefore), and [stepAfter](https://github.com/d3/d3-shape#curveStepAfter). | ||
- **lineWidth**: _number. Optional._ The [CanvasRenderingContext2D lineWidth](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineWidth) of the middle part of each band as identified by the **name** option. | ||
- **colors**: _array[string, ...]. Optional._ An array of _CSS color values_ used as a gradient to give multiple lines in the graph different colors based on the **fill** columns. | ||
- **lineOpacity**: _number. Optional._ A value between 0 and 1 inclusive for the [_CanvasRenderingContext2D globalAlpha_](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalAlpha) of the middle part of each band as identified by the **name** option. | ||
- **shadeOpacity**: _number. Optional._ A value between 0 and 1 inclusive for the [_CanvasRenderingContext2D globalAlpha_](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/globalAlpha) of the shaded sections of each band. | ||
- **name**: _string. Required._ A string indicating the name of the line for the middle part of each band. This **name** must match the result in the data. If no matching name with a result is found, that result will not be rendered. | ||
- **upperColumnName**: _string. Optional._ A string indicating the shaded portion of each band that extends above the **name**d line. | ||
- **lowerColumnName**: _string. Optional._ A string indicating the shaded portion of each band that extends below the **name**d line. | ||
- **ScatterLayerConfig**: _Object_. Maximum one per `<Plot>`. Properties are: | ||
@@ -384,7 +418,7 @@ | ||
- **RawFluxDataTableLayerConfig**: _Object_. Maximum one per `<Plot>`. Properties are: | ||
- **RawFluxDataTableLayerConfig**: _Object_. Maximum one per `<Plot>`. Uses its own property called **files** as the data to be rendered. Ignores both **tables** and **fluxResponse** from `config`. Properties are: | ||
- **type**: _'flux data table'. **Required**._ Specifies that this LayerConfig is a flux data table. | ||
- **files**: _array[string, ...]. **Required**._ An array of strings of comma separated values (CSV). Each CSV string can be taken from a Flux response or manually created. At least one string is required. The string cannot not be an empty string nor a string of only empty space(s). | ||
- **files**: _array[string, ...]. **Required. The data to be rendered**._ An array of strings of comma separated values (CSV). Each CSV string can be taken from a Flux response or manually created. At least one string is required. The string cannot not be an empty string nor a string of only empty space(s). | ||
@@ -395,2 +429,59 @@ - **disableVerticalScrolling**: _boolean. **Optional**. Recommendation: do not include. Defaults to false when excluded._ Disables the vertical scrollbar for the rendered table. | ||
- **TableGraphLayerConfig**: _Object_. Maximum one per `<Plot>`. Requires the use of a **`<HoverTimeProvider>`** component around the `<Plot>` and its parent. For example, here is how to properly wrap `<Plot>` to use render a table: | ||
<pre> | ||
<b><HoverTimeProvider></b> | ||
<div | ||
style={{ | ||
width: "calc(70vw - 20px)", | ||
height: "calc(70vh - 20px)", | ||
margin: "40px", | ||
}} | ||
> | ||
<Plot config={config} /> | ||
</div> | ||
<b></HoverTimeProvider></b> | ||
</pre> | ||
TableGraphLayerConfig uses the `fluxResponse` property from `config` as the data to be rendered. Properties are: | ||
- **type**: _'table'. **Required**._ Specifies that this LayerConfig is a table graph. | ||
- **timeZone**: _string. **Required**._ A string representing the desired time zone. Must be an [_official IANA time zone_](https://stackoverflow.com/questions/38399465/how-to-get-list-of-all-timezones-in-javascript). | ||
- **tableTheme**: _string. **Optional**. Defaults to 'dark' when excluded._ The visual theme for the table graph. Currently, the choices are 'dark' and 'light'. | ||
- **properties**: _Object. **Required**._ An object specifying additional options for the table graph. The properties are: | ||
- **colors**: _array[string, ...]. **Required**._ An array of _CSS color values_ used as a gradient to give rows in the table different colors based on their value. Low values will use colors in the lower indexes while higher values will use colors in the higher indexes. | ||
- **tableOptions**: _Object. **Required**._ Customizations for the table. | ||
- **fixFirstColumn**: _boolean. Optional. Defaults to `true` when excluded._ Determines whether the first column in the table should be hidden. | ||
- **verticalTimeAxis**: _boolean. Optional. Defaults to `true` when excluded._ `true` sets the columns for time values to display vertically with column headings at the top in a horizontal row. `false` will display columns horizontally as rows, with column headings at the left in a vertical column. Warning: when using `false`, any time-like values may cause the entire table to display incorrectly if they are not set to `visible: false` in `fieldOptions`. | ||
- **sortBy**: _Object. Optional._ An object that represents a column in the table that will be sorted in ascending order upon first rendering of the table. User actions may change the sort order and/or the selected column. The object contains the following properties: | ||
- **internalName**: _string. **Required**. Read only._ The name of the column as referenced internally by Giraffe code. | ||
- **displayName**: _string. **Required**._ The name of the column to display. | ||
- **visible**: _boolean. **Required**._ Determine whether to show the column in the table or not. **true** has no effect, as by default all columns are shown even when not represented in **fieldOptions**. **false** will hide the column. | ||
- **fieldOptions**: _array[Object, ...]. **Required**._ An array of objects that represent the columns in the table. By default all columns are shown with the internal name unless modified in this array. Each object contains the following properties: | ||
- **internalName**: _string. **Required**. Read only._ The name of the column as referenced internally by Giraffe code. | ||
- **displayName**: _string. **Required**._ The name of the column to display. | ||
- **visible**: _boolean. **Required**._ Determine whether to show the column in the table or not. **true** has no effect, as by default all columns are shown even when not represented in **fieldOptions**. **false** will hide the column. | ||
- **timeFormat**: _string. **Required**._ A string representing the date and time format for time values. The underlying formatter is [_intl-dateformat_](https://www.npmjs.com/package/intl-dateformat) which supports a subset of the ISO 8601 formats. | ||
- **decimalPlaces**: _Object. **Required**._ | ||
- **isEnforced**: _boolean. Optional. Defaults to false when not included._ Indicates whether the number of decimal places ("**digits**") will be enforced. When **isEnforced** is falsy or omitted, **digits** will be locked to 2 for stat values with a decimal and 0 for stat values that are integers, and the **digits** option will be ignored. | ||
- **digits**: _number. Optional. Defaults to 0 when not included. Maximum 10._ When **digits** is a non-integer number, the decimal portion is ignored. Represents the number of decimal places to display in the stat value. Displayed stat value is subject to rounding. | ||
- **GaugeLayerConfig**: _Object_. Maximum one per `<Plot>`. Properties are: | ||
@@ -397,0 +488,0 @@ |
// This file is automatically generated. | ||
// Please do not change this file! | ||
interface CssExports { | ||
'cf-dapper-scrollbars': string | ||
'cf-dapper-scrollbars--autohide': string | ||
@@ -5,0 +6,0 @@ 'cf-dapper-scrollbars--content': string |
// Computed column names in binned tables (heatmap, histogram) | ||
export const COUNT = 'count' | ||
export const X_MAX = 'xMax' | ||
export const X_MIN = 'xMin' | ||
export const X_MAX = 'xMax' | ||
export const Y_MAX = 'yMax' | ||
export const Y_MIN = 'yMin' | ||
export const Y_MAX = 'yMax' | ||
export const COUNT = 'count' | ||
// Computed column names mapped to group aesthetics | ||
export const TIME = '_time' | ||
export const VALUE = '_value' | ||
export const FILL = '__fill' | ||
export const SYMBOL = '__symbol' | ||
export const STACKED_LINE_CUMULATIVE = 'cumulative' | ||
export const LINE_COUNT = 'lines' | ||
export const SERIES = 'series' | ||
export const STACKED_LINE_CUMULATIVE = 'cumulative' | ||
export const SYMBOL = '__symbol' | ||
export const TIME = '_time' | ||
export const VALUE = '_value' | ||
// Band Chart's most important column key | ||
export const RESULT = 'result' | ||
export const LOWER = 'lower' | ||
export const MAX = 'max' | ||
export const MIN = 'min' | ||
export const RESULT = 'result' | ||
export const UPPER = 'upper' |
@@ -111,1 +111,17 @@ import { | ||
] | ||
/**************************************************************** | ||
* Band Plot uses up to 3 "lines" of data: | ||
* upper, middle, lower | ||
* which will have the same color when shaded. | ||
* | ||
* When there are multiple bands on the same plot, | ||
* we want to contrast the bands to make them easily | ||
* distinguishable. | ||
* | ||
* Allow each band to take up 3 colors on the color scale, | ||
* even though only the first color is used. This is a simple way | ||
* to scale the band colors, and takes up the same scale with | ||
* the same number of total lines as Line Plot. | ||
*/ | ||
export const BAND_COLOR_SCALE_CONSTANT = 3 |
// Components | ||
export {Plot} from './components/Plot' | ||
export {HoverTimeProvider} from './components/hoverTime' | ||
@@ -22,5 +23,7 @@ // Utils | ||
export * from './constants/gaugeStyles' | ||
export {DEFAULT_TABLE_COLORS} from './constants/tableGraph' | ||
// Types | ||
export { | ||
BandLayerConfig, | ||
ColumnData, | ||
@@ -27,0 +30,0 @@ ColumnType, |
@@ -58,18 +58,45 @@ import { | ||
describe('creates a map of indices by column type for all columns', () => { | ||
it('creates a map with null indices when the named columns are not found', () => { | ||
expect(getBandIndexMap(columnMap, 'lower', 'median', 'upper')).toEqual({ | ||
upperIndices: [null, null], | ||
lowerIndices: [null, null], | ||
rowIndices: [null, null], | ||
}) | ||
expect(getBandIndexMap(columnMap, '', '', '')).toEqual({ | ||
upperIndices: [null, null], | ||
lowerIndices: [null, null], | ||
rowIndices: [null, null], | ||
}) | ||
}) | ||
it('creates a map with no indices when the column map is empty', () => { | ||
expect(getBandIndexMap({columnKeys: null, mappings: null})).toEqual({ | ||
maxIndices: [], | ||
minIndices: [], | ||
expect( | ||
getBandIndexMap( | ||
{columnKeys: null, mappings: null}, | ||
'min', | ||
'mean', | ||
'max' | ||
) | ||
).toEqual({ | ||
upperIndices: [], | ||
lowerIndices: [], | ||
rowIndices: [], | ||
}) | ||
expect( | ||
getBandIndexMap({columnKeys: undefined, mappings: undefined}) | ||
getBandIndexMap( | ||
{columnKeys: undefined, mappings: undefined}, | ||
'min', | ||
'mean', | ||
'max' | ||
) | ||
).toEqual({ | ||
maxIndices: [], | ||
minIndices: [], | ||
upperIndices: [], | ||
lowerIndices: [], | ||
rowIndices: [], | ||
}) | ||
expect(getBandIndexMap({columnKeys: [], mappings: []})).toEqual({ | ||
maxIndices: [], | ||
minIndices: [], | ||
expect( | ||
getBandIndexMap({columnKeys: [], mappings: []}, 'min', 'mean', 'max') | ||
).toEqual({ | ||
upperIndices: [], | ||
lowerIndices: [], | ||
rowIndices: [], | ||
@@ -80,5 +107,5 @@ }) | ||
it('creates a map with indices that are in the same position for the same band per column type', () => { | ||
expect(getBandIndexMap(columnMap)).toEqual({ | ||
maxIndices: [0, 1], | ||
minIndices: [2, 3], | ||
expect(getBandIndexMap(columnMap, 'min', 'mean', 'max')).toEqual({ | ||
upperIndices: [0, 1], | ||
lowerIndices: [2, 3], | ||
rowIndices: [5, 4], | ||
@@ -90,18 +117,48 @@ }) | ||
describe('creates a map of unique identifiers for the bands and indices of their data', () => { | ||
it('creates indentifiers with null values when the named columns are not found', () => { | ||
expect( | ||
groupLineIndicesIntoBands(columnMap, 'lower', 'median', 'upper') | ||
).toEqual({ | ||
usage_systemcpucpu0localhost: {lower: null, upper: null, row: null}, | ||
usage_systemcpucpu1localhost: {lower: null, upper: null, row: null}, | ||
}) | ||
expect(groupLineIndicesIntoBands(columnMap, '', '', '')).toEqual({ | ||
usage_systemcpucpu0localhost: {lower: null, upper: null, row: null}, | ||
usage_systemcpucpu1localhost: {lower: null, upper: null, row: null}, | ||
}) | ||
}) | ||
it('creates no indentifiers when the column map is empty', () => { | ||
expect( | ||
groupLineIndicesIntoBands({columnKeys: null, mappings: null}) | ||
groupLineIndicesIntoBands( | ||
{columnKeys: null, mappings: null}, | ||
'min', | ||
'mean', | ||
'max' | ||
) | ||
).toEqual({}) | ||
expect( | ||
groupLineIndicesIntoBands({columnKeys: undefined, mappings: undefined}) | ||
groupLineIndicesIntoBands( | ||
{columnKeys: undefined, mappings: undefined}, | ||
'min', | ||
'mean', | ||
'max' | ||
) | ||
).toEqual({}) | ||
expect(groupLineIndicesIntoBands({columnKeys: [], mappings: []})).toEqual( | ||
{} | ||
) | ||
expect( | ||
groupLineIndicesIntoBands( | ||
{columnKeys: [], mappings: []}, | ||
'min', | ||
'mean', | ||
'max' | ||
) | ||
).toEqual({}) | ||
}) | ||
it('creates identifiers when given a column map', () => { | ||
expect(groupLineIndicesIntoBands(columnMap)).toEqual({ | ||
usage_systemcpucpu0localhost: {min: 3, max: 1, row: 4}, | ||
usage_systemcpucpu1localhost: {min: 2, max: 0, row: 5}, | ||
expect( | ||
groupLineIndicesIntoBands(columnMap, 'min', 'mean', 'max') | ||
).toEqual({ | ||
usage_systemcpucpu0localhost: {lower: 3, upper: 1, row: 4}, | ||
usage_systemcpucpu1localhost: {lower: 2, upper: 0, row: 5}, | ||
}) | ||
@@ -112,3 +169,3 @@ }) | ||
describe('creates the bands to be rendered', () => { | ||
it('creates a line with min and max when they are available in the lineData', () => { | ||
it('creates a line with lower and upper when they are available in the lineData', () => { | ||
const fill = { | ||
@@ -201,21 +258,11 @@ columnKeys: ['result', '_field', '_measurement', 'cpu', 'host'], | ||
const cyan = 'rgb(49, 192, 246)' | ||
const bandFillColors = [ | ||
cyan, | ||
'rgb(78, 145, 226)', | ||
'rgb(106, 103, 205)', | ||
'rgb(134, 70, 182)', | ||
'rgb(161, 53, 158)', | ||
'rgb(186, 54, 130)', | ||
'rgb(209, 70, 101)', | ||
'rgb(232, 95, 70)', | ||
'rgb(255, 126, 39)', | ||
] | ||
const result = getBands(fill, lineData, bandFillColors) | ||
const fillScale = () => cyan | ||
const result = getBands(fill, lineData, fillScale, 'min', 'mean', 'max') | ||
expect(Array.isArray(result)).toEqual(true) | ||
expect(result[0].fill).toEqual(cyan) | ||
expect(result[0].min).toBeDefined() | ||
expect(result[0].max).toBeDefined() | ||
expect(result[0].lower).toBeDefined() | ||
expect(result[0].upper).toBeDefined() | ||
}) | ||
it('creates a line without the min or max when corresponding min or max is missing from lineData', () => { | ||
it('creates a line without the lower or upper when corresponding lower or upper is missing from lineData', () => { | ||
const fill = { | ||
@@ -351,27 +398,28 @@ columnKeys: ['result', '_field', '_measurement', 'cpu', 'host'], | ||
const purple = 'rgb(106, 103, 205)' | ||
const bandFillColors = [ | ||
cyan, | ||
babyBlue, | ||
purple, | ||
'rgb(134, 70, 182)', | ||
'rgb(161, 53, 158)', | ||
'rgb(186, 54, 130)', | ||
'rgb(209, 70, 101)', | ||
'rgb(232, 95, 70)', | ||
'rgb(255, 126, 39)', | ||
] | ||
const result = getBands(fill, lineData, bandFillColors) | ||
const fillScale = index => { | ||
switch (index) { | ||
case 0: | ||
return cyan | ||
case 1: | ||
return babyBlue | ||
case 2: | ||
return purple | ||
default: | ||
return 'none' | ||
} | ||
} | ||
const result = getBands(fill, lineData, fillScale, 'min', 'mean', 'max') | ||
expect(Array.isArray(result)).toEqual(true) | ||
expect(result[0].fill).toEqual(cyan) | ||
expect(result[0].min).toBeUndefined() | ||
expect(result[0].max).toBeDefined() | ||
expect(result[0].lower).toBeUndefined() | ||
expect(result[0].upper).toBeDefined() | ||
expect(result[1].fill).toEqual(babyBlue) | ||
expect(result[1].min).toBeDefined() | ||
expect(result[1].max).toBeUndefined() | ||
expect(result[1].lower).toBeDefined() | ||
expect(result[1].upper).toBeUndefined() | ||
expect(result[2].fill).toEqual(purple) | ||
expect(result[2].min).toBeUndefined() | ||
expect(result[2].max).toBeUndefined() | ||
expect(result[2].lower).toBeUndefined() | ||
expect(result[2].upper).toBeUndefined() | ||
}) | ||
@@ -400,4 +448,4 @@ }) | ||
const bandIndexMap = { | ||
maxIndices: [], | ||
minIndices: [], | ||
upperIndices: [], | ||
lowerIndices: [], | ||
rowIndices: [], | ||
@@ -428,4 +476,4 @@ } | ||
const bandIndexMap = { | ||
maxIndices: [0], | ||
minIndices: [1], | ||
upperIndices: [0], | ||
lowerIndices: [1], | ||
rowIndices: [2], | ||
@@ -508,4 +556,4 @@ } | ||
const bandIndexMap = { | ||
maxIndices: [0, 1], | ||
minIndices: [2, 3], | ||
upperIndices: [0, 1], | ||
lowerIndices: [2, 3], | ||
rowIndices: [5, 4], | ||
@@ -512,0 +560,0 @@ } |
@@ -9,12 +9,17 @@ import { | ||
} from '../types' | ||
import {FILL, RESULT, MAX, MIN} from '../constants/columnKeys' | ||
import {FILL, LOWER, RESULT, UPPER} from '../constants/columnKeys' | ||
import {isDefined} from '../utils/isDefined' | ||
import {createGroupIDColumn, getNominalColorScale} from './' | ||
import {BAND_COLOR_SCALE_CONSTANT} from '../constants' | ||
export const getBands = ( | ||
fill: ColumnGroupMap, | ||
lineData: LineData, | ||
bandFillColors: string[] | ||
fillScale: Function, | ||
lowerColumnName: string, | ||
rowColumnName: string, | ||
upperColumnName: string | ||
): Band[] => { | ||
const minMaxMap = {} | ||
const lowerUpperMap = {} | ||
const {columnKeys, mappings} = fill | ||
@@ -33,18 +38,18 @@ const columnKeysWithoutResult = Array.isArray(columnKeys) | ||
}, '') | ||
if (!minMaxMap[lineName]) { | ||
minMaxMap[lineName] = {} | ||
if (!lowerUpperMap[lineName]) { | ||
lowerUpperMap[lineName] = {} | ||
} | ||
if (map[RESULT] === MAX) { | ||
if (!minMaxMap[lineName][MAX]) { | ||
minMaxMap[lineName][MAX] = lineData[index] | ||
if (map[RESULT] === upperColumnName) { | ||
if (!lowerUpperMap[lineName][upperColumnName]) { | ||
lowerUpperMap[lineName][upperColumnName] = lineData[index] | ||
} | ||
} else if (map[RESULT] === MIN) { | ||
if (!minMaxMap[lineName][MIN]) { | ||
minMaxMap[lineName][MIN] = lineData[index] | ||
} else if (map[RESULT] === lowerColumnName) { | ||
if (!lowerUpperMap[lineName][lowerColumnName]) { | ||
lowerUpperMap[lineName][lowerColumnName] = lineData[index] | ||
} | ||
} else { | ||
} else if (map[RESULT] === rowColumnName) { | ||
bandLines.push({ | ||
...lineData[index], | ||
lineName, | ||
fill: bandFillColors[bandLines.length], | ||
fill: fillScale(bandLines.length), | ||
}) | ||
@@ -56,8 +61,16 @@ } | ||
bands.forEach(band => { | ||
if (minMaxMap[band.lineName][MIN]) { | ||
band[MIN] = {...minMaxMap[band.lineName][MIN], fill: band.fill} | ||
if (band.lineName) { | ||
if (lowerUpperMap[band.lineName][lowerColumnName]) { | ||
band[LOWER] = { | ||
...lowerUpperMap[band.lineName][lowerColumnName], | ||
fill: band.fill, | ||
} | ||
} | ||
if (lowerUpperMap[band.lineName][upperColumnName]) { | ||
band[UPPER] = { | ||
...lowerUpperMap[band.lineName][upperColumnName], | ||
fill: band.fill, | ||
} | ||
} | ||
} | ||
if (minMaxMap[band.lineName][MAX]) { | ||
band[MAX] = {...minMaxMap[band.lineName][MAX], fill: band.fill} | ||
} | ||
}) | ||
@@ -68,11 +81,21 @@ return bands as Band[] | ||
export const getBandIndexMap = ( | ||
fillColumnMap: ColumnGroupMap | ||
fillColumnMap: ColumnGroupMap, | ||
lowerColumnName: string, | ||
rowColumnName: string, | ||
upperColumnName: string | ||
): BandIndexMap => { | ||
const bandIndices = { | ||
rowIndices: [], | ||
minIndices: [], | ||
maxIndices: [], | ||
lowerIndices: [], | ||
upperIndices: [], | ||
} | ||
const bands = Object.values(groupLineIndicesIntoBands(fillColumnMap)) | ||
const bands = Object.values( | ||
groupLineIndicesIntoBands( | ||
fillColumnMap, | ||
lowerColumnName, | ||
rowColumnName, | ||
upperColumnName | ||
) | ||
) | ||
@@ -82,4 +105,4 @@ if (Array.isArray(bands)) { | ||
bandIndices.rowIndices.push(isDefined(band.row) ? band.row : null) | ||
bandIndices.minIndices.push(isDefined(band.min) ? band.min : null) | ||
bandIndices.maxIndices.push(isDefined(band.max) ? band.max : null) | ||
bandIndices.lowerIndices.push(isDefined(band.lower) ? band.lower : null) | ||
bandIndices.upperIndices.push(isDefined(band.upper) ? band.upper : null) | ||
}) | ||
@@ -91,3 +114,8 @@ } | ||
export const groupLineIndicesIntoBands = (fill: ColumnGroupMap) => { | ||
export const groupLineIndicesIntoBands = ( | ||
fill: ColumnGroupMap, | ||
lowerColumnName: string, | ||
rowColumnName: string, | ||
upperColumnName: string | ||
) => { | ||
const {columnKeys, mappings} = fill | ||
@@ -106,10 +134,12 @@ const columnKeysWithoutResult = Array.isArray(columnKeys) | ||
bandLineIndexMap[lineName] = { | ||
min: null, | ||
max: null, | ||
lower: null, | ||
upper: null, | ||
row: null, | ||
} | ||
} | ||
if (line[RESULT] === MAX || line[RESULT] === MIN) { | ||
bandLineIndexMap[lineName][line[RESULT]] = index | ||
} else { | ||
if (line[RESULT] === lowerColumnName) { | ||
bandLineIndexMap[lineName][LOWER] = index | ||
} else if (line[RESULT] === upperColumnName) { | ||
bandLineIndexMap[lineName][UPPER] = index | ||
} else if (line[RESULT] === rowColumnName) { | ||
bandLineIndexMap[lineName].row = index | ||
@@ -123,14 +153,2 @@ } | ||
export const getBandName = (fillColumnMap: ColumnGroupMap): string => { | ||
if (!Array.isArray(fillColumnMap.mappings)) { | ||
return '' | ||
} | ||
return fillColumnMap.mappings.reduce((name, line) => { | ||
if (!name && line[RESULT] !== MAX && line[RESULT] !== MIN) { | ||
name = line[RESULT] | ||
} | ||
return name | ||
}, '') | ||
} | ||
export const alignMinMaxWithBand = ( | ||
@@ -140,3 +158,3 @@ lineData: LineData, | ||
): LineData => { | ||
const {rowIndices, maxIndices, minIndices} = bandIndexMap | ||
const {rowIndices, upperIndices, lowerIndices} = bandIndexMap | ||
@@ -147,30 +165,30 @@ const alignedData = {} | ||
let bandYs = [] | ||
let maxXs = [] | ||
let maxYs = [] | ||
let minXs = [] | ||
let minYs = [] | ||
let upperXs = [] | ||
let upperYs = [] | ||
let lowerXs = [] | ||
let lowerYs = [] | ||
for (let i = 0; i < rowIndices.length; i += 1) { | ||
const bandId = rowIndices[i] | ||
const maxId = maxIndices[i] | ||
const minId = minIndices[i] | ||
const upperId = upperIndices[i] | ||
const lowerId = lowerIndices[i] | ||
if (lineData[maxId]) { | ||
alignedData[maxId] = { | ||
fill: lineData[maxId].fill, | ||
if (lineData[upperId]) { | ||
alignedData[upperId] = { | ||
fill: lineData[upperId].fill, | ||
xs: [], | ||
ys: [], | ||
} | ||
maxXs = lineData[maxId].xs | ||
maxYs = lineData[maxId].ys | ||
upperXs = lineData[upperId].xs | ||
upperYs = lineData[upperId].ys | ||
} | ||
if (lineData[minId]) { | ||
alignedData[minId] = { | ||
fill: lineData[minId].fill, | ||
if (lineData[lowerId]) { | ||
alignedData[lowerId] = { | ||
fill: lineData[lowerId].fill, | ||
xs: [], | ||
ys: [], | ||
} | ||
minXs = lineData[minId].xs | ||
minYs = lineData[minId].ys | ||
lowerXs = lineData[lowerId].xs | ||
lowerYs = lineData[lowerId].ys | ||
} | ||
@@ -188,19 +206,19 @@ | ||
let bandIterator = 0 | ||
let maxIterator = 0 | ||
let minIterator = 0 | ||
let upperIterator = 0 | ||
let lowerIterator = 0 | ||
while ( | ||
bandIterator < bandXs.length || | ||
maxIterator < maxXs.length || | ||
minIterator < minXs.length | ||
upperIterator < upperXs.length || | ||
lowerIterator < lowerXs.length | ||
) { | ||
const bandTime = bandXs[bandIterator] | ||
const bandValue = bandYs[bandIterator] | ||
const maxTime = maxXs[maxIterator] | ||
const maxValue = maxYs[maxIterator] | ||
const minTime = minXs[minIterator] | ||
const minValue = minYs[minIterator] | ||
const upperTime = upperXs[upperIterator] | ||
const upperValue = upperYs[upperIterator] | ||
const lowerTime = lowerXs[lowerIterator] | ||
const lowerValue = lowerYs[lowerIterator] | ||
// 1. All three are equal | ||
if (bandTime === maxTime && bandTime === minTime) { | ||
if (bandTime === upperTime && bandTime === lowerTime) { | ||
if (isDefined(bandTime)) { | ||
@@ -211,74 +229,92 @@ alignedData[bandId].xs.push(bandTime) | ||
} | ||
if (isDefined(maxTime)) { | ||
alignedData[maxId].xs.push(maxTime) | ||
alignedData[maxId].ys.push(maxValue) | ||
maxIterator += 1 | ||
if (isDefined(upperTime)) { | ||
alignedData[upperId].xs.push(upperTime) | ||
alignedData[upperId].ys.push(upperValue) | ||
upperIterator += 1 | ||
} | ||
if (isDefined(minTime)) { | ||
alignedData[minId].xs.push(minTime) | ||
alignedData[minId].ys.push(minValue) | ||
minIterator += 1 | ||
if (isDefined(lowerTime)) { | ||
alignedData[lowerId].xs.push(lowerTime) | ||
alignedData[lowerId].ys.push(lowerValue) | ||
lowerIterator += 1 | ||
} | ||
} | ||
// 2. Min is not equal to the other two | ||
else if (bandTime === maxTime) { | ||
if (bandTime > minTime || !isDefined(bandTime)) { | ||
alignedData[bandId].xs.push(minTime) | ||
alignedData[bandId].ys.push(minValue) | ||
alignedData[maxId].xs.push(minTime) | ||
alignedData[maxId].ys.push(minValue) | ||
alignedData[minId].xs.push(minTime) | ||
alignedData[minId].ys.push(minValue) | ||
minIterator += 1 | ||
} else if (bandTime < minTime || !isDefined(minTime)) { | ||
else if (bandTime === upperTime) { | ||
if (bandTime > lowerTime || !isDefined(bandTime)) { | ||
if (isDefined(bandId)) { | ||
alignedData[bandId].xs.push(lowerTime) | ||
alignedData[bandId].ys.push(lowerValue) | ||
} | ||
if (isDefined(upperId)) { | ||
alignedData[upperId].xs.push(lowerTime) | ||
alignedData[upperId].ys.push(lowerValue) | ||
} | ||
alignedData[lowerId].xs.push(lowerTime) | ||
alignedData[lowerId].ys.push(lowerValue) | ||
lowerIterator += 1 | ||
} else if (bandTime < lowerTime || !isDefined(lowerTime)) { | ||
alignedData[bandId].xs.push(bandTime) | ||
alignedData[bandId].ys.push(bandValue) | ||
alignedData[maxId].xs.push(maxTime) | ||
alignedData[maxId].ys.push(maxValue) | ||
alignedData[minId].xs.push(bandTime) | ||
alignedData[minId].ys.push(bandValue) | ||
alignedData[upperId].xs.push(upperTime) | ||
alignedData[upperId].ys.push(upperValue) | ||
if (isDefined(lowerId)) { | ||
alignedData[lowerId].xs.push(bandTime) | ||
alignedData[lowerId].ys.push(bandValue) | ||
} | ||
bandIterator += 1 | ||
maxIterator += 1 | ||
upperIterator += 1 | ||
} | ||
} | ||
// 3. Max is not equal to the other two | ||
else if (bandTime === minTime) { | ||
if (bandTime > maxTime || !isDefined(bandTime)) { | ||
alignedData[bandId].xs.push(maxTime) | ||
alignedData[bandId].ys.push(maxValue) | ||
alignedData[minId].xs.push(maxTime) | ||
alignedData[minId].ys.push(maxValue) | ||
alignedData[maxId].xs.push(maxTime) | ||
alignedData[maxId].ys.push(maxValue) | ||
maxIterator += 1 | ||
} else if (bandTime < maxTime || !isDefined(maxTime)) { | ||
else if (bandTime === lowerTime) { | ||
if (bandTime > upperTime || !isDefined(bandTime)) { | ||
if (isDefined(bandId)) { | ||
alignedData[bandId].xs.push(upperTime) | ||
alignedData[bandId].ys.push(upperValue) | ||
} | ||
if (isDefined(lowerId)) { | ||
alignedData[lowerId].xs.push(upperTime) | ||
alignedData[lowerId].ys.push(upperValue) | ||
} | ||
alignedData[upperId].xs.push(upperTime) | ||
alignedData[upperId].ys.push(upperValue) | ||
upperIterator += 1 | ||
} else if (bandTime < upperTime || !isDefined(upperTime)) { | ||
alignedData[bandId].xs.push(bandTime) | ||
alignedData[bandId].ys.push(bandValue) | ||
alignedData[maxId].xs.push(bandTime) | ||
alignedData[maxId].ys.push(bandValue) | ||
alignedData[minId].xs.push(minTime) | ||
alignedData[minId].ys.push(minValue) | ||
if (isDefined(upperId)) { | ||
alignedData[upperId].xs.push(bandTime) | ||
alignedData[upperId].ys.push(bandValue) | ||
} | ||
alignedData[lowerId].xs.push(lowerTime) | ||
alignedData[lowerId].ys.push(lowerValue) | ||
bandIterator += 1 | ||
minIterator += 1 | ||
lowerIterator += 1 | ||
} | ||
} | ||
// 4. Band is not equal to the other two | ||
else if (maxTime === minTime) { | ||
if (maxTime > bandTime || !isDefined(maxTime)) { | ||
else if (upperTime === lowerTime) { | ||
if (upperTime > bandTime || !isDefined(upperTime)) { | ||
alignedData[bandId].xs.push(bandTime) | ||
alignedData[bandId].ys.push(bandValue) | ||
alignedData[maxId].xs.push(bandTime) | ||
alignedData[maxId].ys.push(bandValue) | ||
alignedData[minId].xs.push(bandTime) | ||
alignedData[minId].ys.push(bandValue) | ||
if (isDefined(upperId)) { | ||
alignedData[upperId].xs.push(bandTime) | ||
alignedData[upperId].ys.push(bandValue) | ||
} | ||
if (isDefined(lowerId)) { | ||
alignedData[lowerId].xs.push(bandTime) | ||
alignedData[lowerId].ys.push(bandValue) | ||
} | ||
bandIterator += 1 | ||
} else if (maxTime < bandTime || !isDefined(bandTime)) { | ||
alignedData[bandId].xs.push(maxTime) | ||
alignedData[bandId].ys.push(maxValue) | ||
alignedData[maxId].xs.push(maxTime) | ||
alignedData[maxId].ys.push(maxValue) | ||
alignedData[minId].xs.push(minTime) | ||
alignedData[minId].ys.push(minValue) | ||
maxIterator += 1 | ||
minIterator += 1 | ||
} else if (upperTime < bandTime || !isDefined(bandTime)) { | ||
if (isDefined(bandId)) { | ||
alignedData[bandId].xs.push(upperTime) | ||
alignedData[bandId].ys.push(upperValue) | ||
} | ||
alignedData[upperId].xs.push(upperTime) | ||
alignedData[upperId].ys.push(upperValue) | ||
alignedData[lowerId].xs.push(lowerTime) | ||
alignedData[lowerId].ys.push(lowerValue) | ||
upperIterator += 1 | ||
lowerIterator += 1 | ||
} | ||
@@ -289,81 +325,93 @@ } | ||
if (!isDefined(bandTime)) { | ||
if (maxTime > minTime) { | ||
alignedData[bandId].xs.push(minTime) | ||
alignedData[bandId].ys.push(minValue) | ||
alignedData[maxId].xs.push(minTime) | ||
alignedData[maxId].ys.push(minValue) | ||
alignedData[minId].xs.push(minTime) | ||
alignedData[minId].ys.push(minValue) | ||
minIterator += 1 | ||
if (upperTime > lowerTime) { | ||
if (isDefined(bandId)) { | ||
alignedData[bandId].xs.push(lowerTime) | ||
alignedData[bandId].ys.push(lowerValue) | ||
} | ||
alignedData[upperId].xs.push(lowerTime) | ||
alignedData[upperId].ys.push(lowerValue) | ||
alignedData[lowerId].xs.push(lowerTime) | ||
alignedData[lowerId].ys.push(lowerValue) | ||
lowerIterator += 1 | ||
} else { | ||
alignedData[bandId].xs.push(maxTime) | ||
alignedData[bandId].ys.push(maxValue) | ||
alignedData[maxId].xs.push(maxTime) | ||
alignedData[maxId].ys.push(maxValue) | ||
alignedData[minId].xs.push(maxTime) | ||
alignedData[minId].ys.push(maxValue) | ||
maxIterator += 1 | ||
if (isDefined(bandId)) { | ||
alignedData[bandId].xs.push(upperTime) | ||
alignedData[bandId].ys.push(upperValue) | ||
} | ||
alignedData[upperId].xs.push(upperTime) | ||
alignedData[upperId].ys.push(upperValue) | ||
alignedData[lowerId].xs.push(upperTime) | ||
alignedData[lowerId].ys.push(upperValue) | ||
upperIterator += 1 | ||
} | ||
} else if (!isDefined(maxTime)) { | ||
if (bandTime > minTime) { | ||
alignedData[bandId].xs.push(minTime) | ||
alignedData[bandId].ys.push(minValue) | ||
alignedData[maxId].xs.push(minTime) | ||
alignedData[maxId].ys.push(minValue) | ||
alignedData[minId].xs.push(minTime) | ||
alignedData[minId].ys.push(minValue) | ||
minIterator += 1 | ||
} else if (!isDefined(upperTime)) { | ||
if (bandTime > lowerTime) { | ||
alignedData[bandId].xs.push(lowerTime) | ||
alignedData[bandId].ys.push(lowerValue) | ||
if (isDefined(upperId)) { | ||
alignedData[upperId].xs.push(lowerTime) | ||
alignedData[upperId].ys.push(lowerValue) | ||
} | ||
alignedData[lowerId].xs.push(lowerTime) | ||
alignedData[lowerId].ys.push(lowerValue) | ||
lowerIterator += 1 | ||
} else { | ||
alignedData[bandId].xs.push(bandTime) | ||
alignedData[bandId].ys.push(bandValue) | ||
alignedData[maxId].xs.push(bandTime) | ||
alignedData[maxId].ys.push(bandValue) | ||
alignedData[minId].xs.push(bandTime) | ||
alignedData[minId].ys.push(bandValue) | ||
if (isDefined(upperId)) { | ||
alignedData[upperId].xs.push(bandTime) | ||
alignedData[upperId].ys.push(bandValue) | ||
} | ||
alignedData[lowerId].xs.push(bandTime) | ||
alignedData[lowerId].ys.push(bandValue) | ||
bandIterator += 1 | ||
} | ||
} else if (!isDefined(minTime)) { | ||
if (bandTime > maxTime) { | ||
alignedData[bandId].xs.push(maxTime) | ||
alignedData[bandId].ys.push(maxValue) | ||
alignedData[maxId].xs.push(maxTime) | ||
alignedData[maxId].ys.push(maxValue) | ||
alignedData[minId].xs.push(maxTime) | ||
alignedData[minId].ys.push(maxValue) | ||
maxIterator += 1 | ||
} else if (!isDefined(lowerTime)) { | ||
if (bandTime > upperTime) { | ||
alignedData[bandId].xs.push(upperTime) | ||
alignedData[bandId].ys.push(upperValue) | ||
alignedData[upperId].xs.push(upperTime) | ||
alignedData[upperId].ys.push(upperValue) | ||
if (isDefined(lowerId)) { | ||
alignedData[lowerId].xs.push(upperTime) | ||
alignedData[lowerId].ys.push(upperValue) | ||
} | ||
upperIterator += 1 | ||
} else { | ||
alignedData[bandId].xs.push(bandTime) | ||
alignedData[bandId].ys.push(bandValue) | ||
alignedData[maxId].xs.push(bandTime) | ||
alignedData[maxId].ys.push(bandValue) | ||
alignedData[minId].xs.push(bandTime) | ||
alignedData[minId].ys.push(bandValue) | ||
alignedData[upperId].xs.push(bandTime) | ||
alignedData[upperId].ys.push(bandValue) | ||
if (isDefined(lowerId)) { | ||
alignedData[lowerId].xs.push(bandTime) | ||
alignedData[lowerId].ys.push(bandValue) | ||
} | ||
bandIterator += 1 | ||
} | ||
} else { | ||
const lowest = Math.min(bandTime, maxTime, minTime) | ||
const lowest = Math.min(bandTime, upperTime, lowerTime) | ||
if (lowest === minTime) { | ||
alignedData[bandId].xs.push(minTime) | ||
alignedData[bandId].ys.push(minValue) | ||
alignedData[maxId].xs.push(minTime) | ||
alignedData[maxId].ys.push(minValue) | ||
alignedData[minId].xs.push(minTime) | ||
alignedData[minId].ys.push(minValue) | ||
minIterator += 1 | ||
} else if (lowest === maxTime) { | ||
alignedData[bandId].xs.push(maxTime) | ||
alignedData[bandId].ys.push(maxValue) | ||
alignedData[maxId].xs.push(maxTime) | ||
alignedData[maxId].ys.push(maxValue) | ||
alignedData[minId].xs.push(maxTime) | ||
alignedData[minId].ys.push(maxValue) | ||
maxIterator += 1 | ||
if (lowest === lowerTime) { | ||
alignedData[bandId].xs.push(lowerTime) | ||
alignedData[bandId].ys.push(lowerValue) | ||
alignedData[upperId].xs.push(lowerTime) | ||
alignedData[upperId].ys.push(lowerValue) | ||
alignedData[lowerId].xs.push(lowerTime) | ||
alignedData[lowerId].ys.push(lowerValue) | ||
lowerIterator += 1 | ||
} else if (lowest === upperTime) { | ||
alignedData[bandId].xs.push(upperTime) | ||
alignedData[bandId].ys.push(upperValue) | ||
alignedData[upperId].xs.push(upperTime) | ||
alignedData[upperId].ys.push(upperValue) | ||
alignedData[lowerId].xs.push(upperTime) | ||
alignedData[lowerId].ys.push(upperValue) | ||
upperIterator += 1 | ||
} else { | ||
alignedData[bandId].xs.push(bandTime) | ||
alignedData[bandId].ys.push(bandValue) | ||
alignedData[maxId].xs.push(bandTime) | ||
alignedData[maxId].ys.push(bandValue) | ||
alignedData[minId].xs.push(bandTime) | ||
alignedData[minId].ys.push(bandValue) | ||
alignedData[upperId].xs.push(bandTime) | ||
alignedData[upperId].ys.push(bandValue) | ||
alignedData[lowerId].xs.push(bandTime) | ||
alignedData[lowerId].ys.push(bandValue) | ||
bandIterator += 1 | ||
@@ -385,3 +433,6 @@ } | ||
fillColKeys: string[], | ||
colors: string[] | ||
colors: string[], | ||
lowerColumnName: string, | ||
rowColumnName: string, | ||
upperColumnName: string | ||
): BandLayerSpec => { | ||
@@ -396,3 +447,7 @@ const [fillColumn, fillColumnMap] = createGroupIDColumn( | ||
const yCol = table.getColumn(yColumnKey, 'number') | ||
const fillScale = getNominalColorScale(fillColumnMap, colors) | ||
const fillScale = range => | ||
getNominalColorScale( | ||
fillColumnMap, | ||
colors | ||
)(range * BAND_COLOR_SCALE_CONSTANT) | ||
const bandFillColors = [] | ||
@@ -427,5 +482,9 @@ const lineData: LineData = {} | ||
type: 'band', | ||
bandFillColors, | ||
bandIndexMap: getBandIndexMap(fillColumnMap), | ||
bandName: getBandName(fillColumnMap), | ||
bandIndexMap: getBandIndexMap( | ||
fillColumnMap, | ||
lowerColumnName || '', | ||
rowColumnName, | ||
upperColumnName || '' | ||
), | ||
bandName: rowColumnName, | ||
inputTable, | ||
@@ -432,0 +491,0 @@ table, |
import CSS from 'csstype' | ||
import {CSSProperties, ReactNode} from 'react' | ||
import {TimeZone} from './timeZones' | ||
@@ -140,2 +142,3 @@ export type SizedConfig = Config & {width: number; height: number} | ||
Mosaic = 'mosaic', | ||
Table = 'table', | ||
} | ||
@@ -154,2 +157,3 @@ | ||
| MosaicLayerConfig | ||
| TableGraphLayerConfig | ||
@@ -193,3 +197,3 @@ export interface CustomLayerConfig { | ||
gaugeSize?: number | ||
theme?: GaugeTheme | ||
gaugeTheme?: GaugeTheme | ||
} | ||
@@ -309,2 +313,3 @@ | ||
shadeOpacity?: number | ||
name: string | ||
upperColumnName?: string | ||
@@ -323,2 +328,10 @@ lowerColumnName?: string | ||
export interface TableGraphLayerConfig { | ||
type: 'table' // do not refactor or restrict to LayerTypes.Table | ||
tables?: FluxTable[] | ||
timeZone: TimeZone | ||
tableTheme?: Theme | ||
properties: TableViewProperties | ||
} | ||
export interface FluxTable { | ||
@@ -337,2 +350,97 @@ id: string | ||
export interface DashboardQuery { | ||
text?: string | ||
editMode?: QueryEditMode | ||
name?: string | ||
builderConfig?: BuilderConfig | ||
} | ||
export type QueryEditMode = 'builder' | 'advanced' | ||
export interface BuilderConfig { | ||
buckets?: string[] | ||
tags?: BuilderTagsType[] | ||
functions?: BuilderFunctionsType[] | ||
aggregateWindow?: { | ||
period?: string | ||
} | ||
} | ||
export interface BuilderTagsType { | ||
key?: string | ||
values?: string[] | ||
aggregateFunctionType?: BuilderAggregateFunctionType | ||
} | ||
export type BuilderAggregateFunctionType = 'filter' | 'group' | ||
export interface BuilderFunctionsType { | ||
name?: string | ||
} | ||
export interface RenamableField { | ||
readonly internalName?: string | ||
displayName?: string | ||
visible?: boolean | ||
} | ||
export * from './timeZones' | ||
export type Theme = 'light' | 'dark' | ||
export interface TableViewProperties { | ||
type?: string | ||
shape?: string | ||
note?: string | ||
showNoteWhenEmpty?: boolean | ||
queries?: DashboardQuery[] | ||
colors: Color[] | ||
tableOptions: { | ||
wrapping?: 'truncate' | 'wrap' | 'single-line' | ||
fixFirstColumn?: boolean | ||
verticalTimeAxis?: boolean | ||
sortBy?: RenamableField | ||
} | ||
fieldOptions: RenamableField[] | ||
timeFormat: string | ||
decimalPlaces: DecimalPlaces | ||
} | ||
export interface ColumnWidths { | ||
totalWidths: number | ||
widths: {[x: string]: number} | ||
} | ||
export interface TransformTableDataReturnType { | ||
transformedData: string[][] | ||
sortedTimeVals: string[] | ||
columnWidths: ColumnWidths | ||
resolvedRenamableFields: RenamableField[] | ||
sortOptions: SortOptions | ||
} | ||
export interface SortOptions { | ||
field: string | ||
direction: string | ||
} | ||
export interface TimeField { | ||
internalName: string | ||
displayName: string | ||
visible: boolean | ||
} | ||
export interface FluxTable { | ||
id: string | ||
name: string | ||
data: string[][] | ||
result: string | ||
groupKey: { | ||
[columnName: string]: string | ||
} | ||
dataTypes: { | ||
[columnName: string]: string | ||
} | ||
} | ||
/* | ||
@@ -377,2 +485,3 @@ When a user supplies a config for a layer, we derive various data from it: | ||
Mosaic = 'mosaic', | ||
Table = 'table', | ||
} | ||
@@ -418,3 +527,2 @@ | ||
type: 'band' // do not refactor or restrict to SpecTypes.Line | ||
bandFillColors: string[] | ||
bandIndexMap: BandIndexMap | ||
@@ -613,4 +721,4 @@ bandName: string | ||
lineName: string | ||
min: BandBorder | ||
max: BandBorder | ||
lower: BandBorder | ||
upper: BandBorder | ||
xs: Array<number> | ||
@@ -623,4 +731,4 @@ ys: Array<number> | ||
rowIndices: number[] | ||
minIndices: number[] | ||
maxIndices: number[] | ||
lowerIndices: number[] | ||
upperIndices: number[] | ||
} | ||
@@ -641,1 +749,9 @@ | ||
} | ||
export interface StandardFunctionProps { | ||
id?: string | ||
style?: CSSProperties | ||
testID?: string | ||
children?: ReactNode | ||
className?: string | ||
} |
@@ -6,2 +6,3 @@ import {line, curveLinear, area} from 'd3-shape' | ||
import {CURVES} from '../constants' | ||
import {LOWER, UPPER} from '../constants/columnKeys' | ||
import {isDefined} from '../utils/isDefined' | ||
@@ -12,5 +13,5 @@ | ||
interface DrawBandsOptions { | ||
bandFillColors: string[] | ||
context: CanvasRenderingContext2D | ||
fill: ColumnGroupMap | ||
fillScale: Function | ||
interpolation: LineInterpolation | ||
@@ -20,9 +21,12 @@ lineData: LineData | ||
lineOpacity: number | ||
lowerColumnName: string | ||
rowColumnName: string | ||
shadeOpacity: number | ||
upperColumnName: string | ||
} | ||
export const drawBands = ({ | ||
bandFillColors, | ||
context, | ||
fill, | ||
fillScale, | ||
interpolation, | ||
@@ -32,11 +36,22 @@ lineData, | ||
lineOpacity, | ||
lowerColumnName, | ||
rowColumnName, | ||
shadeOpacity, | ||
upperColumnName, | ||
}: DrawBandsOptions): void => { | ||
const bands = getBands(fill, lineData, bandFillColors) | ||
const bands = getBands( | ||
fill, | ||
lineData, | ||
fillScale, | ||
lowerColumnName, | ||
rowColumnName, | ||
upperColumnName | ||
) | ||
// draw shading | ||
for (const band of bands) { | ||
const {min, max} = band | ||
if (min) { | ||
const {xs: xs_min, ys: ys_min} = min | ||
const lower = band[LOWER] | ||
const upper = band[UPPER] | ||
if (lower) { | ||
const {xs: xs_min, ys: ys_min} = lower | ||
const minAreaGenerator = area<number>() | ||
@@ -51,3 +66,3 @@ .y1((i: any) => band.ys[i]) | ||
context.fillStyle = min.fill | ||
context.fillStyle = lower.fill | ||
context.globalAlpha = shadeOpacity | ||
@@ -59,4 +74,4 @@ context.beginPath() | ||
if (max) { | ||
const {xs: xs_max, ys: ys_max} = max | ||
if (upper) { | ||
const {xs: xs_max, ys: ys_max} = upper | ||
const maxAreaGenerator = area<number>() | ||
@@ -71,3 +86,3 @@ .y1((i: any) => ys_max[i]) | ||
context.fillStyle = max.fill | ||
context.fillStyle = upper.fill | ||
context.globalAlpha = shadeOpacity | ||
@@ -74,0 +89,0 @@ context.beginPath() |
@@ -1,4 +0,116 @@ | ||
import {getLineLengths} from './getBandHoverIndices' | ||
import { | ||
getLineLengths, | ||
getBandBoundaries, | ||
getBandHoverIndices, | ||
} from './getBandHoverIndices' | ||
describe('getBandHoverIndices', () => { | ||
describe('getBandHoverIndices utils', () => { | ||
describe('getBandBoundaries', () => { | ||
it('handles empty data', () => { | ||
expect(getBandBoundaries(null, [], {})).toEqual({}) | ||
expect(getBandBoundaries(null, null, {})).toEqual({}) | ||
expect(getBandBoundaries(null, null, null)).toEqual({}) | ||
expect(getBandBoundaries([], [], {})).toEqual({}) | ||
}) | ||
const hoverGroupData = [ | ||
0, | ||
0, | ||
0, | ||
1, | ||
1, | ||
1, | ||
2, | ||
2, | ||
2, | ||
3, | ||
3, | ||
3, | ||
4, | ||
4, | ||
4, | ||
5, | ||
5, | ||
5, | ||
6, | ||
6, | ||
6, | ||
7, | ||
7, | ||
7, | ||
8, | ||
8, | ||
8, | ||
] | ||
const bandLineIndexMap = { | ||
usage_systemcpucpu0localhost: { | ||
lower: 5, | ||
upper: 2, | ||
row: 6, | ||
}, | ||
usage_systemcpucpu1localhost: { | ||
lower: 4, | ||
upper: 1, | ||
row: 7, | ||
}, | ||
usage_systemcpucpu2localhost: { | ||
lower: 3, | ||
upper: 0, | ||
row: 8, | ||
}, | ||
} | ||
it('creates a map with band boundaries when the hover indices are null and other data is available', () => { | ||
const hoverRowIndices = null | ||
expect( | ||
getBandBoundaries(hoverRowIndices, hoverGroupData, bandLineIndexMap) | ||
).toEqual({ | ||
6: { | ||
upperCol: 2, | ||
lowerCol: 5, | ||
upperIndex: null, | ||
lowerIndex: null, | ||
}, | ||
7: { | ||
upperCol: 1, | ||
lowerCol: 4, | ||
upperIndex: null, | ||
lowerIndex: null, | ||
}, | ||
8: { | ||
upperCol: 0, | ||
lowerCol: 3, | ||
upperIndex: null, | ||
lowerIndex: null, | ||
}, | ||
}) | ||
}) | ||
it('creates a mpa with band boundaries when the hover indicies and other data are available', () => { | ||
const hoverRowIndices = [0, 3, 6, 9, 12, 15, 18, 21, 24] | ||
expect( | ||
getBandBoundaries(hoverRowIndices, hoverGroupData, bandLineIndexMap) | ||
).toEqual({ | ||
6: { | ||
upperCol: 2, | ||
lowerCol: 5, | ||
upperIndex: 6, | ||
lowerIndex: 15, | ||
}, | ||
7: { | ||
upperCol: 1, | ||
lowerCol: 4, | ||
upperIndex: 3, | ||
lowerIndex: 12, | ||
}, | ||
8: { | ||
upperCol: 0, | ||
lowerCol: 3, | ||
upperIndex: 0, | ||
lowerIndex: 9, | ||
}, | ||
}) | ||
}) | ||
}) | ||
describe('getLineLengths', () => { | ||
@@ -77,2 +189,45 @@ it('handles empty data', () => { | ||
}) | ||
describe('getBandHoverIndices', () => { | ||
it('can handle empty data', () => { | ||
expect(getBandHoverIndices({}, [], [], {})).toEqual({ | ||
rowIndices: [], | ||
lowerIndices: [], | ||
upperIndices: [], | ||
}) | ||
}) | ||
it('creates the band hover indices when data is available', () => { | ||
const lineLengths = { | ||
0: {length: 3, startIndex: 0}, | ||
1: {length: 3, startIndex: 3}, | ||
2: {length: 3, startIndex: 6}, | ||
3: {length: 3, startIndex: 9}, | ||
4: {length: 3, startIndex: 12}, | ||
5: {length: 3, startIndex: 15}, | ||
6: {length: 3, startIndex: 18}, | ||
7: {length: 3, startIndex: 21}, | ||
8: {length: 3, startIndex: 24}, | ||
} | ||
const hoverRowIndices = [6, 3, 0] | ||
const hoverGroupData = [8, 8, 8, 7, 7, 7, 6, 6, 6] | ||
const bandBoundaries = { | ||
6: {upperCol: 2, lowerCol: 5, upperIndex: 6, lowerIndex: 15}, | ||
7: {upperCol: 1, lowerCol: 4, upperIndex: 3, lowerIndex: 12}, | ||
8: {upperCol: 0, lowerCol: 3, upperIndex: 0, lowerIndex: 9}, | ||
} | ||
expect( | ||
getBandHoverIndices( | ||
lineLengths, | ||
hoverRowIndices, | ||
hoverGroupData, | ||
bandBoundaries | ||
) | ||
).toEqual({ | ||
rowIndices: [18, 21, 24], | ||
lowerIndices: [15, 12, 9], | ||
upperIndices: [6, 3, 0], | ||
}) | ||
}) | ||
}) | ||
}) |
import {NumericColumnData, BandIndexMap, LineData} from '../types' | ||
import {LOWER, UPPER} from '../constants/columnKeys' | ||
import {isDefined} from './isDefined' | ||
interface MinMaxOfBands { | ||
interface BandBoundaries { | ||
[index: string]: { | ||
maxCol: number | ||
minCol: number | ||
maxIndex: number | ||
minIndex: number | ||
upperCol: number | ||
lowerCol: number | ||
upperIndex: number | ||
lowerIndex: number | ||
} | ||
@@ -22,12 +23,12 @@ } | ||
rowIndices: number[] | ||
minIndices: number[] | ||
maxIndices: number[] | ||
lowerIndices: number[] | ||
upperIndices: number[] | ||
} | ||
export const getMinMaxOfBands = ( | ||
export const getBandBoundaries = ( | ||
hoverRowIndices: number[], | ||
hoverGroupData: NumericColumnData, | ||
bandLineIndexMap: object | ||
): MinMaxOfBands => { | ||
const minMaxOfBands = {} | ||
): BandBoundaries => { | ||
const bandBoundaries = {} | ||
@@ -42,25 +43,26 @@ const hoverColumnToIndexMap = {} | ||
const bands = Object.values(bandLineIndexMap) | ||
const bands = bandLineIndexMap ? Object.values(bandLineIndexMap) : [] | ||
bands.forEach(band => { | ||
minMaxOfBands[band.row] = { | ||
maxCol: null, | ||
minCol: null, | ||
maxIndex: null, | ||
minIndex: null, | ||
bandBoundaries[band.row] = { | ||
upperCol: null, | ||
lowerCol: null, | ||
upperIndex: null, | ||
lowerIndex: null, | ||
} | ||
if (isDefined(band.max)) { | ||
minMaxOfBands[band.row].maxCol = band.max | ||
if (isDefined(hoverColumnToIndexMap[band.max])) { | ||
minMaxOfBands[band.row].maxIndex = hoverColumnToIndexMap[band.max] | ||
if (isDefined(band[UPPER])) { | ||
bandBoundaries[band.row].upperCol = band[UPPER] | ||
if (isDefined(hoverColumnToIndexMap[band[UPPER]])) { | ||
bandBoundaries[band.row].upperIndex = hoverColumnToIndexMap[band[UPPER]] | ||
} | ||
} | ||
if (isDefined(band.min)) { | ||
minMaxOfBands[band.row].minCol = band.min | ||
if (isDefined(hoverColumnToIndexMap[band.min])) { | ||
minMaxOfBands[band.row].minIndex = hoverColumnToIndexMap[band.min] | ||
if (isDefined(band[LOWER])) { | ||
bandBoundaries[band.row].lowerCol = band[LOWER] | ||
if (isDefined(hoverColumnToIndexMap[band[LOWER]])) { | ||
bandBoundaries[band.row].lowerIndex = hoverColumnToIndexMap[band[LOWER]] | ||
} | ||
} | ||
}) | ||
return minMaxOfBands | ||
return bandBoundaries | ||
} | ||
@@ -94,8 +96,8 @@ | ||
hoverGroupData: NumericColumnData, | ||
minMaxOfBands: MinMaxOfBands | ||
bandBoundaries: BandBoundaries | ||
): BandIndexMap => { | ||
const bandHoverIndices = { | ||
rowIndices: [], | ||
minIndices: [], | ||
maxIndices: [], | ||
lowerIndices: [], | ||
upperIndices: [], | ||
} | ||
@@ -106,7 +108,7 @@ | ||
const columnId = hoverGroupData[index] | ||
const hoveredBandId = Object.keys(minMaxOfBands).find( | ||
const hoveredBandId = Object.keys(bandBoundaries).find( | ||
bandId => Number(bandId) === Number(columnId) | ||
) | ||
if (minMaxOfBands[hoveredBandId]) { | ||
if (bandBoundaries[hoveredBandId]) { | ||
const offset = index % lineLengths[hoveredBandId].length | ||
@@ -116,4 +118,8 @@ const rowBase = lineLengths[hoveredBandId].startIndex | ||
bandHoverIndices.rowIndices.push(rowBase + offset) | ||
bandHoverIndices.maxIndices.push(minMaxOfBands[hoveredBandId].maxIndex) | ||
bandHoverIndices.minIndices.push(minMaxOfBands[hoveredBandId].minIndex) | ||
bandHoverIndices.upperIndices.push( | ||
bandBoundaries[hoveredBandId].upperIndex | ||
) | ||
bandHoverIndices.lowerIndices.push( | ||
bandBoundaries[hoveredBandId].lowerIndex | ||
) | ||
} | ||
@@ -120,0 +126,0 @@ }) |
@@ -10,3 +10,3 @@ import {Table, Scale} from '../types' | ||
yScale: Scale<number, number>, | ||
fillColors: string[] | ||
fillScale: Function | ||
): Array<{x: number; y: number; fill: string}> => { | ||
@@ -19,4 +19,4 @@ const xColData = table.getColumn(xColKey, 'number') | ||
y: yScale(yColData[hoverIndex]), | ||
fill: fillColors[index], | ||
fill: fillScale(index), | ||
})) | ||
} |
@@ -269,3 +269,6 @@ import {newTableFromConfig} from './newTable' | ||
layerConfig.fill, | ||
layerConfig.colors | ||
layerConfig.colors, | ||
layerConfig.lowerColumnName, | ||
layerConfig.name, | ||
layerConfig.upperColumnName | ||
) | ||
@@ -334,2 +337,3 @@ } | ||
case LayerTypes.SingleStat: | ||
case LayerTypes.Table: | ||
return null | ||
@@ -336,0 +340,0 @@ |
@@ -225,12 +225,13 @@ import { | ||
bandName: string, | ||
lowerColumnName: string, | ||
upperColumnName: string, | ||
getValueFormatter: (colKey: string) => (x: any) => string, | ||
fillColKeys: string[], | ||
colors: string[], | ||
position?: LinePosition, | ||
lineData?: LineData | ||
lineData: LineData | ||
): TooltipData => { | ||
const { | ||
rowIndices: hoveredRowIndices, | ||
minIndices, | ||
maxIndices, | ||
lowerIndices, | ||
upperIndices, | ||
} = bandHoverIndices | ||
@@ -243,10 +244,10 @@ | ||
const sortOrder = lineData | ||
? getDataSortOrder(lineData, hoveredRowIndices, position) | ||
? getDataSortOrder(lineData, hoveredRowIndices, null) | ||
: hoveredRowIndices | ||
const minOrder = lineData | ||
? getDataSortOrder(lineData, minIndices, position) | ||
: minIndices | ||
? getDataSortOrder(lineData, lowerIndices, null) | ||
: lowerIndices | ||
const maxOrder = lineData | ||
? getDataSortOrder(lineData, maxIndices, position) | ||
: maxIndices | ||
? getDataSortOrder(lineData, upperIndices, null) | ||
: upperIndices | ||
const xColData = table.getColumn(xColKey, 'number') | ||
@@ -280,49 +281,57 @@ const yColData = table.getColumn(yColKey, 'number') | ||
if (yColKey === VALUE) { | ||
tooltipAdditionalColumns.push({ | ||
key: yColKey, | ||
name: `${yColKey}:min`, | ||
type: table.getColumnType(yColKey), | ||
colors, | ||
values: orderDataByValue( | ||
minIndices, | ||
minOrder, | ||
minIndices.map(i => yFormatter(yColData[i])) | ||
), | ||
}) | ||
if (lowerColumnName) { | ||
tooltipAdditionalColumns.push({ | ||
key: yColKey, | ||
name: `${yColKey}:${lowerColumnName}`, | ||
type: table.getColumnType(yColKey), | ||
colors, | ||
values: orderDataByValue( | ||
lowerIndices, | ||
minOrder, | ||
lowerIndices.map(i => yFormatter(yColData[i])) | ||
), | ||
}) | ||
} | ||
tooltipAdditionalColumns.push({ | ||
key: yColKey, | ||
name: `${yColKey}:max`, | ||
type: table.getColumnType(yColKey), | ||
colors, | ||
values: orderDataByValue( | ||
maxIndices, | ||
maxOrder, | ||
maxIndices.map(i => yFormatter(yColData[i])) | ||
), | ||
}) | ||
if (upperColumnName) { | ||
tooltipAdditionalColumns.push({ | ||
key: yColKey, | ||
name: `${yColKey}:${upperColumnName}`, | ||
type: table.getColumnType(yColKey), | ||
colors, | ||
values: orderDataByValue( | ||
upperIndices, | ||
maxOrder, | ||
upperIndices.map(i => yFormatter(yColData[i])) | ||
), | ||
}) | ||
} | ||
} else { | ||
tooltipAdditionalColumns.push({ | ||
key: xColKey, | ||
name: `${xColKey}:min`, | ||
type: table.getColumnType(xColKey), | ||
colors, | ||
values: orderDataByValue( | ||
minIndices, | ||
minOrder, | ||
minIndices.map(i => xFormatter(xColData[i])) | ||
), | ||
}) | ||
if (lowerColumnName) { | ||
tooltipAdditionalColumns.push({ | ||
key: xColKey, | ||
name: `${xColKey}:${lowerColumnName}`, | ||
type: table.getColumnType(xColKey), | ||
colors, | ||
values: orderDataByValue( | ||
lowerIndices, | ||
minOrder, | ||
lowerIndices.map(i => xFormatter(xColData[i])) | ||
), | ||
}) | ||
} | ||
tooltipAdditionalColumns.push({ | ||
key: xColKey, | ||
name: `${xColKey}:max`, | ||
type: table.getColumnType(xColKey), | ||
colors, | ||
values: orderDataByValue( | ||
maxIndices, | ||
maxOrder, | ||
maxIndices.map(i => xFormatter(xColData[i])) | ||
), | ||
}) | ||
if (upperColumnName) { | ||
tooltipAdditionalColumns.push({ | ||
key: xColKey, | ||
name: `${xColKey}:${upperColumnName}`, | ||
type: table.getColumnType(xColKey), | ||
colors, | ||
values: orderDataByValue( | ||
upperIndices, | ||
maxOrder, | ||
upperIndices.map(i => xFormatter(xColData[i])) | ||
), | ||
}) | ||
} | ||
} | ||
@@ -329,0 +338,0 @@ |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 4 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
4537830
312
23161
625
52
78
9