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
0d8384e0
Commit
0d8384e0
authored
Mar 06, 2019
by
ryan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
sortable class
parent
f7c1842a
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
149 additions
and
80 deletions
+149
-80
public/app/plugins/panel/table2/TablePanel.tsx
+84
-48
public/app/plugins/panel/table2/renderer.tsx
+15
-15
public/app/plugins/panel/table2/sortable.tsx
+41
-0
public/app/plugins/panel/table2/specs/renderer.test.ts
+5
-2
public/app/plugins/panel/table2/types.ts
+0
-11
public/sass/components/_panel_table2.scss
+4
-4
No files found.
public/app/plugins/panel/table2/TablePanel.tsx
View file @
0d8384e0
...
...
@@ -3,18 +3,19 @@ import _ from 'lodash';
import
React
,
{
Component
,
ReactNode
}
from
'react'
;
// Types
import
{
PanelProps
}
from
'@grafana/ui/src/types
'
;
import
{
PanelProps
,
ThemeContext
}
from
'@grafana/ui
'
;
import
{
Options
}
from
'./types'
;
import
{
Table
,
SortDirectionType
,
SortIndicator
,
Column
,
TableHeaderProps
,
TableCellProps
}
from
'react-virtualized'
;
import
{
TableRenderer
}
from
'./renderer'
;
import
{
SortedTableData
}
from
'./sortable'
;
interface
Props
extends
PanelProps
<
Options
>
{}
interface
State
{
sortBy
:
string
;
sortDirection
:
SortDirectionType
;
sortedList
:
any
[]
;
sortBy
?:
number
;
// but really is a number!
sortDirection
?
:
SortDirectionType
;
data
:
SortedTableData
;
}
export
class
TablePanel
extends
Component
<
Props
,
State
>
{
...
...
@@ -22,55 +23,87 @@ export class TablePanel extends Component<Props, State> {
constructor
(
props
:
Props
)
{
super
(
props
);
const
{
panelData
,
options
,
replaceVariables
}
=
this
.
props
;
this
.
state
=
{
sortBy
:
'XX'
,
sortDirection
:
'ASC'
,
sortedList
:
[],
data
:
new
SortedTableData
(
panelData
.
tableData
),
};
const
{
panelData
,
options
,
replaceVariables
}
=
this
.
props
;
const
theme
=
null
;
// TODO?
this
.
renderer
=
new
TableRenderer
(
options
.
styles
,
this
.
state
.
data
,
this
.
_rowGetter
,
replaceVariables
)
;
}
this
.
renderer
=
new
TableRenderer
(
panelData
.
tableData
,
options
,
replaceVariables
,
theme
);
componentDidUpdate
(
prevProps
:
Props
,
prevState
:
State
)
{
const
{
panelData
,
options
}
=
this
.
props
;
const
{
sortBy
,
sortDirection
}
=
this
.
state
;
console
.
log
(
'componentDidUpdate'
,
this
.
props
);
// Update the renderer if options change
if
(
options
!==
prevProps
.
options
)
{
console
.
log
(
'Options Changed, update renderer'
,
options
);
this
.
renderer
=
new
TableRenderer
(
options
.
styles
,
this
.
state
.
data
,
this
.
_rowGetter
,
this
.
props
.
replaceVariables
);
}
// Update the data when data or sort changes
if
(
panelData
!==
prevProps
.
panelData
||
sortBy
!==
prevState
.
sortBy
||
sortDirection
!==
prevState
.
sortDirection
)
{
const
data
=
new
SortedTableData
(
panelData
.
tableData
,
sortBy
,
sortDirection
===
'DESC'
);
this
.
setState
({
data
});
console
.
log
(
'Data Changed, update'
,
data
);
}
}
_rowGetter
=
({
index
})
=>
{
return
this
.
props
.
panelData
.
tableData
.
rows
[
index
]
;
return
this
.
state
.
data
.
getRow
(
index
)
;
};
_sort
=
({
sortBy
,
sortDirection
})
=>
{
// const sortedList = this._sortList({sortBy, sortDirection});
_sort
=
({
sortBy
})
=>
{
let
sortDirection
=
this
.
state
.
sortDirection
;
if
(
sortBy
!==
this
.
state
.
sortBy
)
{
sortDirection
=
'DESC'
;
}
else
if
(
sortDirection
===
'DESC'
)
{
sortDirection
=
'ASC'
;
}
else
{
sortBy
=
null
;
}
// This will trigger sort via properties
console
.
log
(
'SORT'
,
sortBy
,
typeof
sortBy
,
sortDirection
);
// this.setState({sortBy, sortDirection, sortedList});
console
.
log
(
'TODO, sort!'
,
sortBy
,
sortDirection
);
this
.
setState
({
sortBy
,
sortDirection
});
};
_headerRenderer
=
(
header
:
TableHeaderProps
):
ReactNode
=>
{
const
{
sortBy
,
dataKey
,
sortDirection
}
=
header
;
const
tableData
=
this
.
props
.
panelData
.
tableData
!
;
const
col
=
tableData
.
columns
[
dataKey
];
const
dataKey
=
header
.
dataKey
as
any
;
// types say string, but it is number?
const
{
data
,
sortBy
,
sortDirection
}
=
this
.
state
;
const
col
=
data
.
getInfo
()[
dataKey
];
if
(
!
col
)
{
return
<
div
>
??
{
dataKey
}
??
</
div
>;
}
const
isSorted
=
sortBy
===
dataKey
;
console
.
log
(
'header SORT'
,
sortBy
,
isSorted
);
return
(
<
div
>
{
col
.
text
}
{
sortBy
===
dataKey
&&
<
SortIndicator
sortDirection=
{
sortDirection
}
/>
}
{
col
.
text
}
{
isSorted
&&
<
SortIndicator
sortDirection=
{
sortDirection
}
/>
}
</
div
>
);
};
_cellRenderer
=
(
cell
:
TableCellProps
)
=>
{
const
{
columnIndex
,
rowIndex
}
=
cell
;
const
tableData
=
this
.
props
.
panelData
.
tableData
!
;
const
val
=
tableData
.
rows
[
rowIndex
]
[
columnIndex
];
const
row
=
this
.
state
.
data
.
getRow
(
rowIndex
)
;
const
val
=
row
[
columnIndex
];
return
this
.
renderer
.
renderCell
(
columnIndex
,
rowIndex
,
val
);
};
render
()
{
const
{
panelData
,
width
,
height
,
options
}
=
this
.
props
;
const
{
showHeader
}
=
options
;
const
{
sortBy
,
sortDirection
}
=
this
.
state
;
//
const { sortBy, sortDirection } = this.state;
const
{
tableData
}
=
panelData
;
if
(
!
tableData
||
tableData
.
rows
.
length
<
1
)
{
...
...
@@ -78,32 +111,35 @@ export class TablePanel extends Component<Props, State> {
}
return
(
<
Table
disableHeader=
{
!
showHeader
}
headerHeight=
{
30
}
height=
{
height
}
overscanRowCount=
{
10
}
rowHeight=
{
30
}
rowGetter=
{
this
.
_rowGetter
}
rowCount=
{
tableData
.
rows
.
length
}
sort=
{
this
.
_sort
}
sortBy=
{
sortBy
}
sortDirection=
{
sortDirection
}
width=
{
width
}
>
{
tableData
.
columns
.
map
((
col
,
index
)
=>
{
return
(
<
Column
key=
{
index
}
dataKey=
{
index
}
headerRenderer=
{
this
.
_headerRenderer
}
cellRenderer=
{
this
.
_cellRenderer
}
flexGrow=
{
1
}
width=
{
60
}
/>
);
})
}
</
Table
>
<
ThemeContext
.
Consumer
>
{
(
theme
// ???
{
this
.
renderer
.
setTheme
(
theme
)
}
)
=>
(
<
Table
disableHeader=
{
!
showHeader
}
headerHeight=
{
30
}
height=
{
height
}
overscanRowCount=
{
10
}
rowHeight=
{
30
}
rowGetter=
{
this
.
_rowGetter
}
rowCount=
{
tableData
.
rows
.
length
}
sort=
{
this
.
_sort
}
width=
{
width
}
>
{
tableData
.
columns
.
map
((
col
,
index
)
=>
{
return
(
<
Column
key=
{
index
}
dataKey=
{
index
}
headerRenderer=
{
this
.
_headerRenderer
}
cellRenderer=
{
this
.
_cellRenderer
}
width=
{
300
}
/>
);
})
}
</
Table
>
)
}
</
ThemeContext
.
Consumer
>
);
}
}
public/app/plugins/panel/table2/renderer.tsx
View file @
0d8384e0
...
...
@@ -7,14 +7,10 @@ import { sanitize } from 'app/core/utils/text';
// Types
import
kbn
from
'app/core/utils/kbn'
;
import
{
getValueFormat
,
getColorFromHexRgbOrName
,
GrafanaThemeType
,
InterpolateFunction
,
TableData
,
}
from
'@grafana/ui'
;
import
{
Options
,
Style
}
from
'./types'
;
import
{
getValueFormat
,
getColorFromHexRgbOrName
,
GrafanaThemeType
,
InterpolateFunction
}
from
'@grafana/ui'
;
import
{
Style
}
from
'./types'
;
import
{
SortedTableData
}
from
'./sortable'
;
import
{
Index
}
from
'react-virtualized'
;
type
CellFormatter
=
(
v
:
any
,
style
:
Style
)
=>
string
;
...
...
@@ -32,12 +28,13 @@ export class TableRenderer {
columns
:
ColumnInfo
[];
colorState
:
any
;
theme
?:
GrafanaThemeType
;
constructor
(
private
data
:
TableData
,
options
:
Options
,
private
r
eplaceVariables
:
InterpolateFunction
,
private
theme
?:
GrafanaThemeType
styles
:
Style
[]
,
data
:
SortedTableData
,
private
r
owGetter
:
(
info
:
Index
)
=>
any
[],
// matches the table rowGetter
private
replaceVariables
:
InterpolateFunction
)
{
this
.
colorState
=
{};
...
...
@@ -45,9 +42,8 @@ export class TableRenderer {
this
.
columns
=
[];
return
;
}
const
{
styles
}
=
options
;
this
.
columns
=
data
.
columns
.
map
((
col
,
index
)
=>
{
this
.
columns
=
data
.
getInfo
()
.
map
((
col
,
index
)
=>
{
let
title
=
col
.
text
;
let
style
:
Style
=
null
;
...
...
@@ -72,6 +68,10 @@ export class TableRenderer {
});
}
setTheme
(
theme
:
GrafanaThemeType
)
{
this
.
theme
=
theme
;
}
getColorForValue
(
value
,
style
:
Style
)
{
if
(
!
style
.
thresholds
)
{
return
null
;
...
...
@@ -222,7 +222,7 @@ export class TableRenderer {
renderRowVariables
(
rowIndex
:
number
)
{
const
scopedVars
=
{};
const
row
=
this
.
data
.
rows
[
rowIndex
]
;
const
row
=
this
.
rowGetter
({
index
:
rowIndex
})
;
for
(
let
i
=
0
;
i
<
row
.
length
;
i
++
)
{
scopedVars
[
`__cell_
${
i
}
`
]
=
{
value
:
row
[
i
]
};
}
...
...
public/app/plugins/panel/table2/sortable.tsx
0 → 100644
View file @
0d8384e0
// Libraries
import
_
from
'lodash'
;
import
{
TableData
}
from
'@grafana/ui'
;
export
class
SortedTableData
{
rows
:
any
[];
constructor
(
private
data
:
TableData
,
sortIndex
?:
number
,
reverse
?:
boolean
)
{
if
(
_
.
isNumber
(
sortIndex
))
{
// Make a copy of all the rows
this
.
rows
=
this
.
data
.
rows
.
map
((
row
,
index
)
=>
{
return
row
;
});
this
.
rows
.
sort
((
a
,
b
)
=>
{
a
=
a
[
sortIndex
];
b
=
b
[
sortIndex
];
// Sort null or undefined separately from comparable values
return
+
(
a
==
null
)
-
+
(
b
==
null
)
||
+
(
a
>
b
)
||
-
(
a
<
b
);
});
if
(
reverse
)
{
this
.
rows
.
reverse
();
}
}
else
{
this
.
rows
=
data
.
rows
;
}
}
getInfo
():
any
[]
{
return
this
.
data
.
columns
;
}
getRow
(
index
:
number
):
any
[]
{
return
this
.
rows
[
index
];
}
getCount
():
number
{
return
this
.
rows
.
length
;
}
}
public/app/plugins/panel/table2/specs/renderer.test.ts
View file @
0d8384e0
...
...
@@ -6,6 +6,7 @@ import { Options } from '../types';
import
{
PanelProps
,
LoadingState
}
from
'@grafana/ui/src/types'
;
import
moment
from
'moment'
;
import
{
TableRenderer
}
from
'../renderer'
;
import
{
SortedTableData
}
from
'../sortable'
;
// TODO: this is commented out with *x* describe!
// Essentially all the elements need to replace the <td> with <div>
...
...
@@ -203,8 +204,10 @@ xdescribe('when rendering table', () => {
renderCounter
:
1
,
options
:
panel
,
};
const
theme
=
null
;
const
renderer
=
new
TableRenderer
(
table
,
panel
,
props
.
replaceVariables
,
theme
);
//panel, table, 'utc', sanitize, templateSrv);
const
data
=
new
SortedTableData
(
table
);
const
rowGetter
=
({
index
})
=>
data
.
getRow
(
index
);
const
renderer
=
new
TableRenderer
(
panel
.
styles
,
data
,
rowGetter
,
props
.
replaceVariables
);
renderer
.
setTheme
(
null
);
it
(
'time column should be formated'
,
()
=>
{
const
html
=
renderer
.
renderCell
(
0
,
0
,
1388556366666
);
...
...
public/app/plugins/panel/table2/types.ts
View file @
0d8384e0
...
...
@@ -22,17 +22,6 @@ export interface Style {
preserveFormat
?:
boolean
;
}
export
type
CellFormatter
=
(
v
:
any
,
style
:
Style
)
=>
string
;
export
interface
ColumnInfo
{
header
:
string
;
accessor
:
string
;
// the field name
style
?:
Style
;
hidden
?:
boolean
;
formatter
:
CellFormatter
;
filterable
?:
boolean
;
}
export
interface
Options
{
showHeader
:
boolean
;
styles
:
Style
[];
...
...
public/sass/components/_panel_table2.scss
View file @
0d8384e0
.ReactVirtualized__Table
{
}
//
.ReactVirtualized__Table {
//
}
.ReactVirtualized__Table__Grid
{
}
//
.ReactVirtualized__Table__Grid {
//
}
.ReactVirtualized__Table__headerRow
{
font-weight
:
700
;
...
...
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