Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
77b3da3e
Commit
77b3da3e
authored
Mar 25, 2019
by
Ryan McKinley
Committed by
Torkel Ödegaard
Mar 25, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor(data models): Renamed TableData to SeriesData (#16185)
parent
c7d10826
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
283 additions
and
253 deletions
+283
-253
packages/grafana-ui/src/components/Table/Table.story.tsx
+4
-4
packages/grafana-ui/src/components/Table/Table.tsx
+15
-15
packages/grafana-ui/src/components/Table/TableCellBuilder.tsx
+5
-5
packages/grafana-ui/src/components/Table/TableInputCSV.story.tsx
+2
-2
packages/grafana-ui/src/components/Table/TableInputCSV.test.tsx
+2
-2
packages/grafana-ui/src/components/Table/TableInputCSV.tsx
+4
-4
packages/grafana-ui/src/components/Table/examples.ts
+27
-27
packages/grafana-ui/src/types/data.ts
+38
-27
packages/grafana-ui/src/types/panel.ts
+2
-2
packages/grafana-ui/src/utils/__snapshots__/processTableData.test.ts.snap
+10
-10
packages/grafana-ui/src/utils/processTableData.test.ts
+30
-30
packages/grafana-ui/src/utils/processTableData.ts
+70
-52
packages/grafana-ui/src/utils/statsCalculator.test.ts
+8
-8
packages/grafana-ui/src/utils/statsCalculator.ts
+23
-23
public/app/core/table_model.ts
+1
-0
public/app/features/dashboard/dashgrid/DataPanel.test.tsx
+10
-10
public/app/features/dashboard/dashgrid/DataPanel.tsx
+10
-10
public/app/features/dashboard/dashgrid/PanelChrome.tsx
+4
-4
public/app/plugins/datasource/influxdb/influx_series.ts
+2
-2
public/app/plugins/datasource/prometheus/result_transformer.ts
+2
-2
public/app/plugins/panel/graph2/GraphPanel.tsx
+6
-6
public/app/plugins/panel/singlestat2/SingleStatPanel.tsx
+8
-8
No files found.
packages/grafana-ui/src/components/Table/Table.story.tsx
View file @
77b3da3e
...
@@ -4,7 +4,7 @@ import { Table } from './Table';
...
@@ -4,7 +4,7 @@ import { Table } from './Table';
import
{
getTheme
}
from
'../../themes'
;
import
{
getTheme
}
from
'../../themes'
;
import
{
migratedTestTable
,
migratedTestStyles
,
simpleTable
}
from
'./examples'
;
import
{
migratedTestTable
,
migratedTestStyles
,
simpleTable
}
from
'./examples'
;
import
{
ScopedVars
,
Table
Data
,
GrafanaThemeType
}
from
'../../types/index'
;
import
{
ScopedVars
,
Series
Data
,
GrafanaThemeType
}
from
'../../types/index'
;
import
{
withFullSizeStory
}
from
'../../utils/storybook/withFullSizeStory'
;
import
{
withFullSizeStory
}
from
'../../utils/storybook/withFullSizeStory'
;
import
{
number
,
boolean
}
from
'@storybook/addon-knobs'
;
import
{
number
,
boolean
}
from
'@storybook/addon-knobs'
;
...
@@ -29,11 +29,11 @@ export function columnIndexToLeter(column: number) {
...
@@ -29,11 +29,11 @@ export function columnIndexToLeter(column: number) {
return
String
.
fromCharCode
(
A
+
c2
);
return
String
.
fromCharCode
(
A
+
c2
);
}
}
export
function
makeDummyTable
(
columnCount
:
number
,
rowCount
:
number
):
Table
Data
{
export
function
makeDummyTable
(
columnCount
:
number
,
rowCount
:
number
):
Series
Data
{
return
{
return
{
column
s
:
Array
.
from
(
new
Array
(
columnCount
),
(
x
,
i
)
=>
{
field
s
:
Array
.
from
(
new
Array
(
columnCount
),
(
x
,
i
)
=>
{
return
{
return
{
text
:
columnIndexToLeter
(
i
),
name
:
columnIndexToLeter
(
i
),
};
};
}),
}),
rows
:
Array
.
from
(
new
Array
(
rowCount
),
(
x
,
rowId
)
=>
{
rows
:
Array
.
from
(
new
Array
(
rowCount
),
(
x
,
rowId
)
=>
{
...
...
packages/grafana-ui/src/components/Table/Table.tsx
View file @
77b3da3e
...
@@ -12,9 +12,9 @@ import {
...
@@ -12,9 +12,9 @@ import {
}
from
'react-virtualized'
;
}
from
'react-virtualized'
;
import
{
Themeable
}
from
'../../types/theme'
;
import
{
Themeable
}
from
'../../types/theme'
;
import
{
sort
Table
Data
}
from
'../../utils/processTableData'
;
import
{
sort
Series
Data
}
from
'../../utils/processTableData'
;
import
{
Table
Data
,
InterpolateFunction
}
from
'@grafana/ui'
;
import
{
Series
Data
,
InterpolateFunction
}
from
'@grafana/ui'
;
import
{
import
{
TableCellBuilder
,
TableCellBuilder
,
ColumnStyle
,
ColumnStyle
,
...
@@ -25,7 +25,7 @@ import {
...
@@ -25,7 +25,7 @@ import {
import
{
stringToJsRegex
}
from
'../../utils/index'
;
import
{
stringToJsRegex
}
from
'../../utils/index'
;
export
interface
Props
extends
Themeable
{
export
interface
Props
extends
Themeable
{
data
:
Table
Data
;
data
:
Series
Data
;
minColumnWidth
:
number
;
minColumnWidth
:
number
;
showHeader
:
boolean
;
showHeader
:
boolean
;
...
@@ -43,7 +43,7 @@ export interface Props extends Themeable {
...
@@ -43,7 +43,7 @@ export interface Props extends Themeable {
interface
State
{
interface
State
{
sortBy
?:
number
;
sortBy
?:
number
;
sortDirection
?:
SortDirectionType
;
sortDirection
?:
SortDirectionType
;
data
:
Table
Data
;
data
:
Series
Data
;
}
}
interface
ColumnRenderInfo
{
interface
ColumnRenderInfo
{
...
@@ -108,17 +108,17 @@ export class Table extends Component<Props, State> {
...
@@ -108,17 +108,17 @@ export class Table extends Component<Props, State> {
// Update the data when data or sort changes
// Update the data when data or sort changes
if
(
dataChanged
||
sortBy
!==
prevState
.
sortBy
||
sortDirection
!==
prevState
.
sortDirection
)
{
if
(
dataChanged
||
sortBy
!==
prevState
.
sortBy
||
sortDirection
!==
prevState
.
sortDirection
)
{
this
.
scrollToTop
=
true
;
this
.
scrollToTop
=
true
;
this
.
setState
({
data
:
sort
Table
Data
(
data
,
sortBy
,
sortDirection
===
'DESC'
)
});
this
.
setState
({
data
:
sort
Series
Data
(
data
,
sortBy
,
sortDirection
===
'DESC'
)
});
}
}
}
}
/** Given the configuration, setup how each column gets rendered */
/** Given the configuration, setup how each column gets rendered */
initColumns
(
props
:
Props
):
ColumnRenderInfo
[]
{
initColumns
(
props
:
Props
):
ColumnRenderInfo
[]
{
const
{
styles
,
data
,
width
,
minColumnWidth
}
=
props
;
const
{
styles
,
data
,
width
,
minColumnWidth
}
=
props
;
const
columnWidth
=
Math
.
max
(
width
/
data
.
column
s
.
length
,
minColumnWidth
);
const
columnWidth
=
Math
.
max
(
width
/
data
.
field
s
.
length
,
minColumnWidth
);
return
data
.
column
s
.
map
((
col
,
index
)
=>
{
return
data
.
field
s
.
map
((
col
,
index
)
=>
{
let
title
=
col
.
text
;
let
title
=
col
.
name
;
let
style
:
ColumnStyle
|
null
=
null
;
// ColumnStyle
let
style
:
ColumnStyle
|
null
=
null
;
// ColumnStyle
// Find the style based on the text
// Find the style based on the text
...
@@ -159,7 +159,7 @@ export class Table extends Component<Props, State> {
...
@@ -159,7 +159,7 @@ export class Table extends Component<Props, State> {
this
.
setState
({
sortBy
:
sort
,
sortDirection
:
dir
});
this
.
setState
({
sortBy
:
sort
,
sortDirection
:
dir
});
};
};
/** Converts the grid coordinates to
Table
Data coordinates */
/** Converts the grid coordinates to
Series
Data coordinates */
getCellRef
=
(
rowIndex
:
number
,
columnIndex
:
number
):
DataIndex
=>
{
getCellRef
=
(
rowIndex
:
number
,
columnIndex
:
number
):
DataIndex
=>
{
const
{
showHeader
,
rotate
}
=
this
.
props
;
const
{
showHeader
,
rotate
}
=
this
.
props
;
const
rowOffset
=
showHeader
?
-
1
:
0
;
const
rowOffset
=
showHeader
?
-
1
:
0
;
...
@@ -187,17 +187,17 @@ export class Table extends Component<Props, State> {
...
@@ -187,17 +187,17 @@ export class Table extends Component<Props, State> {
const
{
columnIndex
,
rowIndex
,
style
}
=
cell
.
props
;
const
{
columnIndex
,
rowIndex
,
style
}
=
cell
.
props
;
const
{
column
}
=
this
.
getCellRef
(
rowIndex
,
columnIndex
);
const
{
column
}
=
this
.
getCellRef
(
rowIndex
,
columnIndex
);
let
col
=
data
.
column
s
[
column
];
let
col
=
data
.
field
s
[
column
];
const
sorting
=
sortBy
===
column
;
const
sorting
=
sortBy
===
column
;
if
(
!
col
)
{
if
(
!
col
)
{
col
=
{
col
=
{
text
:
'??'
+
columnIndex
+
'???'
,
name
:
'??'
+
columnIndex
+
'???'
,
};
};
}
}
return
(
return
(
<
div
className=
"gf-table-header"
style=
{
style
}
onClick=
{
()
=>
this
.
onCellClick
(
rowIndex
,
columnIndex
)
}
>
<
div
className=
"gf-table-header"
style=
{
style
}
onClick=
{
()
=>
this
.
onCellClick
(
rowIndex
,
columnIndex
)
}
>
{
col
.
text
}
{
col
.
name
}
{
sorting
&&
<
SortIndicator
sortDirection=
{
sortDirection
}
/>
}
{
sorting
&&
<
SortIndicator
sortDirection=
{
sortDirection
}
/>
}
</
div
>
</
div
>
);
);
...
@@ -217,7 +217,7 @@ export class Table extends Component<Props, State> {
...
@@ -217,7 +217,7 @@ export class Table extends Component<Props, State> {
const
{
data
}
=
this
.
state
;
const
{
data
}
=
this
.
state
;
const
isHeader
=
row
<
0
;
const
isHeader
=
row
<
0
;
const
rowData
=
isHeader
?
data
.
column
s
:
data
.
rows
[
row
];
const
rowData
=
isHeader
?
data
.
field
s
:
data
.
rows
[
row
];
const
value
=
rowData
?
rowData
[
column
]
:
''
;
const
value
=
rowData
?
rowData
[
column
]
:
''
;
const
builder
=
isHeader
?
this
.
headerBuilder
:
this
.
getTableCellBuilder
(
column
);
const
builder
=
isHeader
?
this
.
headerBuilder
:
this
.
getTableCellBuilder
(
column
);
...
@@ -226,7 +226,7 @@ export class Table extends Component<Props, State> {
...
@@ -226,7 +226,7 @@ export class Table extends Component<Props, State> {
{
builder
({
{
builder
({
value
,
value
,
row
:
rowData
,
row
:
rowData
,
column
:
data
.
column
s
[
column
],
column
:
data
.
field
s
[
column
],
table
:
this
,
table
:
this
,
props
,
props
,
})
}
})
}
...
@@ -242,7 +242,7 @@ export class Table extends Component<Props, State> {
...
@@ -242,7 +242,7 @@ export class Table extends Component<Props, State> {
const
{
showHeader
,
fixedHeader
,
fixedColumns
,
rotate
,
width
,
height
}
=
this
.
props
;
const
{
showHeader
,
fixedHeader
,
fixedColumns
,
rotate
,
width
,
height
}
=
this
.
props
;
const
{
data
}
=
this
.
state
;
const
{
data
}
=
this
.
state
;
let
columnCount
=
data
.
column
s
.
length
;
let
columnCount
=
data
.
field
s
.
length
;
let
rowCount
=
data
.
rows
.
length
+
(
showHeader
?
1
:
0
);
let
rowCount
=
data
.
rows
.
length
+
(
showHeader
?
1
:
0
);
let
fixedColumnCount
=
Math
.
min
(
fixedColumns
,
columnCount
);
let
fixedColumnCount
=
Math
.
min
(
fixedColumns
,
columnCount
);
...
...
packages/grafana-ui/src/components/Table/TableCellBuilder.tsx
View file @
77b3da3e
...
@@ -6,12 +6,12 @@ import { Table, Props } from './Table';
...
@@ -6,12 +6,12 @@ import { Table, Props } from './Table';
import
moment
from
'moment'
;
import
moment
from
'moment'
;
import
{
ValueFormatter
}
from
'../../utils/index'
;
import
{
ValueFormatter
}
from
'../../utils/index'
;
import
{
GrafanaTheme
}
from
'../../types/theme'
;
import
{
GrafanaTheme
}
from
'../../types/theme'
;
import
{
getValueFormat
,
getColorFromHexRgbOrName
,
Column
}
from
'@grafana/ui'
;
import
{
getValueFormat
,
getColorFromHexRgbOrName
,
Field
}
from
'@grafana/ui'
;
import
{
InterpolateFunction
}
from
'../../types/panel'
;
import
{
InterpolateFunction
}
from
'../../types/panel'
;
export
interface
TableCellBuilderOptions
{
export
interface
TableCellBuilderOptions
{
value
:
any
;
value
:
any
;
column
?:
Column
;
column
?:
Field
;
row
?:
any
[];
row
?:
any
[];
table
?:
Table
;
table
?:
Table
;
className
?:
string
;
className
?:
string
;
...
@@ -74,7 +74,7 @@ export interface ColumnStyle {
...
@@ -74,7 +74,7 @@ export interface ColumnStyle {
// private replaceVariables: InterpolateFunction,
// private replaceVariables: InterpolateFunction,
// private fmt?:ValueFormatter) {
// private fmt?:ValueFormatter) {
export
function
getCellBuilder
(
schema
:
Column
,
style
:
ColumnStyle
|
null
,
props
:
Props
):
TableCellBuilder
{
export
function
getCellBuilder
(
schema
:
Field
,
style
:
ColumnStyle
|
null
,
props
:
Props
):
TableCellBuilder
{
if
(
!
style
)
{
if
(
!
style
)
{
return
simpleCellBuilder
;
return
simpleCellBuilder
;
}
}
...
@@ -154,12 +154,12 @@ class CellBuilderWithStyle {
...
@@ -154,12 +154,12 @@ class CellBuilderWithStyle {
private
mapper
:
ValueMapper
,
private
mapper
:
ValueMapper
,
private
style
:
ColumnStyle
,
private
style
:
ColumnStyle
,
private
theme
:
GrafanaTheme
,
private
theme
:
GrafanaTheme
,
private
column
:
Column
,
private
column
:
Field
,
private
replaceVariables
:
InterpolateFunction
,
private
replaceVariables
:
InterpolateFunction
,
private
fmt
?:
ValueFormatter
private
fmt
?:
ValueFormatter
)
{
)
{
//
//
console
.
log
(
'COLUMN'
,
column
.
text
,
theme
);
console
.
log
(
'COLUMN'
,
column
.
name
,
theme
);
}
}
getColorForValue
=
(
value
:
any
):
string
|
null
=>
{
getColorForValue
=
(
value
:
any
):
string
|
null
=>
{
...
...
packages/grafana-ui/src/components/Table/TableInputCSV.story.tsx
View file @
77b3da3e
...
@@ -3,7 +3,7 @@ import React from 'react';
...
@@ -3,7 +3,7 @@ import React from 'react';
import
{
storiesOf
}
from
'@storybook/react'
;
import
{
storiesOf
}
from
'@storybook/react'
;
import
TableInputCSV
from
'./TableInputCSV'
;
import
TableInputCSV
from
'./TableInputCSV'
;
import
{
action
}
from
'@storybook/addon-actions'
;
import
{
action
}
from
'@storybook/addon-actions'
;
import
{
Table
Data
}
from
'../../types/data'
;
import
{
Series
Data
}
from
'../../types/data'
;
import
{
withCenteredStory
}
from
'../../utils/storybook/withCenteredStory'
;
import
{
withCenteredStory
}
from
'../../utils/storybook/withCenteredStory'
;
const
TableInputStories
=
storiesOf
(
'UI/Table/Input'
,
module
);
const
TableInputStories
=
storiesOf
(
'UI/Table/Input'
,
module
);
...
@@ -15,7 +15,7 @@ TableInputStories.add('default', () => {
...
@@ -15,7 +15,7 @@ TableInputStories.add('default', () => {
<
div
style=
{
{
width
:
'90%'
,
height
:
'90vh'
}
}
>
<
div
style=
{
{
width
:
'90%'
,
height
:
'90vh'
}
}
>
<
TableInputCSV
<
TableInputCSV
text=
{
'a,b,c
\
n1,2,3'
}
text=
{
'a,b,c
\
n1,2,3'
}
onTableParsed=
{
(
table
:
Table
Data
,
text
:
string
)
=>
{
onTableParsed=
{
(
table
:
Series
Data
,
text
:
string
)
=>
{
console
.
log
(
'Table'
,
table
,
text
);
console
.
log
(
'Table'
,
table
,
text
);
action
(
'Table'
)(
table
,
text
);
action
(
'Table'
)(
table
,
text
);
}
}
}
}
...
...
packages/grafana-ui/src/components/Table/TableInputCSV.test.tsx
View file @
77b3da3e
...
@@ -2,7 +2,7 @@ import React from 'react';
...
@@ -2,7 +2,7 @@ import React from 'react';
import
renderer
from
'react-test-renderer'
;
import
renderer
from
'react-test-renderer'
;
import
TableInputCSV
from
'./TableInputCSV'
;
import
TableInputCSV
from
'./TableInputCSV'
;
import
{
Table
Data
}
from
'../../types/data'
;
import
{
Series
Data
}
from
'../../types/data'
;
describe
(
'TableInputCSV'
,
()
=>
{
describe
(
'TableInputCSV'
,
()
=>
{
it
(
'renders correctly'
,
()
=>
{
it
(
'renders correctly'
,
()
=>
{
...
@@ -10,7 +10,7 @@ describe('TableInputCSV', () => {
...
@@ -10,7 +10,7 @@ describe('TableInputCSV', () => {
.
create
(
.
create
(
<
TableInputCSV
<
TableInputCSV
text=
{
'a,b,c
\
n1,2,3'
}
text=
{
'a,b,c
\
n1,2,3'
}
onTableParsed=
{
(
table
:
Table
Data
,
text
:
string
)
=>
{
onTableParsed=
{
(
table
:
Series
Data
,
text
:
string
)
=>
{
// console.log('Table:', table, 'from:', text);
// console.log('Table:', table, 'from:', text);
}
}
}
}
/>
/>
...
...
packages/grafana-ui/src/components/Table/TableInputCSV.tsx
View file @
77b3da3e
import
React
from
'react'
;
import
React
from
'react'
;
import
debounce
from
'lodash/debounce'
;
import
debounce
from
'lodash/debounce'
;
import
{
parseCSV
,
TableParseOptions
,
TableParseDetails
}
from
'../../utils/processTableData'
;
import
{
parseCSV
,
TableParseOptions
,
TableParseDetails
}
from
'../../utils/processTableData'
;
import
{
Table
Data
}
from
'../../types/data'
;
import
{
Series
Data
}
from
'../../types/data'
;
import
{
AutoSizer
}
from
'react-virtualized'
;
import
{
AutoSizer
}
from
'react-virtualized'
;
interface
Props
{
interface
Props
{
options
?:
TableParseOptions
;
options
?:
TableParseOptions
;
text
:
string
;
text
:
string
;
onTableParsed
:
(
table
:
Table
Data
,
text
:
string
)
=>
void
;
onTableParsed
:
(
table
:
Series
Data
,
text
:
string
)
=>
void
;
}
}
interface
State
{
interface
State
{
text
:
string
;
text
:
string
;
table
:
Table
Data
;
table
:
Series
Data
;
details
:
TableParseDetails
;
details
:
TableParseDetails
;
}
}
...
@@ -82,7 +82,7 @@ class TableInputCSV extends React.PureComponent<Props, State> {
...
@@ -82,7 +82,7 @@ class TableInputCSV extends React.PureComponent<Props, State> {
<
div
className=
"gf-table-input-csv"
style=
{
{
width
,
height
}
}
>
<
div
className=
"gf-table-input-csv"
style=
{
{
width
,
height
}
}
>
<
textarea
placeholder=
"Enter CSV here..."
value=
{
this
.
state
.
text
}
onChange=
{
this
.
onTextChange
}
/>
<
textarea
placeholder=
"Enter CSV here..."
value=
{
this
.
state
.
text
}
onChange=
{
this
.
onTextChange
}
/>
<
footer
onClick=
{
this
.
onFooterClicked
}
className=
{
footerClassNames
}
>
<
footer
onClick=
{
this
.
onFooterClicked
}
className=
{
footerClassNames
}
>
Rows:
{
table
.
rows
.
length
}
, Columns:
{
table
.
column
s
.
length
}
Rows:
{
table
.
rows
.
length
}
, Columns:
{
table
.
field
s
.
length
}
{
hasErrors
?
<
i
className=
"fa fa-exclamation-triangle"
/>
:
<
i
className=
"fa fa-check-circle"
/>
}
{
hasErrors
?
<
i
className=
"fa fa-exclamation-triangle"
/>
:
<
i
className=
"fa fa-check-circle"
/>
}
</
footer
>
</
footer
>
</
div
>
</
div
>
...
...
packages/grafana-ui/src/components/Table/examples.ts
View file @
77b3da3e
import
{
Table
Data
}
from
'../../types/data'
;
import
{
Series
Data
}
from
'../../types/data'
;
import
{
ColumnStyle
}
from
'./TableCellBuilder'
;
import
{
ColumnStyle
}
from
'./TableCellBuilder'
;
import
{
getColorDefinitionByName
}
from
'@grafana/ui'
;
import
{
getColorDefinitionByName
}
from
'@grafana/ui'
;
...
@@ -7,23 +7,23 @@ const SemiDarkOrange = getColorDefinitionByName('semi-dark-orange');
...
@@ -7,23 +7,23 @@ const SemiDarkOrange = getColorDefinitionByName('semi-dark-orange');
export
const
migratedTestTable
=
{
export
const
migratedTestTable
=
{
type
:
'table'
,
type
:
'table'
,
column
s
:
[
field
s
:
[
{
text
:
'Time'
},
{
name
:
'Time'
},
{
text
:
'Value'
},
{
name
:
'Value'
},
{
text
:
'Colored'
},
{
name
:
'Colored'
},
{
text
:
'Undefined'
},
{
name
:
'Undefined'
},
{
text
:
'String'
},
{
name
:
'String'
},
{
text
:
'United'
,
unit
:
'bps'
},
{
name
:
'United'
,
unit
:
'bps'
},
{
text
:
'Sanitized'
},
{
name
:
'Sanitized'
},
{
text
:
'Link'
},
{
name
:
'Link'
},
{
text
:
'Array'
},
{
name
:
'Array'
},
{
text
:
'Mapping'
},
{
name
:
'Mapping'
},
{
text
:
'RangeMapping'
},
{
name
:
'RangeMapping'
},
{
text
:
'MappingColored'
},
{
name
:
'MappingColored'
},
{
text
:
'RangeMappingColored'
},
{
name
:
'RangeMappingColored'
},
],
],
rows
:
[[
1388556366666
,
1230
,
40
,
undefined
,
''
,
''
,
'my.host.com'
,
'host1'
,
[
'value1'
,
'value2'
],
1
,
2
,
1
,
2
]],
rows
:
[[
1388556366666
,
1230
,
40
,
undefined
,
''
,
''
,
'my.host.com'
,
'host1'
,
[
'value1'
,
'value2'
],
1
,
2
,
1
,
2
]],
}
as
Table
Data
;
}
as
Series
Data
;
export
const
migratedTestStyles
:
ColumnStyle
[]
=
[
export
const
migratedTestStyles
:
ColumnStyle
[]
=
[
{
{
...
@@ -87,19 +87,19 @@ export const migratedTestStyles: ColumnStyle[] = [
...
@@ -87,19 +87,19 @@ export const migratedTestStyles: ColumnStyle[] = [
valueMaps
:
[
valueMaps
:
[
{
{
value
:
'1'
,
value
:
'1'
,
text
:
'on'
,
name
:
'on'
,
},
},
{
{
value
:
'0'
,
value
:
'0'
,
text
:
'off'
,
name
:
'off'
,
},
},
{
{
value
:
'HELLO WORLD'
,
value
:
'HELLO WORLD'
,
text
:
'HELLO GRAFANA'
,
name
:
'HELLO GRAFANA'
,
},
},
{
{
value
:
'value1, value2'
,
value
:
'value1, value2'
,
text
:
'value3, value4'
,
name
:
'value3, value4'
,
},
},
],
],
},
},
...
@@ -111,12 +111,12 @@ export const migratedTestStyles: ColumnStyle[] = [
...
@@ -111,12 +111,12 @@ export const migratedTestStyles: ColumnStyle[] = [
{
{
from
:
'1'
,
from
:
'1'
,
to
:
'3'
,
to
:
'3'
,
text
:
'on'
,
name
:
'on'
,
},
},
{
{
from
:
'3'
,
from
:
'3'
,
to
:
'6'
,
to
:
'6'
,
text
:
'off'
,
name
:
'off'
,
},
},
],
],
},
},
...
@@ -127,11 +127,11 @@ export const migratedTestStyles: ColumnStyle[] = [
...
@@ -127,11 +127,11 @@ export const migratedTestStyles: ColumnStyle[] = [
valueMaps
:
[
valueMaps
:
[
{
{
value
:
'1'
,
value
:
'1'
,
text
:
'on'
,
name
:
'on'
,
},
},
{
{
value
:
'0'
,
value
:
'0'
,
text
:
'off'
,
name
:
'off'
,
},
},
],
],
colorMode
:
'value'
,
colorMode
:
'value'
,
...
@@ -146,12 +146,12 @@ export const migratedTestStyles: ColumnStyle[] = [
...
@@ -146,12 +146,12 @@ export const migratedTestStyles: ColumnStyle[] = [
{
{
from
:
'1'
,
from
:
'1'
,
to
:
'3'
,
to
:
'3'
,
text
:
'on'
,
name
:
'on'
,
},
},
{
{
from
:
'3'
,
from
:
'3'
,
to
:
'6'
,
to
:
'6'
,
text
:
'off'
,
name
:
'off'
,
},
},
],
],
colorMode
:
'value'
,
colorMode
:
'value'
,
...
@@ -162,6 +162,6 @@ export const migratedTestStyles: ColumnStyle[] = [
...
@@ -162,6 +162,6 @@ export const migratedTestStyles: ColumnStyle[] = [
export
const
simpleTable
=
{
export
const
simpleTable
=
{
type
:
'table'
,
type
:
'table'
,
columns
:
[{
text
:
'First'
},
{
text
:
'Second'
},
{
text
:
'Third'
}],
columns
:
[{
name
:
'First'
},
{
name
:
'Second'
},
{
name
:
'Third'
}],
rows
:
[[
701
,
205
,
305
],
[
702
,
206
,
301
],
[
703
,
207
,
304
]],
rows
:
[[
701
,
205
,
305
],
[
702
,
206
,
301
],
[
703
,
207
,
304
]],
};
};
packages/grafana-ui/src/types/data.ts
View file @
77b3da3e
...
@@ -5,6 +5,44 @@ export enum LoadingState {
...
@@ -5,6 +5,44 @@ export enum LoadingState {
Error
=
'Error'
,
Error
=
'Error'
,
}
}
export
enum
FieldType
{
time
=
'time'
,
// or date
number
=
'number'
,
string
=
'string'
,
boolean
=
'boolean'
,
other
=
'other'
,
// Object, Array, etc
}
export
interface
Field
{
name
:
string
;
// The column name
type
?:
FieldType
;
filterable
?:
boolean
;
unit
?:
string
;
dateFormat
?:
string
;
// Source data format
}
export
interface
Tags
{
[
key
:
string
]:
string
;
}
export
interface
SeriesData
{
name
?:
string
;
fields
:
Field
[];
rows
:
any
[][];
tags
?:
Tags
;
}
export
interface
Column
{
text
:
string
;
// For a Column, the 'text' is the field name
filterable
?:
boolean
;
unit
?:
string
;
}
export
interface
TableData
{
columns
:
Column
[];
rows
:
any
[][];
}
export
type
TimeSeriesValue
=
number
|
null
;
export
type
TimeSeriesValue
=
number
|
null
;
export
type
TimeSeriesPoints
=
TimeSeriesValue
[][];
export
type
TimeSeriesPoints
=
TimeSeriesValue
[][];
...
@@ -33,33 +71,6 @@ export enum NullValueMode {
...
@@ -33,33 +71,6 @@ export enum NullValueMode {
/** View model projection of many time series */
/** View model projection of many time series */
export
type
TimeSeriesVMs
=
TimeSeriesVM
[];
export
type
TimeSeriesVMs
=
TimeSeriesVM
[];
export
enum
ColumnType
{
time
=
'time'
,
// or date
number
=
'number'
,
string
=
'string'
,
boolean
=
'boolean'
,
other
=
'other'
,
// Object, Array, etc
}
export
interface
Column
{
text
:
string
;
// The column name
type
?:
ColumnType
;
filterable
?:
boolean
;
unit
?:
string
;
dateFormat
?:
string
;
// Source data format
}
export
interface
Tags
{
[
key
:
string
]:
string
;
}
export
interface
TableData
{
name
?:
string
;
columns
:
Column
[];
rows
:
any
[][];
tags
?:
Tags
;
}
export
interface
AnnotationEvent
{
export
interface
AnnotationEvent
{
annotation
?:
any
;
annotation
?:
any
;
dashboardId
?:
number
;
dashboardId
?:
number
;
...
...
packages/grafana-ui/src/types/panel.ts
View file @
77b3da3e
import
{
ComponentClass
}
from
'react'
;
import
{
ComponentClass
}
from
'react'
;
import
{
LoadingState
,
Table
Data
}
from
'./data'
;
import
{
LoadingState
,
Series
Data
}
from
'./data'
;
import
{
TimeRange
}
from
'./time'
;
import
{
TimeRange
}
from
'./time'
;
import
{
ScopedVars
}
from
'./datasource'
;
import
{
ScopedVars
}
from
'./datasource'
;
export
type
InterpolateFunction
=
(
value
:
string
,
scopedVars
?:
ScopedVars
,
format
?:
string
|
Function
)
=>
string
;
export
type
InterpolateFunction
=
(
value
:
string
,
scopedVars
?:
ScopedVars
,
format
?:
string
|
Function
)
=>
string
;
export
interface
PanelProps
<
T
=
any
>
{
export
interface
PanelProps
<
T
=
any
>
{
data
?:
Table
Data
[];
data
?:
Series
Data
[];
timeRange
:
TimeRange
;
timeRange
:
TimeRange
;
loading
:
LoadingState
;
loading
:
LoadingState
;
options
:
T
;
options
:
T
;
...
...
packages/grafana-ui/src/utils/__snapshots__/processTableData.test.ts.snap
View file @
77b3da3e
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`process
Table
Data basic processing should generate a header and fix widths 1`] = `
exports[`process
Series
Data basic processing should generate a header and fix widths 1`] = `
Object {
Object {
"
column
s": Array [
"
field
s": Array [
Object {
Object {
"
text": "Column
1",
"
name": "Field
1",
},
},
Object {
Object {
"
text": "Column
2",
"
name": "Field
2",
},
},
Object {
Object {
"
text": "Column
3",
"
name": "Field
3",
},
},
],
],
"rows": Array [
"rows": Array [
...
@@ -33,17 +33,17 @@ Object {
...
@@ -33,17 +33,17 @@ Object {
}
}
`;
`;
exports[`process
Table
Data basic processing should read header and two rows 1`] = `
exports[`process
Series
Data basic processing should read header and two rows 1`] = `
Object {
Object {
"
column
s": Array [
"
field
s": Array [
Object {
Object {
"
text
": "a",
"
name
": "a",
},
},
Object {
Object {
"
text
": "b",
"
name
": "b",
},
},
Object {
Object {
"
text
": "c",
"
name
": "c",
},
},
],
],
"rows": Array [
"rows": Array [
...
...
packages/grafana-ui/src/utils/processTableData.test.ts
View file @
77b3da3e
import
{
parseCSV
,
to
TableData
,
guessColumnTypes
,
guessColumn
TypeFromValue
}
from
'./processTableData'
;
import
{
parseCSV
,
to
SeriesData
,
guessFieldTypes
,
guessField
TypeFromValue
}
from
'./processTableData'
;
import
{
Column
Type
}
from
'../types/data'
;
import
{
Field
Type
}
from
'../types/data'
;
import
moment
from
'moment'
;
import
moment
from
'moment'
;
describe
(
'process
Table
Data'
,
()
=>
{
describe
(
'process
Series
Data'
,
()
=>
{
describe
(
'basic processing'
,
()
=>
{
describe
(
'basic processing'
,
()
=>
{
it
(
'should read header and two rows'
,
()
=>
{
it
(
'should read header and two rows'
,
()
=>
{
const
text
=
'a,b,c
\
n1,2,3
\
n4,5,6'
;
const
text
=
'a,b,c
\
n1,2,3
\
n4,5,6'
;
...
@@ -21,14 +21,14 @@ describe('processTableData', () => {
...
@@ -21,14 +21,14 @@ describe('processTableData', () => {
});
});
});
});
describe
(
'to
Table
Data'
,
()
=>
{
describe
(
'to
Series
Data'
,
()
=>
{
it
(
'converts timeseries to table '
,
()
=>
{
it
(
'converts timeseries to table '
,
()
=>
{
const
input1
=
{
const
input1
=
{
target
:
'Field Name'
,
target
:
'Field Name'
,
datapoints
:
[[
100
,
1
],
[
200
,
2
]],
datapoints
:
[[
100
,
1
],
[
200
,
2
]],
};
};
let
table
=
to
Table
Data
(
input1
);
let
table
=
to
Series
Data
(
input1
);
expect
(
table
.
columns
[
0
].
text
).
toBe
(
input1
.
target
);
expect
(
table
.
fields
[
0
].
name
).
toBe
(
input1
.
target
);
expect
(
table
.
rows
).
toBe
(
input1
.
datapoints
);
expect
(
table
.
rows
).
toBe
(
input1
.
datapoints
);
// Should fill a default name if target is empty
// Should fill a default name if target is empty
...
@@ -37,48 +37,48 @@ describe('toTableData', () => {
...
@@ -37,48 +37,48 @@ describe('toTableData', () => {
target
:
''
,
target
:
''
,
datapoints
:
[[
100
,
1
],
[
200
,
2
]],
datapoints
:
[[
100
,
1
],
[
200
,
2
]],
};
};
table
=
to
Table
Data
(
input2
);
table
=
to
Series
Data
(
input2
);
expect
(
table
.
columns
[
0
].
text
).
toEqual
(
'Value'
);
expect
(
table
.
fields
[
0
].
name
).
toEqual
(
'Value'
);
});
});
it
(
'keeps tableData unchanged'
,
()
=>
{
it
(
'keeps tableData unchanged'
,
()
=>
{
const
input
=
{
const
input
=
{
column
s
:
[{
text
:
'A'
},
{
text
:
'B'
},
{
text
:
'C'
}],
field
s
:
[{
text
:
'A'
},
{
text
:
'B'
},
{
text
:
'C'
}],
rows
:
[[
100
,
'A'
,
1
],
[
200
,
'B'
,
2
],
[
300
,
'C'
,
3
]],
rows
:
[[
100
,
'A'
,
1
],
[
200
,
'B'
,
2
],
[
300
,
'C'
,
3
]],
};
};
const
table
=
to
Table
Data
(
input
);
const
table
=
to
Series
Data
(
input
);
expect
(
table
).
toBe
(
input
);
expect
(
table
).
toBe
(
input
);
});
});
it
(
'Guess Colum Types from value'
,
()
=>
{
it
(
'Guess Colum Types from value'
,
()
=>
{
expect
(
guess
ColumnTypeFromValue
(
1
)).
toBe
(
Column
Type
.
number
);
expect
(
guess
FieldTypeFromValue
(
1
)).
toBe
(
Field
Type
.
number
);
expect
(
guess
ColumnTypeFromValue
(
1.234
)).
toBe
(
Column
Type
.
number
);
expect
(
guess
FieldTypeFromValue
(
1.234
)).
toBe
(
Field
Type
.
number
);
expect
(
guess
ColumnTypeFromValue
(
3.125e7
)).
toBe
(
Column
Type
.
number
);
expect
(
guess
FieldTypeFromValue
(
3.125e7
)).
toBe
(
Field
Type
.
number
);
expect
(
guess
ColumnTypeFromValue
(
true
)).
toBe
(
Column
Type
.
boolean
);
expect
(
guess
FieldTypeFromValue
(
true
)).
toBe
(
Field
Type
.
boolean
);
expect
(
guess
ColumnTypeFromValue
(
false
)).
toBe
(
Column
Type
.
boolean
);
expect
(
guess
FieldTypeFromValue
(
false
)).
toBe
(
Field
Type
.
boolean
);
expect
(
guess
ColumnTypeFromValue
(
new
Date
())).
toBe
(
Column
Type
.
time
);
expect
(
guess
FieldTypeFromValue
(
new
Date
())).
toBe
(
Field
Type
.
time
);
expect
(
guess
ColumnTypeFromValue
(
moment
())).
toBe
(
Column
Type
.
time
);
expect
(
guess
FieldTypeFromValue
(
moment
())).
toBe
(
Field
Type
.
time
);
});
});
it
(
'Guess Colum Types from strings'
,
()
=>
{
it
(
'Guess Colum Types from strings'
,
()
=>
{
expect
(
guess
ColumnTypeFromValue
(
'1'
)).
toBe
(
Column
Type
.
number
);
expect
(
guess
FieldTypeFromValue
(
'1'
)).
toBe
(
Field
Type
.
number
);
expect
(
guess
ColumnTypeFromValue
(
'1.234'
)).
toBe
(
Column
Type
.
number
);
expect
(
guess
FieldTypeFromValue
(
'1.234'
)).
toBe
(
Field
Type
.
number
);
expect
(
guess
ColumnTypeFromValue
(
'3.125e7'
)).
toBe
(
Column
Type
.
number
);
expect
(
guess
FieldTypeFromValue
(
'3.125e7'
)).
toBe
(
Field
Type
.
number
);
expect
(
guess
ColumnTypeFromValue
(
'True'
)).
toBe
(
Column
Type
.
boolean
);
expect
(
guess
FieldTypeFromValue
(
'True'
)).
toBe
(
Field
Type
.
boolean
);
expect
(
guess
ColumnTypeFromValue
(
'FALSE'
)).
toBe
(
Column
Type
.
boolean
);
expect
(
guess
FieldTypeFromValue
(
'FALSE'
)).
toBe
(
Field
Type
.
boolean
);
expect
(
guess
ColumnTypeFromValue
(
'true'
)).
toBe
(
Column
Type
.
boolean
);
expect
(
guess
FieldTypeFromValue
(
'true'
)).
toBe
(
Field
Type
.
boolean
);
expect
(
guess
ColumnTypeFromValue
(
'xxxx'
)).
toBe
(
Column
Type
.
string
);
expect
(
guess
FieldTypeFromValue
(
'xxxx'
)).
toBe
(
Field
Type
.
string
);
});
});
it
(
'Guess Colum Types from table'
,
()
=>
{
it
(
'Guess Colum Types from table'
,
()
=>
{
const
table
=
{
const
table
=
{
columns
:
[{
text
:
'A (number)'
},
{
text
:
'B (strings)'
},
{
text
:
'C (nulls)'
},
{
text
:
'Time'
}],
fields
:
[{
name
:
'A (number)'
},
{
name
:
'B (strings)'
},
{
name
:
'C (nulls)'
},
{
name
:
'Time'
}],
rows
:
[[
123
,
null
,
null
,
'2000'
],
[
null
,
'Hello'
,
null
,
'XXX'
]],
rows
:
[[
123
,
null
,
null
,
'2000'
],
[
null
,
'Hello'
,
null
,
'XXX'
]],
};
};
const
norm
=
guess
Column
Types
(
table
);
const
norm
=
guess
Field
Types
(
table
);
expect
(
norm
.
columns
[
0
].
type
).
toBe
(
Column
Type
.
number
);
expect
(
norm
.
fields
[
0
].
type
).
toBe
(
Field
Type
.
number
);
expect
(
norm
.
columns
[
1
].
type
).
toBe
(
Column
Type
.
string
);
expect
(
norm
.
fields
[
1
].
type
).
toBe
(
Field
Type
.
string
);
expect
(
norm
.
column
s
[
2
].
type
).
toBeUndefined
();
expect
(
norm
.
field
s
[
2
].
type
).
toBeUndefined
();
expect
(
norm
.
columns
[
3
].
type
).
toBe
(
Column
Type
.
time
);
// based on name
expect
(
norm
.
fields
[
3
].
type
).
toBe
(
Field
Type
.
time
);
// based on name
});
});
});
});
packages/grafana-ui/src/utils/processTableData.ts
View file @
77b3da3e
...
@@ -7,7 +7,7 @@ import moment from 'moment';
...
@@ -7,7 +7,7 @@ import moment from 'moment';
import
Papa
,
{
ParseError
,
ParseMeta
}
from
'papaparse'
;
import
Papa
,
{
ParseError
,
ParseMeta
}
from
'papaparse'
;
// Types
// Types
import
{
TableData
,
Column
,
TimeSeries
,
ColumnType
}
from
'../types'
;
import
{
SeriesData
,
Field
,
TimeSeries
,
FieldType
,
TableData
}
from
'../types'
;
// Subset of all parse options
// Subset of all parse options
export
interface
TableParseOptions
{
export
interface
TableParseOptions
{
...
@@ -31,12 +31,12 @@ export interface TableParseDetails {
...
@@ -31,12 +31,12 @@ export interface TableParseDetails {
* @returns a new table that has equal length rows, or the same
* @returns a new table that has equal length rows, or the same
* table if no changes were needed
* table if no changes were needed
*/
*/
export
function
matchRowSizes
(
table
:
TableData
):
Table
Data
{
export
function
matchRowSizes
(
table
:
SeriesData
):
Series
Data
{
const
{
rows
}
=
table
;
const
{
rows
}
=
table
;
let
{
column
s
}
=
table
;
let
{
field
s
}
=
table
;
let
sameSize
=
true
;
let
sameSize
=
true
;
let
size
=
column
s
.
length
;
let
size
=
field
s
.
length
;
rows
.
forEach
(
row
=>
{
rows
.
forEach
(
row
=>
{
if
(
size
!==
row
.
length
)
{
if
(
size
!==
row
.
length
)
{
sameSize
=
false
;
sameSize
=
false
;
...
@@ -47,13 +47,13 @@ export function matchRowSizes(table: TableData): TableData {
...
@@ -47,13 +47,13 @@ export function matchRowSizes(table: TableData): TableData {
return
table
;
return
table
;
}
}
// Pad
Column
s
// Pad
Field
s
if
(
size
!==
column
s
.
length
)
{
if
(
size
!==
field
s
.
length
)
{
const
diff
=
size
-
column
s
.
length
;
const
diff
=
size
-
field
s
.
length
;
columns
=
[...
column
s
];
fields
=
[...
field
s
];
for
(
let
i
=
0
;
i
<
diff
;
i
++
)
{
for
(
let
i
=
0
;
i
<
diff
;
i
++
)
{
column
s
.
push
({
field
s
.
push
({
text
:
'Column '
+
(
column
s
.
length
+
1
),
name
:
'Field '
+
(
field
s
.
length
+
1
),
});
});
}
}
}
}
...
@@ -72,30 +72,30 @@ export function matchRowSizes(table: TableData): TableData {
...
@@ -72,30 +72,30 @@ export function matchRowSizes(table: TableData): TableData {
});
});
return
{
return
{
column
s
,
field
s
,
rows
:
fixedRows
,
rows
:
fixedRows
,
};
};
}
}
function
make
Columns
(
values
:
any
[]):
Column
[]
{
function
make
Fields
(
values
:
any
[]):
Field
[]
{
return
values
.
map
((
value
,
index
)
=>
{
return
values
.
map
((
value
,
index
)
=>
{
if
(
!
value
)
{
if
(
!
value
)
{
value
=
'
Column
'
+
(
index
+
1
);
value
=
'
Field
'
+
(
index
+
1
);
}
}
return
{
return
{
text
:
value
.
toString
().
trim
(),
name
:
value
.
toString
().
trim
(),
};
};
});
});
}
}
/**
/**
* Convert CSV text into a valid
Table
Data object
* Convert CSV text into a valid
Series
Data object
*
*
* @param text
* @param text
* @param options
* @param options
* @param details, if exists the result will be filled with debugging details
* @param details, if exists the result will be filled with debugging details
*/
*/
export
function
parseCSV
(
text
:
string
,
options
?:
TableParseOptions
,
details
?:
TableParseDetails
):
Table
Data
{
export
function
parseCSV
(
text
:
string
,
options
?:
TableParseOptions
,
details
?:
TableParseDetails
):
Series
Data
{
const
results
=
Papa
.
parse
(
text
,
{
...
options
,
dynamicTyping
:
true
,
skipEmptyLines
:
true
});
const
results
=
Papa
.
parse
(
text
,
{
...
options
,
dynamicTyping
:
true
,
skipEmptyLines
:
true
});
const
{
data
,
meta
,
errors
}
=
results
;
const
{
data
,
meta
,
errors
}
=
results
;
...
@@ -118,7 +118,7 @@ export function parseCSV(text: string, options?: TableParseOptions, details?: Ta
...
@@ -118,7 +118,7 @@ export function parseCSV(text: string, options?: TableParseOptions, details?: Ta
details
.
errors
=
errors
;
details
.
errors
=
errors
;
}
}
return
{
return
{
column
s
:
[],
field
s
:
[],
rows
:
[],
rows
:
[],
};
};
}
}
...
@@ -128,22 +128,35 @@ export function parseCSV(text: string, options?: TableParseOptions, details?: Ta
...
@@ -128,22 +128,35 @@ export function parseCSV(text: string, options?: TableParseOptions, details?: Ta
const
header
=
headerIsNotFirstLine
?
[]
:
results
.
data
.
shift
();
const
header
=
headerIsNotFirstLine
?
[]
:
results
.
data
.
shift
();
return
matchRowSizes
({
return
matchRowSizes
({
columns
:
makeColumn
s
(
header
),
fields
:
makeField
s
(
header
),
rows
:
results
.
data
,
rows
:
results
.
data
,
});
});
}
}
function
convertTimeSeriesToTableData
(
timeSeries
:
TimeSeries
):
TableData
{
function
convertTableToSeriesData
(
table
:
TableData
):
SeriesData
{
return
{
// rename the 'text' to 'name' field
fields
:
table
.
columns
.
map
(
c
=>
{
const
{
text
,
...
field
}
=
c
;
const
f
=
field
as
Field
;
f
.
name
=
text
;
return
f
;
}),
rows
:
table
.
rows
,
};
}
function
convertTimeSeriesToSeriesData
(
timeSeries
:
TimeSeries
):
SeriesData
{
return
{
return
{
name
:
timeSeries
.
target
,
name
:
timeSeries
.
target
,
column
s
:
[
field
s
:
[
{
{
text
:
timeSeries
.
target
||
'Value'
,
name
:
timeSeries
.
target
||
'Value'
,
unit
:
timeSeries
.
unit
,
unit
:
timeSeries
.
unit
,
},
},
{
{
text
:
'Time'
,
name
:
'Time'
,
type
:
Column
Type
.
time
,
type
:
Field
Type
.
time
,
unit
:
'dateTimeAsIso'
,
unit
:
'dateTimeAsIso'
,
},
},
],
],
...
@@ -151,10 +164,10 @@ function convertTimeSeriesToTableData(timeSeries: TimeSeries): TableData {
...
@@ -151,10 +164,10 @@ function convertTimeSeriesToTableData(timeSeries: TimeSeries): TableData {
};
};
}
}
export
const
getFirstTime
Column
=
(
table
:
Table
Data
):
number
=>
{
export
const
getFirstTime
Field
=
(
table
:
Series
Data
):
number
=>
{
const
{
column
s
}
=
table
;
const
{
field
s
}
=
table
;
for
(
let
i
=
0
;
i
<
column
s
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
field
s
.
length
;
i
++
)
{
if
(
columns
[
i
].
type
===
Column
Type
.
time
)
{
if
(
fields
[
i
].
type
===
Field
Type
.
time
)
{
return
i
;
return
i
;
}
}
}
}
...
@@ -170,45 +183,45 @@ const NUMBER = /^\s*-?(\d*\.?\d+|\d+\.?\d*)(e[-+]?\d+)?\s*$/i;
...
@@ -170,45 +183,45 @@ const NUMBER = /^\s*-?(\d*\.?\d+|\d+\.?\d*)(e[-+]?\d+)?\s*$/i;
*
*
* TODO: better Date/Time support! Look for standard date strings?
* TODO: better Date/Time support! Look for standard date strings?
*/
*/
export
function
guess
ColumnTypeFromValue
(
v
:
any
):
Column
Type
{
export
function
guess
FieldTypeFromValue
(
v
:
any
):
Field
Type
{
if
(
isNumber
(
v
))
{
if
(
isNumber
(
v
))
{
return
Column
Type
.
number
;
return
Field
Type
.
number
;
}
}
if
(
isString
(
v
))
{
if
(
isString
(
v
))
{
if
(
NUMBER
.
test
(
v
))
{
if
(
NUMBER
.
test
(
v
))
{
return
Column
Type
.
number
;
return
Field
Type
.
number
;
}
}
if
(
v
===
'true'
||
v
===
'TRUE'
||
v
===
'True'
||
v
===
'false'
||
v
===
'FALSE'
||
v
===
'False'
)
{
if
(
v
===
'true'
||
v
===
'TRUE'
||
v
===
'True'
||
v
===
'false'
||
v
===
'FALSE'
||
v
===
'False'
)
{
return
Column
Type
.
boolean
;
return
Field
Type
.
boolean
;
}
}
return
Column
Type
.
string
;
return
Field
Type
.
string
;
}
}
if
(
isBoolean
(
v
))
{
if
(
isBoolean
(
v
))
{
return
Column
Type
.
boolean
;
return
Field
Type
.
boolean
;
}
}
if
(
v
instanceof
Date
||
v
instanceof
moment
)
{
if
(
v
instanceof
Date
||
v
instanceof
moment
)
{
return
Column
Type
.
time
;
return
Field
Type
.
time
;
}
}
return
Column
Type
.
other
;
return
Field
Type
.
other
;
}
}
/**
/**
* Looks at the data to guess the column type. This ignores any existing setting
* Looks at the data to guess the column type. This ignores any existing setting
*/
*/
function
guess
ColumnTypeFromTable
(
table
:
TableData
,
index
:
number
):
Column
Type
|
undefined
{
function
guess
FieldTypeFromTable
(
table
:
SeriesData
,
index
:
number
):
Field
Type
|
undefined
{
const
column
=
table
.
column
s
[
index
];
const
column
=
table
.
field
s
[
index
];
// 1. Use the column name to guess
// 1. Use the column name to guess
if
(
column
.
text
)
{
if
(
column
.
name
)
{
const
name
=
column
.
text
.
toLowerCase
();
const
name
=
column
.
name
.
toLowerCase
();
if
(
name
===
'date'
||
name
===
'time'
)
{
if
(
name
===
'date'
||
name
===
'time'
)
{
return
Column
Type
.
time
;
return
Field
Type
.
time
;
}
}
}
}
...
@@ -216,7 +229,7 @@ function guessColumnTypeFromTable(table: TableData, index: number): ColumnType |
...
@@ -216,7 +229,7 @@ function guessColumnTypeFromTable(table: TableData, index: number): ColumnType |
for
(
let
i
=
0
;
i
<
table
.
rows
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
table
.
rows
.
length
;
i
++
)
{
const
v
=
table
.
rows
[
i
][
index
];
const
v
=
table
.
rows
[
i
][
index
];
if
(
v
!==
null
)
{
if
(
v
!==
null
)
{
return
guess
Column
TypeFromValue
(
v
);
return
guess
Field
TypeFromValue
(
v
);
}
}
}
}
...
@@ -228,20 +241,20 @@ function guessColumnTypeFromTable(table: TableData, index: number): ColumnType |
...
@@ -228,20 +241,20 @@ function guessColumnTypeFromTable(table: TableData, index: number): ColumnType |
* @returns a table Returns a copy of the table with the best guess for each column type
* @returns a table Returns a copy of the table with the best guess for each column type
* If the table already has column types defined, they will be used
* If the table already has column types defined, they will be used
*/
*/
export
const
guess
ColumnTypes
=
(
table
:
TableData
):
Table
Data
=>
{
export
const
guess
FieldTypes
=
(
table
:
SeriesData
):
Series
Data
=>
{
for
(
let
i
=
0
;
i
<
table
.
column
s
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
table
.
field
s
.
length
;
i
++
)
{
if
(
!
table
.
column
s
[
i
].
type
)
{
if
(
!
table
.
field
s
[
i
].
type
)
{
// Somethign is missing a type return a modified copy
// Somethign is missing a type return a modified copy
return
{
return
{
...
table
,
...
table
,
columns
:
table
.
column
s
.
map
((
column
,
index
)
=>
{
fields
:
table
.
field
s
.
map
((
column
,
index
)
=>
{
if
(
column
.
type
)
{
if
(
column
.
type
)
{
return
column
;
return
column
;
}
}
// Replace it with a calculated version
// Replace it with a calculated version
return
{
return
{
...
column
,
...
column
,
type
:
guess
Column
TypeFromTable
(
table
,
index
),
type
:
guess
Field
TypeFromTable
(
table
,
index
),
};
};
}),
}),
};
};
...
@@ -251,21 +264,26 @@ export const guessColumnTypes = (table: TableData): TableData => {
...
@@ -251,21 +264,26 @@ export const guessColumnTypes = (table: TableData): TableData => {
return
table
;
return
table
;
};
};
export
const
isTableData
=
(
data
:
any
):
data
is
Table
Data
=>
data
&&
data
.
hasOwnProperty
(
'columns'
);
export
const
isTableData
=
(
data
:
any
):
data
is
Series
Data
=>
data
&&
data
.
hasOwnProperty
(
'columns'
);
export
const
toTableData
=
(
data
:
any
):
TableData
=>
{
export
const
isSeriesData
=
(
data
:
any
):
data
is
SeriesData
=>
data
&&
data
.
hasOwnProperty
(
'fields'
);
if
(
data
.
hasOwnProperty
(
'columns'
))
{
return
data
as
TableData
;
export
const
toSeriesData
=
(
data
:
any
):
SeriesData
=>
{
if
(
data
.
hasOwnProperty
(
'fields'
))
{
return
data
as
SeriesData
;
}
}
if
(
data
.
hasOwnProperty
(
'datapoints'
))
{
if
(
data
.
hasOwnProperty
(
'datapoints'
))
{
return
convertTimeSeriesToTableData
(
data
);
return
convertTimeSeriesToSeriesData
(
data
);
}
if
(
data
.
hasOwnProperty
(
'columns'
))
{
return
convertTableToSeriesData
(
data
);
}
}
// TODO, try to convert JSON/Array to table?
// TODO, try to convert JSON/Array to table?
console
.
warn
(
'Can not convert'
,
data
);
console
.
warn
(
'Can not convert'
,
data
);
throw
new
Error
(
'Unsupported data format'
);
throw
new
Error
(
'Unsupported data format'
);
};
};
export
function
sort
TableData
(
data
:
TableData
,
sortIndex
?:
number
,
reverse
=
false
):
Table
Data
{
export
function
sort
SeriesData
(
data
:
SeriesData
,
sortIndex
?:
number
,
reverse
=
false
):
Series
Data
{
if
(
isNumber
(
sortIndex
))
{
if
(
isNumber
(
sortIndex
))
{
const
copy
=
{
const
copy
=
{
...
data
,
...
data
,
...
...
packages/grafana-ui/src/utils/statsCalculator.test.ts
View file @
77b3da3e
...
@@ -41,8 +41,8 @@ describe('Stats Calculators', () => {
...
@@ -41,8 +41,8 @@ describe('Stats Calculators', () => {
it
(
'should calculate basic stats'
,
()
=>
{
it
(
'should calculate basic stats'
,
()
=>
{
const
stats
=
calculateStats
({
const
stats
=
calculateStats
({
table
:
basicTable
,
series
:
basicTable
,
column
Index
:
0
,
field
Index
:
0
,
stats
:
[
'first'
,
'last'
,
'mean'
],
stats
:
[
'first'
,
'last'
,
'mean'
],
});
});
...
@@ -58,8 +58,8 @@ describe('Stats Calculators', () => {
...
@@ -58,8 +58,8 @@ describe('Stats Calculators', () => {
it
(
'should support a single stat also'
,
()
=>
{
it
(
'should support a single stat also'
,
()
=>
{
const
stats
=
calculateStats
({
const
stats
=
calculateStats
({
table
:
basicTable
,
series
:
basicTable
,
column
Index
:
0
,
field
Index
:
0
,
stats
:
[
'first'
],
stats
:
[
'first'
],
});
});
...
@@ -70,8 +70,8 @@ describe('Stats Calculators', () => {
...
@@ -70,8 +70,8 @@ describe('Stats Calculators', () => {
it
(
'should get non standard stats'
,
()
=>
{
it
(
'should get non standard stats'
,
()
=>
{
const
stats
=
calculateStats
({
const
stats
=
calculateStats
({
table
:
basicTable
,
series
:
basicTable
,
column
Index
:
0
,
field
Index
:
0
,
stats
:
[
StatID
.
distinctCount
,
StatID
.
changeCount
],
stats
:
[
StatID
.
distinctCount
,
StatID
.
changeCount
],
});
});
...
@@ -81,8 +81,8 @@ describe('Stats Calculators', () => {
...
@@ -81,8 +81,8 @@ describe('Stats Calculators', () => {
it
(
'should calculate step'
,
()
=>
{
it
(
'should calculate step'
,
()
=>
{
const
stats
=
calculateStats
({
const
stats
=
calculateStats
({
table
:
{
columns
:
[{
text
:
'A'
}],
rows
:
[[
100
],
[
200
],
[
300
],
[
400
]]
},
series
:
{
fields
:
[{
name
:
'A'
}],
rows
:
[[
100
],
[
200
],
[
300
],
[
400
]]
},
column
Index
:
0
,
field
Index
:
0
,
stats
:
[
StatID
.
step
,
StatID
.
delta
],
stats
:
[
StatID
.
step
,
StatID
.
delta
],
});
});
...
...
packages/grafana-ui/src/utils/statsCalculator.ts
View file @
77b3da3e
// Libraries
// Libraries
import
isNumber
from
'lodash/isNumber'
;
import
isNumber
from
'lodash/isNumber'
;
import
{
Table
Data
,
NullValueMode
}
from
'../types/index'
;
import
{
Series
Data
,
NullValueMode
}
from
'../types/index'
;
export
enum
StatID
{
export
enum
StatID
{
sum
=
'sum'
,
sum
=
'sum'
,
...
@@ -29,7 +29,7 @@ export interface ColumnStats {
...
@@ -29,7 +29,7 @@ export interface ColumnStats {
}
}
// Internal function
// Internal function
type
StatCalculator
=
(
table
:
TableData
,
column
Index
:
number
,
ignoreNulls
:
boolean
,
nullAsZero
:
boolean
)
=>
ColumnStats
;
type
StatCalculator
=
(
data
:
SeriesData
,
field
Index
:
number
,
ignoreNulls
:
boolean
,
nullAsZero
:
boolean
)
=>
ColumnStats
;
export
interface
StatCalculatorInfo
{
export
interface
StatCalculatorInfo
{
id
:
string
;
id
:
string
;
...
@@ -64,8 +64,8 @@ export function getStatsCalculators(ids?: string[]): StatCalculatorInfo[] {
...
@@ -64,8 +64,8 @@ export function getStatsCalculators(ids?: string[]): StatCalculatorInfo[] {
}
}
export
interface
CalculateStatsOptions
{
export
interface
CalculateStatsOptions
{
table
:
Table
Data
;
series
:
Series
Data
;
column
Index
:
number
;
field
Index
:
number
;
stats
:
string
[];
// The stats to calculate
stats
:
string
[];
// The stats to calculate
nullValueMode
?:
NullValueMode
;
nullValueMode
?:
NullValueMode
;
}
}
...
@@ -74,7 +74,7 @@ export interface CalculateStatsOptions {
...
@@ -74,7 +74,7 @@ export interface CalculateStatsOptions {
* @returns an object with a key for each selected stat
* @returns an object with a key for each selected stat
*/
*/
export
function
calculateStats
(
options
:
CalculateStatsOptions
):
ColumnStats
{
export
function
calculateStats
(
options
:
CalculateStatsOptions
):
ColumnStats
{
const
{
table
,
column
Index
,
stats
,
nullValueMode
}
=
options
;
const
{
series
,
field
Index
,
stats
,
nullValueMode
}
=
options
;
if
(
!
stats
||
stats
.
length
<
1
)
{
if
(
!
stats
||
stats
.
length
<
1
)
{
return
{};
return
{};
...
@@ -82,9 +82,9 @@ export function calculateStats(options: CalculateStatsOptions): ColumnStats {
...
@@ -82,9 +82,9 @@ export function calculateStats(options: CalculateStatsOptions): ColumnStats {
const
queue
=
getStatsCalculators
(
stats
);
const
queue
=
getStatsCalculators
(
stats
);
// Return early for empty
tabl
es
// Return early for empty
seri
es
// This lets the concrete implementations assume at least one row
// This lets the concrete implementations assume at least one row
if
(
!
table
.
rows
||
table
.
rows
.
length
<
1
)
{
if
(
!
series
.
rows
||
series
.
rows
.
length
<
1
)
{
const
stats
=
{}
as
ColumnStats
;
const
stats
=
{}
as
ColumnStats
;
for
(
const
stat
of
queue
)
{
for
(
const
stat
of
queue
)
{
stats
[
stat
.
id
]
=
stat
.
emptyInputResult
!==
null
?
stat
.
emptyInputResult
:
null
;
stats
[
stat
.
id
]
=
stat
.
emptyInputResult
!==
null
?
stat
.
emptyInputResult
:
null
;
...
@@ -97,16 +97,16 @@ export function calculateStats(options: CalculateStatsOptions): ColumnStats {
...
@@ -97,16 +97,16 @@ export function calculateStats(options: CalculateStatsOptions): ColumnStats {
// Avoid calculating all the standard stats if possible
// Avoid calculating all the standard stats if possible
if
(
queue
.
length
===
1
&&
queue
[
0
].
calculator
)
{
if
(
queue
.
length
===
1
&&
queue
[
0
].
calculator
)
{
return
queue
[
0
].
calculator
(
table
,
column
Index
,
ignoreNulls
,
nullAsZero
);
return
queue
[
0
].
calculator
(
series
,
field
Index
,
ignoreNulls
,
nullAsZero
);
}
}
// For now everything can use the standard stats
// For now everything can use the standard stats
let
values
=
standardStatsStat
(
table
,
column
Index
,
ignoreNulls
,
nullAsZero
);
let
values
=
standardStatsStat
(
series
,
field
Index
,
ignoreNulls
,
nullAsZero
);
for
(
const
calc
of
queue
)
{
for
(
const
calc
of
queue
)
{
if
(
!
values
.
hasOwnProperty
(
calc
.
id
)
&&
calc
.
calculator
)
{
if
(
!
values
.
hasOwnProperty
(
calc
.
id
)
&&
calc
.
calculator
)
{
values
=
{
values
=
{
...
values
,
...
values
,
...
calc
.
calculator
(
table
,
column
Index
,
ignoreNulls
,
nullAsZero
),
...
calc
.
calculator
(
series
,
field
Index
,
ignoreNulls
,
nullAsZero
),
};
};
}
}
}
}
...
@@ -223,8 +223,8 @@ function getById(id: string): StatCalculatorInfo | undefined {
...
@@ -223,8 +223,8 @@ function getById(id: string): StatCalculatorInfo | undefined {
}
}
function
standardStatsStat
(
function
standardStatsStat
(
data
:
Table
Data
,
data
:
Series
Data
,
column
Index
:
number
,
field
Index
:
number
,
ignoreNulls
:
boolean
,
ignoreNulls
:
boolean
,
nullAsZero
:
boolean
nullAsZero
:
boolean
):
ColumnStats
{
):
ColumnStats
{
...
@@ -250,7 +250,7 @@ function standardStatsStat(
...
@@ -250,7 +250,7 @@ function standardStatsStat(
}
as
ColumnStats
;
}
as
ColumnStats
;
for
(
let
i
=
0
;
i
<
data
.
rows
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
data
.
rows
.
length
;
i
++
)
{
let
currentValue
=
data
.
rows
[
i
][
column
Index
];
let
currentValue
=
data
.
rows
[
i
][
field
Index
];
if
(
currentValue
===
null
)
{
if
(
currentValue
===
null
)
{
if
(
ignoreNulls
)
{
if
(
ignoreNulls
)
{
...
@@ -345,17 +345,17 @@ function standardStatsStat(
...
@@ -345,17 +345,17 @@ function standardStatsStat(
return
stats
;
return
stats
;
}
}
function
calculateFirst
(
data
:
TableData
,
column
Index
:
number
,
ignoreNulls
:
boolean
,
nullAsZero
:
boolean
):
ColumnStats
{
function
calculateFirst
(
data
:
SeriesData
,
field
Index
:
number
,
ignoreNulls
:
boolean
,
nullAsZero
:
boolean
):
ColumnStats
{
return
{
first
:
data
.
rows
[
0
][
column
Index
]
};
return
{
first
:
data
.
rows
[
0
][
field
Index
]
};
}
}
function
calculateLast
(
data
:
TableData
,
column
Index
:
number
,
ignoreNulls
:
boolean
,
nullAsZero
:
boolean
):
ColumnStats
{
function
calculateLast
(
data
:
SeriesData
,
field
Index
:
number
,
ignoreNulls
:
boolean
,
nullAsZero
:
boolean
):
ColumnStats
{
return
{
last
:
data
.
rows
[
data
.
rows
.
length
-
1
][
column
Index
]
};
return
{
last
:
data
.
rows
[
data
.
rows
.
length
-
1
][
field
Index
]
};
}
}
function
calculateChangeCount
(
function
calculateChangeCount
(
data
:
Table
Data
,
data
:
Series
Data
,
column
Index
:
number
,
field
Index
:
number
,
ignoreNulls
:
boolean
,
ignoreNulls
:
boolean
,
nullAsZero
:
boolean
nullAsZero
:
boolean
):
ColumnStats
{
):
ColumnStats
{
...
@@ -363,7 +363,7 @@ function calculateChangeCount(
...
@@ -363,7 +363,7 @@ function calculateChangeCount(
let
first
=
true
;
let
first
=
true
;
let
last
:
any
=
null
;
let
last
:
any
=
null
;
for
(
let
i
=
0
;
i
<
data
.
rows
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
data
.
rows
.
length
;
i
++
)
{
let
currentValue
=
data
.
rows
[
i
][
column
Index
];
let
currentValue
=
data
.
rows
[
i
][
field
Index
];
if
(
currentValue
===
null
)
{
if
(
currentValue
===
null
)
{
if
(
ignoreNulls
)
{
if
(
ignoreNulls
)
{
continue
;
continue
;
...
@@ -383,14 +383,14 @@ function calculateChangeCount(
...
@@ -383,14 +383,14 @@ function calculateChangeCount(
}
}
function
calculateDistinctCount
(
function
calculateDistinctCount
(
data
:
Table
Data
,
data
:
Series
Data
,
column
Index
:
number
,
field
Index
:
number
,
ignoreNulls
:
boolean
,
ignoreNulls
:
boolean
,
nullAsZero
:
boolean
nullAsZero
:
boolean
):
ColumnStats
{
):
ColumnStats
{
const
distinct
=
new
Set
<
any
>
();
const
distinct
=
new
Set
<
any
>
();
for
(
let
i
=
0
;
i
<
data
.
rows
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
data
.
rows
.
length
;
i
++
)
{
let
currentValue
=
data
.
rows
[
i
][
column
Index
];
let
currentValue
=
data
.
rows
[
i
][
field
Index
];
if
(
currentValue
===
null
)
{
if
(
currentValue
===
null
)
{
if
(
ignoreNulls
)
{
if
(
ignoreNulls
)
{
continue
;
continue
;
...
...
public/app/core/table_model.ts
View file @
77b3da3e
...
@@ -9,6 +9,7 @@ interface MutableColumn extends Column {
...
@@ -9,6 +9,7 @@ interface MutableColumn extends Column {
title
?:
string
;
title
?:
string
;
sort
?:
boolean
;
sort
?:
boolean
;
desc
?:
boolean
;
desc
?:
boolean
;
type
?:
string
;
}
}
export
default
class
TableModel
implements
TableData
{
export
default
class
TableModel
implements
TableData
{
...
...
public/app/features/dashboard/dashgrid/DataPanel.test.tsx
View file @
77b3da3e
// Library
// Library
import
React
from
'react'
;
import
React
from
'react'
;
import
{
DataPanel
,
getProcessed
Table
Data
}
from
'./DataPanel'
;
import
{
DataPanel
,
getProcessed
Series
Data
}
from
'./DataPanel'
;
describe
(
'DataPanel'
,
()
=>
{
describe
(
'DataPanel'
,
()
=>
{
let
dataPanel
:
DataPanel
;
let
dataPanel
:
DataPanel
;
...
@@ -34,27 +34,27 @@ describe('DataPanel', () => {
...
@@ -34,27 +34,27 @@ describe('DataPanel', () => {
target
:
''
,
target
:
''
,
datapoints
:
[[
100
,
1
],
[
200
,
2
]],
datapoints
:
[[
100
,
1
],
[
200
,
2
]],
};
};
const
data
=
getProcessed
Table
Data
([
null
,
input1
,
input2
,
null
,
null
]);
const
data
=
getProcessed
Series
Data
([
null
,
input1
,
input2
,
null
,
null
]);
expect
(
data
.
length
).
toBe
(
2
);
expect
(
data
.
length
).
toBe
(
2
);
expect
(
data
[
0
].
columns
[
0
].
text
).
toBe
(
input1
.
target
);
expect
(
data
[
0
].
fields
[
0
].
name
).
toBe
(
input1
.
target
);
expect
(
data
[
0
].
rows
).
toBe
(
input1
.
datapoints
);
expect
(
data
[
0
].
rows
).
toBe
(
input1
.
datapoints
);
// Default name
// Default name
expect
(
data
[
1
].
columns
[
0
].
text
).
toEqual
(
'Value'
);
expect
(
data
[
1
].
fields
[
0
].
name
).
toEqual
(
'Value'
);
// Every colun should have a name and a type
// Every colun should have a name and a type
for
(
const
table
of
data
)
{
for
(
const
table
of
data
)
{
for
(
const
column
of
table
.
column
s
)
{
for
(
const
column
of
table
.
field
s
)
{
expect
(
column
.
text
).
toBeDefined
();
expect
(
column
.
name
).
toBeDefined
();
expect
(
column
.
type
).
toBeDefined
();
expect
(
column
.
type
).
toBeDefined
();
}
}
}
}
});
});
it
(
'supports null values from query OK'
,
()
=>
{
it
(
'supports null values from query OK'
,
()
=>
{
expect
(
getProcessed
Table
Data
([
null
,
null
,
null
,
null
])).
toEqual
([]);
expect
(
getProcessed
Series
Data
([
null
,
null
,
null
,
null
])).
toEqual
([]);
expect
(
getProcessed
Table
Data
(
undefined
)).
toEqual
([]);
expect
(
getProcessed
Series
Data
(
undefined
)).
toEqual
([]);
expect
(
getProcessed
Table
Data
((
null
as
unknown
)
as
any
[])).
toEqual
([]);
expect
(
getProcessed
Series
Data
((
null
as
unknown
)
as
any
[])).
toEqual
([]);
expect
(
getProcessed
Table
Data
([])).
toEqual
([]);
expect
(
getProcessed
Series
Data
([])).
toEqual
([]);
});
});
});
});
public/app/features/dashboard/dashgrid/DataPanel.tsx
View file @
77b3da3e
...
@@ -11,16 +11,16 @@ import {
...
@@ -11,16 +11,16 @@ import {
DataQueryResponse
,
DataQueryResponse
,
DataQueryError
,
DataQueryError
,
LoadingState
,
LoadingState
,
Table
Data
,
Series
Data
,
TimeRange
,
TimeRange
,
ScopedVars
,
ScopedVars
,
to
Table
Data
,
to
Series
Data
,
guess
Column
Types
,
guess
Field
Types
,
}
from
'@grafana/ui'
;
}
from
'@grafana/ui'
;
interface
RenderProps
{
interface
RenderProps
{
loading
:
LoadingState
;
loading
:
LoadingState
;
data
:
Table
Data
[];
data
:
Series
Data
[];
}
}
export
interface
Props
{
export
interface
Props
{
...
@@ -44,7 +44,7 @@ export interface State {
...
@@ -44,7 +44,7 @@ export interface State {
isFirstLoad
:
boolean
;
isFirstLoad
:
boolean
;
loading
:
LoadingState
;
loading
:
LoadingState
;
response
:
DataQueryResponse
;
response
:
DataQueryResponse
;
data
?:
Table
Data
[];
data
?:
Series
Data
[];
}
}
/**
/**
...
@@ -52,18 +52,18 @@ export interface State {
...
@@ -52,18 +52,18 @@ export interface State {
*
*
* This is also used by PanelChrome for snapshot support
* This is also used by PanelChrome for snapshot support
*/
*/
export
function
getProcessed
TableData
(
results
?:
any
[]):
Table
Data
[]
{
export
function
getProcessed
SeriesData
(
results
?:
any
[]):
Series
Data
[]
{
if
(
!
results
)
{
if
(
!
results
)
{
return
[];
return
[];
}
}
const
tables
:
Table
Data
[]
=
[];
const
series
:
Series
Data
[]
=
[];
for
(
const
r
of
results
)
{
for
(
const
r
of
results
)
{
if
(
r
)
{
if
(
r
)
{
tables
.
push
(
guessColumnTypes
(
toTable
Data
(
r
)));
series
.
push
(
guessFieldTypes
(
toSeries
Data
(
r
)));
}
}
}
}
return
tabl
es
;
return
seri
es
;
}
}
export
class
DataPanel
extends
Component
<
Props
,
State
>
{
export
class
DataPanel
extends
Component
<
Props
,
State
>
{
...
@@ -167,7 +167,7 @@ export class DataPanel extends Component<Props, State> {
...
@@ -167,7 +167,7 @@ export class DataPanel extends Component<Props, State> {
this
.
setState
({
this
.
setState
({
loading
:
LoadingState
.
Done
,
loading
:
LoadingState
.
Done
,
response
:
resp
,
response
:
resp
,
data
:
getProcessed
Table
Data
(
resp
.
data
),
data
:
getProcessed
Series
Data
(
resp
.
data
),
isFirstLoad
:
false
,
isFirstLoad
:
false
,
});
});
}
catch
(
err
)
{
}
catch
(
err
)
{
...
...
public/app/features/dashboard/dashgrid/PanelChrome.tsx
View file @
77b3da3e
...
@@ -19,12 +19,12 @@ import config from 'app/core/config';
...
@@ -19,12 +19,12 @@ import config from 'app/core/config';
// Types
// Types
import
{
DashboardModel
,
PanelModel
}
from
'../state'
;
import
{
DashboardModel
,
PanelModel
}
from
'../state'
;
import
{
PanelPlugin
}
from
'app/types'
;
import
{
PanelPlugin
}
from
'app/types'
;
import
{
DataQueryResponse
,
TimeRange
,
LoadingState
,
TableData
,
DataQueryError
}
from
'@grafana/ui'
;
import
{
DataQueryResponse
,
TimeRange
,
LoadingState
,
DataQueryError
,
SeriesData
}
from
'@grafana/ui'
;
import
{
ScopedVars
}
from
'@grafana/ui'
;
import
{
ScopedVars
}
from
'@grafana/ui'
;
import
templateSrv
from
'app/features/templating/template_srv'
;
import
templateSrv
from
'app/features/templating/template_srv'
;
import
{
getProcessed
Table
Data
}
from
'./DataPanel'
;
import
{
getProcessed
Series
Data
}
from
'./DataPanel'
;
const
DEFAULT_PLUGIN_ERROR
=
'Error in plugin'
;
const
DEFAULT_PLUGIN_ERROR
=
'Error in plugin'
;
...
@@ -141,10 +141,10 @@ export class PanelChrome extends PureComponent<Props, State> {
...
@@ -141,10 +141,10 @@ export class PanelChrome extends PureComponent<Props, State> {
}
}
get
getDataForPanel
()
{
get
getDataForPanel
()
{
return
this
.
hasPanelSnapshot
?
getProcessed
Table
Data
(
this
.
props
.
panel
.
snapshotData
)
:
null
;
return
this
.
hasPanelSnapshot
?
getProcessed
Series
Data
(
this
.
props
.
panel
.
snapshotData
)
:
null
;
}
}
renderPanelPlugin
(
loading
:
LoadingState
,
data
:
Table
Data
[],
width
:
number
,
height
:
number
):
JSX
.
Element
{
renderPanelPlugin
(
loading
:
LoadingState
,
data
:
Series
Data
[],
width
:
number
,
height
:
number
):
JSX
.
Element
{
const
{
panel
,
plugin
}
=
this
.
props
;
const
{
panel
,
plugin
}
=
this
.
props
;
const
{
timeRange
,
renderCounter
}
=
this
.
state
;
const
{
timeRange
,
renderCounter
}
=
this
.
state
;
const
PanelComponent
=
plugin
.
exports
.
reactPanel
.
panel
;
const
PanelComponent
=
plugin
.
exports
.
reactPanel
.
panel
;
...
...
public/app/plugins/datasource/influxdb/influx_series.ts
View file @
77b3da3e
import
_
from
'lodash'
;
import
_
from
'lodash'
;
import
TableModel
from
'app/core/table_model'
;
import
TableModel
from
'app/core/table_model'
;
import
{
Column
Type
}
from
'@grafana/ui'
;
import
{
Field
Type
}
from
'@grafana/ui'
;
export
default
class
InfluxSeries
{
export
default
class
InfluxSeries
{
series
:
any
;
series
:
any
;
...
@@ -157,7 +157,7 @@ export default class InfluxSeries {
...
@@ -157,7 +157,7 @@ export default class InfluxSeries {
// Check that the first column is indeed 'time'
// Check that the first column is indeed 'time'
if
(
series
.
columns
[
0
]
===
'time'
)
{
if
(
series
.
columns
[
0
]
===
'time'
)
{
// Push this now before the tags and with the right type
// Push this now before the tags and with the right type
table
.
columns
.
push
({
text
:
'Time'
,
type
:
Column
Type
.
time
});
table
.
columns
.
push
({
text
:
'Time'
,
type
:
Field
Type
.
time
});
j
++
;
j
++
;
}
}
_
.
each
(
_
.
keys
(
series
.
tags
),
key
=>
{
_
.
each
(
_
.
keys
(
series
.
tags
),
key
=>
{
...
...
public/app/plugins/datasource/prometheus/result_transformer.ts
View file @
77b3da3e
import
_
from
'lodash'
;
import
_
from
'lodash'
;
import
TableModel
from
'app/core/table_model'
;
import
TableModel
from
'app/core/table_model'
;
import
{
TimeSeries
,
Column
Type
}
from
'@grafana/ui'
;
import
{
TimeSeries
,
Field
Type
}
from
'@grafana/ui'
;
export
class
ResultTransformer
{
export
class
ResultTransformer
{
constructor
(
private
templateSrv
)
{}
constructor
(
private
templateSrv
)
{}
...
@@ -98,7 +98,7 @@ export class ResultTransformer {
...
@@ -98,7 +98,7 @@ export class ResultTransformer {
// Sort metric labels, create columns for them and record their index
// Sort metric labels, create columns for them and record their index
const
sortedLabels
=
_
.
keys
(
metricLabels
).
sort
();
const
sortedLabels
=
_
.
keys
(
metricLabels
).
sort
();
table
.
columns
.
push
({
text
:
'Time'
,
type
:
Column
Type
.
time
});
table
.
columns
.
push
({
text
:
'Time'
,
type
:
Field
Type
.
time
});
_
.
each
(
sortedLabels
,
(
label
,
labelIndex
)
=>
{
_
.
each
(
sortedLabels
,
(
label
,
labelIndex
)
=>
{
metricLabels
[
label
]
=
labelIndex
+
1
;
metricLabels
[
label
]
=
labelIndex
+
1
;
table
.
columns
.
push
({
text
:
label
,
filterable
:
true
});
table
.
columns
.
push
({
text
:
label
,
filterable
:
true
});
...
...
public/app/plugins/panel/graph2/GraphPanel.tsx
View file @
77b3da3e
...
@@ -2,7 +2,7 @@
...
@@ -2,7 +2,7 @@
import
_
from
'lodash'
;
import
_
from
'lodash'
;
import
React
,
{
PureComponent
}
from
'react'
;
import
React
,
{
PureComponent
}
from
'react'
;
import
{
Graph
,
PanelProps
,
NullValueMode
,
colors
,
TimeSeriesVMs
,
ColumnType
,
getFirstTimeColumn
}
from
'@grafana/ui'
;
import
{
Graph
,
PanelProps
,
NullValueMode
,
colors
,
TimeSeriesVMs
,
FieldType
,
getFirstTimeField
}
from
'@grafana/ui'
;
import
{
Options
}
from
'./types'
;
import
{
Options
}
from
'./types'
;
import
{
getFlotPairs
}
from
'@grafana/ui/src/utils/flotPairs'
;
import
{
getFlotPairs
}
from
'@grafana/ui/src/utils/flotPairs'
;
...
@@ -15,16 +15,16 @@ export class GraphPanel extends PureComponent<Props> {
...
@@ -15,16 +15,16 @@ export class GraphPanel extends PureComponent<Props> {
const
vmSeries
:
TimeSeriesVMs
=
[];
const
vmSeries
:
TimeSeriesVMs
=
[];
for
(
const
table
of
data
)
{
for
(
const
table
of
data
)
{
const
timeColumn
=
getFirstTime
Column
(
table
);
const
timeColumn
=
getFirstTime
Field
(
table
);
if
(
timeColumn
<
0
)
{
if
(
timeColumn
<
0
)
{
continue
;
continue
;
}
}
for
(
let
i
=
0
;
i
<
table
.
column
s
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
table
.
field
s
.
length
;
i
++
)
{
const
column
=
table
.
column
s
[
i
];
const
column
=
table
.
field
s
[
i
];
// Show all numeric columns
// Show all numeric columns
if
(
column
.
type
===
Column
Type
.
number
)
{
if
(
column
.
type
===
Field
Type
.
number
)
{
// Use external calculator just to make sure it works :)
// Use external calculator just to make sure it works :)
const
points
=
getFlotPairs
({
const
points
=
getFlotPairs
({
rows
:
table
.
rows
,
rows
:
table
.
rows
,
...
@@ -34,7 +34,7 @@ export class GraphPanel extends PureComponent<Props> {
...
@@ -34,7 +34,7 @@ export class GraphPanel extends PureComponent<Props> {
});
});
vmSeries
.
push
({
vmSeries
.
push
({
label
:
column
.
text
,
label
:
column
.
name
,
data
:
points
,
data
:
points
,
color
:
colors
[
vmSeries
.
length
%
colors
.
length
],
color
:
colors
[
vmSeries
.
length
%
colors
.
length
],
...
...
public/app/plugins/panel/singlestat2/SingleStatPanel.tsx
View file @
77b3da3e
...
@@ -4,7 +4,7 @@ import React, { PureComponent, CSSProperties } from 'react';
...
@@ -4,7 +4,7 @@ import React, { PureComponent, CSSProperties } from 'react';
// Types
// Types
import
{
SingleStatOptions
,
SingleStatBaseOptions
}
from
'./types'
;
import
{
SingleStatOptions
,
SingleStatBaseOptions
}
from
'./types'
;
import
{
DisplayValue
,
PanelProps
,
NullValueMode
,
Column
Type
,
calculateStats
}
from
'@grafana/ui'
;
import
{
DisplayValue
,
PanelProps
,
NullValueMode
,
Field
Type
,
calculateStats
}
from
'@grafana/ui'
;
import
{
config
}
from
'app/core/config'
;
import
{
config
}
from
'app/core/config'
;
import
{
getDisplayProcessor
}
from
'@grafana/ui'
;
import
{
getDisplayProcessor
}
from
'@grafana/ui'
;
import
{
ProcessedValuesRepeater
}
from
'./ProcessedValuesRepeater'
;
import
{
ProcessedValuesRepeater
}
from
'./ProcessedValuesRepeater'
;
...
@@ -26,19 +26,19 @@ export const getSingleStatValues = (props: PanelProps<SingleStatBaseOptions>): D
...
@@ -26,19 +26,19 @@ export const getSingleStatValues = (props: PanelProps<SingleStatBaseOptions>): D
const
values
:
DisplayValue
[]
=
[];
const
values
:
DisplayValue
[]
=
[];
for
(
const
table
of
data
)
{
for
(
const
series
of
data
)
{
if
(
stat
===
'name'
)
{
if
(
stat
===
'name'
)
{
values
.
push
(
display
(
table
.
name
));
values
.
push
(
display
(
series
.
name
));
}
}
for
(
let
i
=
0
;
i
<
table
.
column
s
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
series
.
field
s
.
length
;
i
++
)
{
const
column
=
table
.
column
s
[
i
];
const
column
=
series
.
field
s
[
i
];
// Show all columns that are not 'time'
// Show all columns that are not 'time'
if
(
column
.
type
===
Column
Type
.
number
)
{
if
(
column
.
type
===
Field
Type
.
number
)
{
const
stats
=
calculateStats
({
const
stats
=
calculateStats
({
table
,
series
,
column
Index
:
i
,
field
Index
:
i
,
stats
:
[
stat
],
// The stats to calculate
stats
:
[
stat
],
// The stats to calculate
nullValueMode
:
NullValueMode
.
Null
,
nullValueMode
:
NullValueMode
.
Null
,
});
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment