Skip to content

Commit

Permalink
fix: removed bar grouping feature
Browse files Browse the repository at this point in the history
  • Loading branch information
Sciator committed Feb 10, 2021
1 parent 495bb71 commit 7a1e0f4
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 191 deletions.
18 changes: 7 additions & 11 deletions giraffe/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -669,15 +669,9 @@ TableGraphLayerConfig uses the `fluxResponse` property from `config` as the data

All values (excluding **type**) are Optional and their defaults is defined by theme `GAUGE_MINI_THEME_BULLET_DARK`

- **type**: _'gauge mini'. **Required**._ Specifies that this LayerConfig is a gauge mini layer.
gauge mini creates one bar per unique __field_ value

- **barsDefinitions** _{groupByColumns; bars;}_ _(types of properties based on selected style)_
- Object style:
- **groupByColumns** _{ [key: string]: true }_ bar for each unique combination of given columns values. _(example: `{cpu: true, _field: true}`)_
- **bars** _{ barDef: { [key in keyof T]: string }, label?: string }[]_ where _barDef_ contains values for specific bar columns and label for this bar.
- _or_ Array style:
- **groupByColumns** _string[]_ bar for each unique combination of given columns values. _(example: `['cpu', '_field', ]`)_
- **bars** _{ barDef: string[], label?: string }[]_ where _barDef_ contains values for specific bar columns and label for this bar. Each barDef value belongs to key grom groupByColumns with same index.
- **type**: _'gauge mini'. **Required**._ Specifies that this LayerConfig is a gauge mini layer.

- **mode** _'progress' | 'bullet'._
- `'bullet'` backgroud bar is colored and value bar has always secondary color
Expand Down Expand Up @@ -729,6 +723,8 @@ TableGraphLayerConfig uses the `fluxResponse` property from `config` as the data
- **labelMainFontColor** _string_ Main label color.

Bar labels
- **labelBarsEnabled** _boolean_ Bar labels shown if true

- **labelBarsFontSize** _number_ Bar labels font size

- **labelBarsFontColor** _string_ Bar labels font color
Expand Down Expand Up @@ -764,7 +760,7 @@ TableGraphLayerConfig uses the `fluxResponse` property from `config` as the data

- **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.
- example ```valueFormater: (num: number) => `${num.toFixed(0)}%` ``` for _value=23.213_ will show text value _23%_.
- example ```valueFormater: (num: number) => `${((num || 0) * 100).toFixed(0)}%` ``` for _value=0.23213_ will show text value _23%_.

**Precreated themes**
- `GAUGE_MINI_THEME_BULLET_DARK`
Expand All @@ -773,7 +769,6 @@ TableGraphLayerConfig uses the `fluxResponse` property from `config` as the data
type: 'gauge mini',
mode: 'bullet',
textMode: 'follow',
barsDefinitions: {groupByColumns: ["_field"]},

valueHeight: 18,
gaugeHeight: 25,
Expand All @@ -795,6 +790,7 @@ TableGraphLayerConfig uses the `fluxResponse` property from `config` as the data
labelMainFontSize: 13,
labelMainFontColor: InfluxColors.Ghost,

labelBarsEnabled: false,
labelBarsFontSize: 11,
labelBarsFontColor: InfluxColors.Forge,

Expand All @@ -816,7 +812,6 @@ TableGraphLayerConfig uses the `fluxResponse` property from `config` as the data
type: 'gauge mini',
mode: 'progress',
textMode: 'follow',
barsDefinitions: {groupByColumns: ['_field']},

valueHeight: 20,
gaugeHeight: 20,
Expand All @@ -836,6 +831,7 @@ TableGraphLayerConfig uses the `fluxResponse` property from `config` as the data
labelMainFontSize: 13,
labelMainFontColor: InfluxColors.Ghost,

labelBarsEnabled: false,
labelBarsFontSize: 11,
labelBarsFontColor: InfluxColors.Forge,

Expand Down
43 changes: 8 additions & 35 deletions giraffe/src/components/GaugeMini.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {scaleLinear} from 'd3-scale'

// Types
import {GaugeMiniColors, GaugeMiniLayerConfig} from '../types'
import {GroupedData} from './LatestMultipleValueTransform'

import {
gaugeMiniNormalizeThemeMemoized,
GaugeMiniThemeNormalized,
Expand All @@ -13,28 +15,10 @@ import {
interface Props {
width: number
height: number
values: {colsMString: string; value: number}[]
values: GroupedData
theme: Required<GaugeMiniLayerConfig>
}

// todo: move into gauge utils
/** create merged string for given column string values. String is same for all columns with same values and unique for different ones */
export const createColsMString = <T extends {[key: string]: true}>(
groupedBy: T,
col: {[key in keyof T]: string}
): string => {
const columns = Object.keys(groupedBy)
.filter(x => groupedBy[x])
.sort()
const columnValues = columns.map(x => col[x])
/**
* replacing - with -- will ensures that rows
* { a: '0-1', b: '2' } and { a: '0', b: '1-2' }
* will not have same string (0-1-2 instead they will be 0--1-2 and 0-1--2)
*/
return columnValues.map(x => x.split('-').join('--')).join('-')
}

const barCssClass = 'gauge-mini-bar'

//#region svg helpers
Expand Down Expand Up @@ -473,6 +457,7 @@ export const GaugeMini: FunctionComponent<Props> = ({
labelMain,
labelMainFontSize,
labelMainFontColor,
labelBarsEnabled,
labelBarsFontColor,
labelBarsFontSize,
colors,
Expand All @@ -485,29 +470,18 @@ export const GaugeMini: FunctionComponent<Props> = ({
const barLabelWidth = Math.max(...barLabelsWidth) || 0
const barWidth = width - sidePaddings * 2 - barLabelWidth
const maxBarHeight = Math.max(gaugeHeight, valueHeight)
const allBarsHeight = values.length * (maxBarHeight + barPaddings)

const barsDefinitions = theme.barsDefinitions
const allBarsHeight =
Object.keys(values).length * (maxBarHeight + barPaddings)

// create unified barsDefinition

const labelMapping: any = {}
barsDefinitions?.bars?.forEach(x => {
if (!x.label) {
return
}
const mstring = createColsMString(barsDefinitions.groupByColumns, x.barDef)
labelMapping[mstring] = x.label
})

const [autocenterToken, setAutocenterToken] = useState(Date.now())
useEffect(() => {
setAutocenterToken(Date.now())
}, [
width,
height,
barLabelWidth,
barsDefinitions,
valueHeight,
gaugeHeight,
barPaddings,
Expand Down Expand Up @@ -536,11 +510,10 @@ export const GaugeMini: FunctionComponent<Props> = ({
{labelMain}
</text>
)}
{values.map(({colsMString, value}, i) => {
{Object.entries(values).map(([group, value], i) => {
const y = 0 + i * (maxBarHeight + barPaddings)
const label = labelMapping?.[colsMString]

const textCenter = y + maxBarHeight / 2
const label = labelBarsEnabled ? group : ''

// todo: no rerender ?
const onRectChanged = (r: DOMRect) => {
Expand Down
4 changes: 3 additions & 1 deletion giraffe/src/components/GaugeMiniLayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import {GaugeMiniLayerConfig} from '../types'
import {GaugeMini} from './GaugeMini'

import {GAUGE_MINI_THEME_BULLET_DARK} from '../constants/gaugeMiniStyles'
import {GroupedData} from './LatestMultipleValueTransform'

interface Props {
values: {colsMString: string; value: number}[]
values: GroupedData
theme: GaugeMiniLayerConfig
}

// todo: move gauge mini here
export const GaugeMiniLayer: FunctionComponent<Props> = (props: Props) => {
const {theme, values} = props
const themeOrDefault: Required<GaugeMiniLayerConfig> = {
Expand Down
104 changes: 34 additions & 70 deletions giraffe/src/components/LatestMultipleValueTransform.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,10 @@
// Libraries
import React, {useMemo, FunctionComponent} from 'react'
import {Table} from '../types'
import {createColsMString} from './GaugeMini'

interface SelectedColumns {
[key: string]: true
}

export const getLatestValuesGrouped = (
table: Table,
columnsObj: SelectedColumns
) => {
const columns = Object.keys(columnsObj).sort()

columns.forEach(x => {
if (table.getColumnType(x) !== 'string') {
throw new Error(
`Data can be grouped only by string columns. But column ${x} is typeof ${table.getColumnType(
x
)}`
)
}
})

const valueColumn = table.getColumn('_value', 'number') as number[]

if (!valueColumn.length) {
return []
}
export type GroupedData = {[key: string]: number}

const getTimeColumn = (table: Table) => {
// Fallback to `_stop` column if `_time` column missing otherwise return empty array.
let timeColData: number[] = []

Expand All @@ -41,73 +17,61 @@ export const getLatestValuesGrouped = (
return []
}

const groupColsData = columns.map(k =>
table.getColumn(k, 'string')
) as string[][]
return timeColData
}

const result: {[key: string]: number} = {}
export const getLatestValuesGrouped = (
table: Table,
groupColumnKey: string
): GroupedData => {
const valueCol = table.getColumn('_value', 'number')
const groupCol = table.getColumn(groupColumnKey)

timeColData
// merge time with it's index
.map((time, index) => ({time, index}))
// remove entries without time
.filter(({time}) => time)
// todo: sort time complexity too high ... replace with another solution
// from low time to high time (last is last)
.sort(({time: t1}, {time: t2}) => t1 - t2)
// get relevant data from index (we don't need time anymore)
.map(({index}) => ({
value: valueColumn[index],
groupRow: groupColsData.map(x => x[index]),
}))
// remove invalid data
.filter(({value}) => Number.isFinite(value) && typeof value === 'number')
// create result
.forEach(({value, groupRow}) => {
const grupObj = {}
groupRow.forEach((x, i) => (grupObj[columns[i]] = x))
const strKey = createColsMString(columnsObj, grupObj)
// data is inserted from last to first so latest data is first
result[strKey] = value
})
if (!valueCol.length) {
return {}
}

return result
return Object.fromEntries(
getTimeColumn(table)
// merge time with it's index
.map((time, index) => ({time, index}))
// remove entries without time
.filter(({time}) => time)
// todo: sort time complexity too high ... replace with linear solution
// from low time to high time (last is last)
.sort(({time: t1}, {time: t2}) => t1 - t2)
// get relevant data from index (we don't need time anymore)
.map(({index}) => [groupCol?.[index] ?? '', valueCol[index]] as const)
// remove invalid data
.filter(
([_, value]) => typeof value === 'number' && Number.isFinite(value)
)
)
}

interface Props {
table: Table
columns: SelectedColumns
children: (latestValue: {colsMString: string; value: number}[]) => JSX.Element
children: (latestValue: GroupedData) => JSX.Element
quiet?: boolean
}

// todo: can return string ?
export const LatestMultipleValueTransform: FunctionComponent<Props> = ({
table,
columns,
quiet = false,
children,
}) => {
const latestValues = useMemo(() => getLatestValuesGrouped(table, columns), [
const latestValues = useMemo(() => getLatestValuesGrouped(table, '_field'), [
table,
])

if (latestValues.length === 0 && quiet) {
return null
}

if (latestValues.length === 0) {
return (
if (Object.keys(latestValues).length === 0) {
return quiet ? null : (
<div>
<h4>No latest value found</h4>
</div>
)
}

const entries = Object.keys(latestValues).map(x => ({
colsMString: x,
value: latestValues[x],
}))

return children(entries)
return children(latestValues)
}
5 changes: 0 additions & 5 deletions giraffe/src/components/SizedTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {TableGraphLayer} from './TableGraphLayer'

import {usePlotEnv} from '../utils/usePlotEnv'
import {LatestMultipleValueTransform} from './LatestMultipleValueTransform'
import {getGaugeMiniBarsDefinitions} from '../utils/gaugeMiniThemeNormalize'

interface Props {
config: SizedConfig
Expand Down Expand Up @@ -87,10 +86,6 @@ export const SizedTable: FunctionComponent<Props> = ({
<LatestMultipleValueTransform
key={layerIndex}
table={newTableFromConfig(config)}
columns={
getGaugeMiniBarsDefinitions(layerConfig.barsDefinitions)
.groupByColumns
}
>
{latestValues => (
<GaugeMiniLayer
Expand Down
4 changes: 2 additions & 2 deletions giraffe/src/constants/gaugeMiniStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export const GAUGE_MINI_THEME_BULLET_DARK: Required<GaugeMiniLayerConfig> = {
type: 'gauge mini',
mode: 'bullet',
textMode: 'follow',
barsDefinitions: {groupByColumns: ['_field']},

valueHeight: 18,
gaugeHeight: 25,
Expand All @@ -27,6 +26,7 @@ export const GAUGE_MINI_THEME_BULLET_DARK: Required<GaugeMiniLayerConfig> = {
labelMainFontSize: 13,
labelMainFontColor: InfluxColors.Ghost,

labelBarsEnabled: false,
labelBarsFontSize: 11,
labelBarsFontColor: InfluxColors.Forge,

Expand All @@ -46,7 +46,6 @@ export const GAUGE_MINI_THEME_PROGRESS_DARK: Required<GaugeMiniLayerConfig> = {
type: 'gauge mini',
mode: 'progress',
textMode: 'follow',
barsDefinitions: {groupByColumns: ['_field']},

valueHeight: 20,
gaugeHeight: 20,
Expand All @@ -66,6 +65,7 @@ export const GAUGE_MINI_THEME_PROGRESS_DARK: Required<GaugeMiniLayerConfig> = {
labelMainFontSize: 13,
labelMainFontColor: InfluxColors.Ghost,

labelBarsEnabled: false,
labelBarsFontSize: 11,
labelBarsFontColor: InfluxColors.Forge,

Expand Down
Loading

0 comments on commit 7a1e0f4

Please sign in to comment.