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
91a2307b
Commit
91a2307b
authored
Mar 10, 2019
by
ryan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rotate!
parent
b80c773e
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
174 additions
and
79 deletions
+174
-79
packages/grafana-ui/src/components/Table/Table.story.tsx
+33
-15
packages/grafana-ui/src/components/Table/Table.tsx
+99
-59
packages/grafana-ui/src/components/Table/TableCellBuilder.tsx
+1
-0
packages/grafana-ui/src/components/Table/examples.ts
+2
-2
public/app/plugins/panel/table2/TablePanelEditor.tsx
+32
-3
public/app/plugins/panel/table2/types.ts
+7
-0
No files found.
packages/grafana-ui/src/components/Table/Table.story.tsx
View file @
91a2307b
...
...
@@ -19,17 +19,26 @@ const replaceVariables = (value: string, scopedVars?: ScopedVars) => {
return
value
;
};
export
function
makeDummyTable
(
columnCount
:
number
,
rowCount
:
number
):
TableData
{
export
function
columnIndexToLeter
(
column
:
number
)
{
const
A
=
'A'
.
charCodeAt
(
0
);
const
c1
=
Math
.
floor
(
column
/
26
);
const
c2
=
column
%
26
;
if
(
c1
>
0
)
{
return
String
.
fromCharCode
(
A
+
c1
-
1
)
+
String
.
fromCharCode
(
A
+
c2
);
}
return
String
.
fromCharCode
(
A
+
c2
);
}
export
function
makeDummyTable
(
columnCount
:
number
,
rowCount
:
number
):
TableData
{
return
{
columns
:
Array
.
from
(
new
Array
(
columnCount
),
(
x
,
i
)
=>
{
return
{
text
:
String
.
fromCharCode
(
A
+
i
),
text
:
columnIndexToLeter
(
i
),
};
}),
rows
:
Array
.
from
(
new
Array
(
rowCount
),
(
x
,
rowId
)
=>
{
const
suffix
=
(
rowId
+
1
).
toString
();
return
Array
.
from
(
new
Array
(
columnCount
),
(
x
,
colId
)
=>
String
.
fromCharCode
(
A
+
colId
)
+
suffix
);
return
Array
.
from
(
new
Array
(
columnCount
),
(
x
,
colId
)
=>
columnIndexToLeter
(
colId
)
+
suffix
);
}),
type
:
'table'
,
columnMap
:
{},
...
...
@@ -37,45 +46,54 @@ export function makeDummyTable(columnCount: number, rowCount: number): TableData
}
storiesOf
(
'Alpha/Table'
,
module
)
.
add
(
'basic'
,
()
=>
{
.
add
(
'Basic Table'
,
()
=>
{
// NOTE: This example does not seem to survice rotate &
// Changing fixed headers... but the next one does?
// perhaps `simpleTable` is static and reused?
const
showHeader
=
boolean
(
'Show Header'
,
true
);
const
fixedRowCount
=
number
(
'Fixed Rows'
,
1
,
{
min
:
0
,
max
:
50
,
step
:
1
,
range
:
false
});
const
fixedColumnCount
=
number
(
'Fixed Columns'
,
1
,
{
min
:
0
,
max
:
50
,
step
:
1
,
range
:
false
});
const
fixedHeader
=
boolean
(
'Fixed Header'
,
true
);
const
fixedColumns
=
number
(
'Fixed Columns'
,
0
,
{
min
:
0
,
max
:
50
,
step
:
1
,
range
:
false
});
const
rotate
=
boolean
(
'Rotate'
,
false
);
return
withFullSizeStory
(
Table
,
{
styles
:
[],
data
:
simpleTable
,
replaceVariables
,
fixedRowCount
,
fixedColumnCount
,
showHeader
,
fixedHeader
,
fixedColumns
,
rotate
,
theme
:
getTheme
(
GrafanaThemeType
.
Light
),
});
})
.
add
(
'
variable s
ize'
,
()
=>
{
const
columnCount
=
number
(
'Column Count'
,
20
,
{
min
:
2
,
max
:
50
,
step
:
1
,
range
:
false
});
.
add
(
'
Variable S
ize'
,
()
=>
{
const
columnCount
=
number
(
'Column Count'
,
15
,
{
min
:
2
,
max
:
50
,
step
:
1
,
range
:
false
});
const
rowCount
=
number
(
'Row Count'
,
20
,
{
min
:
0
,
max
:
100
,
step
:
1
,
range
:
false
});
const
showHeader
=
boolean
(
'Show Header'
,
true
);
const
fixedRowCount
=
number
(
'Fixed Rows'
,
1
,
{
min
:
0
,
max
:
50
,
step
:
1
,
range
:
false
});
const
fixedColumnCount
=
number
(
'Fixed Columns'
,
1
,
{
min
:
0
,
max
:
50
,
step
:
1
,
range
:
false
});
const
fixedHeader
=
boolean
(
'Fixed Header'
,
true
);
const
fixedColumns
=
number
(
'Fixed Columns'
,
1
,
{
min
:
0
,
max
:
50
,
step
:
1
,
range
:
false
});
const
rotate
=
boolean
(
'Rotate'
,
false
);
return
withFullSizeStory
(
Table
,
{
styles
:
[],
data
:
makeDummyTable
(
columnCount
,
rowCount
),
replaceVariables
,
fixedRowCount
,
fixedColumnCount
,
showHeader
,
fixedHeader
,
fixedColumns
,
rotate
,
theme
:
getTheme
(
GrafanaThemeType
.
Light
),
});
})
.
add
(
'
Old tests configuration
'
,
()
=>
{
.
add
(
'
Test Config (migrated)
'
,
()
=>
{
return
withFullSizeStory
(
Table
,
{
styles
:
migratedTestStyles
,
data
:
migratedTestTable
,
replaceVariables
,
showHeader
:
true
,
rotate
:
true
,
theme
:
getTheme
(
GrafanaThemeType
.
Light
),
});
});
packages/grafana-ui/src/components/Table/Table.tsx
View file @
91a2307b
...
...
@@ -14,21 +14,24 @@ import { Themeable } from '../../types/theme';
import
{
sortTableData
}
from
'../../utils/processTimeSeries'
;
import
{
TableData
,
InterpolateFunction
}
from
'@grafana/ui'
;
import
{
TableCellBuilder
,
ColumnStyle
,
getCellBuilder
,
TableCellBuilderOptions
}
from
'./TableCellBuilder'
;
import
{
TableCellBuilder
,
ColumnStyle
,
getCellBuilder
,
TableCellBuilderOptions
,
simpleCellBuilder
,
}
from
'./TableCellBuilder'
;
import
{
stringToJsRegex
}
from
'../../utils/index'
;
interface
ColumnInfo
{
index
:
number
;
header
:
string
;
builder
:
TableCellBuilder
;
}
export
interface
Props
extends
Themeable
{
data
:
TableData
;
showHeader
:
boolean
;
fixedColumnCount
:
number
;
fixedRowCount
:
number
;
fixedHeader
:
boolean
;
fixedColumns
:
number
;
rotate
:
boolean
;
styles
:
ColumnStyle
[];
replaceVariables
:
InterpolateFunction
;
width
:
number
;
height
:
number
;
...
...
@@ -41,15 +44,26 @@ interface State {
data
:
TableData
;
}
interface
ColumnRenderInfo
{
header
:
string
;
builder
:
TableCellBuilder
;
}
interface
DataIndex
{
column
:
number
;
row
:
number
;
// -1 is the header!
}
export
class
Table
extends
Component
<
Props
,
State
>
{
columns
:
Column
Info
[];
renderer
:
ColumnRender
Info
[];
measurer
:
CellMeasurerCache
;
scrollToTop
=
false
;
static
defaultProps
=
{
showHeader
:
true
,
fixedRowCount
:
1
,
fixedColumnCount
:
0
,
fixedHeader
:
true
,
fixedColumns
:
0
,
rotate
:
false
,
};
constructor
(
props
:
Props
)
{
...
...
@@ -59,7 +73,7 @@ export class Table extends Component<Props, State> {
data
:
props
.
data
,
};
this
.
columns
=
this
.
initColumns
(
props
);
this
.
renderer
=
this
.
initColumns
(
props
);
this
.
measurer
=
new
CellMeasurerCache
({
defaultHeight
:
30
,
defaultWidth
:
150
,
...
...
@@ -70,9 +84,11 @@ export class Table extends Component<Props, State> {
const
{
data
,
styles
,
showHeader
}
=
this
.
props
;
const
{
sortBy
,
sortDirection
}
=
this
.
state
;
const
dataChanged
=
data
!==
prevProps
.
data
;
const
configsChanged
=
showHeader
!==
prevProps
.
showHeader
;
console
.
log
(
'TABLE'
,
this
.
props
.
theme
);
const
configsChanged
=
showHeader
!==
prevProps
.
showHeader
||
this
.
props
.
rotate
!==
prevProps
.
rotate
||
this
.
props
.
fixedColumns
!==
prevProps
.
fixedColumns
||
this
.
props
.
fixedHeader
!==
prevProps
.
fixedHeader
;
// Reset the size cache
if
(
dataChanged
||
configsChanged
)
{
...
...
@@ -80,8 +96,9 @@ export class Table extends Component<Props, State> {
}
// Update the renderer if options change
// We only *need* do to this if the header values changes, but this does every data update
if
(
dataChanged
||
styles
!==
prevProps
.
styles
)
{
this
.
columns
=
this
.
initColumns
(
this
.
props
);
this
.
renderer
=
this
.
initColumns
(
this
.
props
);
}
// Update the data when data or sort changes
...
...
@@ -91,9 +108,9 @@ export class Table extends Component<Props, State> {
}
}
initColumns
(
props
:
Props
):
ColumnInfo
[]
{
/** Given the configuration, setup how each column gets rendered */
initColumns
(
props
:
Props
):
ColumnRenderInfo
[]
{
const
{
styles
,
data
}
=
props
;
console
.
log
(
'STYLES'
,
styles
);
return
data
.
columns
.
map
((
col
,
index
)
=>
{
let
title
=
col
.
text
;
...
...
@@ -113,7 +130,6 @@ export class Table extends Component<Props, State> {
}
return
{
index
,
header
:
title
,
builder
:
getCellBuilder
(
col
,
style
,
this
.
props
),
};
...
...
@@ -137,27 +153,37 @@ export class Table extends Component<Props, State> {
this
.
setState
({
sortBy
:
sort
,
sortDirection
:
dir
});
};
/** Converts the grid coordinates to TableData coordinates */
getCellRef
=
(
rowIndex
:
number
,
columnIndex
:
number
):
DataIndex
=>
{
const
{
showHeader
,
rotate
}
=
this
.
props
;
const
rowOffset
=
showHeader
?
-
1
:
0
;
if
(
rotate
)
{
return
{
column
:
rowIndex
,
row
:
columnIndex
+
rowOffset
};
}
else
{
return
{
column
:
columnIndex
,
row
:
rowIndex
+
rowOffset
};
}
};
handleCellClick
=
(
rowIndex
:
number
,
columnIndex
:
number
)
=>
{
const
{
showHeader
}
=
this
.
props
;
const
{
data
}
=
this
.
state
;
const
realRowIndex
=
rowIndex
-
(
showHeader
?
1
:
0
);
if
(
realRowIndex
<
0
)
{
this
.
doSort
(
columnIndex
);
const
{
row
,
column
}
=
this
.
getCellRef
(
rowIndex
,
columnIndex
);
if
(
row
<
0
)
{
this
.
doSort
(
column
);
}
else
{
const
row
=
data
.
rows
[
realRowIndex
];
const
value
=
row
[
columnIndex
];
console
.
log
(
'CLICK'
,
rowIndex
,
columnIndex
,
value
);
const
values
=
this
.
state
.
data
.
rows
[
row
];
const
value
=
values
[
column
];
console
.
log
(
'CLICK'
,
value
,
row
);
}
};
headerBuilder
=
(
cell
:
TableCellBuilderOptions
):
ReactElement
<
'div'
>
=>
{
const
{
data
,
sortBy
,
sortDirection
}
=
this
.
state
;
const
{
columnIndex
,
rowIndex
,
style
}
=
cell
.
props
;
const
{
column
}
=
this
.
getCellRef
(
rowIndex
,
columnIndex
);
let
col
=
data
.
columns
[
column
Index
];
const
sorting
=
sortBy
===
column
Index
;
let
col
=
data
.
columns
[
column
];
const
sorting
=
sortBy
===
column
;
if
(
!
col
)
{
// NOT SURE Why this happens sometimes
col
=
{
text
:
'??'
+
columnIndex
+
'???'
,
};
...
...
@@ -171,47 +197,60 @@ export class Table extends Component<Props, State> {
);
};
getTableCellBuilder
=
(
column
:
number
):
TableCellBuilder
=>
{
const
render
=
this
.
renderer
[
column
];
if
(
render
&&
render
.
builder
)
{
return
render
.
builder
;
}
return
simpleCellBuilder
;
// the default
};
cellRenderer
=
(
props
:
GridCellProps
):
React
.
ReactNode
=>
{
const
{
rowIndex
,
columnIndex
,
key
,
parent
}
=
props
;
const
{
showHeader
}
=
this
.
props
;
const
{
row
,
column
}
=
this
.
getCellRef
(
rowIndex
,
columnIndex
)
;
const
{
data
}
=
this
.
state
;
const
column
=
this
.
columns
[
columnIndex
];
if
(
!
column
)
{
// NOT SURE HOW/WHY THIS HAPPENS!
// Without it it will crash in storybook when you cycle up/down the # of columns
// this cell is never visible in the output?
return
(
<
div
key=
{
key
}
style=
{
props
.
style
}
>
XXXXX
</
div
>
);
}
const
realRowIndex
=
rowIndex
-
(
showHeader
?
1
:
0
);
const
isHeader
=
realRowIndex
<
0
;
const
row
=
isHeader
?
data
.
columns
:
data
.
rows
[
realRowIndex
];
const
value
=
row
[
columnIndex
];
const
builder
=
isHeader
?
this
.
headerBuilder
:
column
.
builder
;
const
isHeader
=
row
<
0
;
const
rowData
=
isHeader
?
data
.
columns
:
data
.
rows
[
row
];
const
value
=
rowData
?
rowData
[
column
]
:
`[
${
columnIndex
}
:
${
rowIndex
}
]`
;
const
builder
=
isHeader
?
this
.
headerBuilder
:
this
.
getTableCellBuilder
(
column
);
return
(
<
CellMeasurer
cache=
{
this
.
measurer
}
columnIndex=
{
columnIndex
}
key=
{
key
}
parent=
{
parent
}
rowIndex=
{
rowIndex
}
>
{
builder
({
value
,
row
,
table
:
this
,
props
})
}
{
builder
({
value
,
row
:
rowData
,
column
:
data
.
columns
[
column
],
table
:
this
,
props
,
})
}
</
CellMeasurer
>
);
};
render
()
{
const
{
data
,
showHeader
,
width
,
height
}
=
this
.
props
;
const
{
showHeader
,
fixedHeader
,
fixedColumns
,
rotate
,
width
,
height
}
=
this
.
props
;
const
{
data
}
=
this
.
state
;
cons
t
columnCount
=
data
.
columns
.
length
;
cons
t
rowCount
=
data
.
rows
.
length
+
(
showHeader
?
1
:
0
);
le
t
columnCount
=
data
.
columns
.
length
;
le
t
rowCount
=
data
.
rows
.
length
+
(
showHeader
?
1
:
0
);
const
fixedColumnCount
=
Math
.
min
(
this
.
props
.
fixedColumnCount
,
columnCount
);
const
fixedRowCount
=
Math
.
min
(
this
.
props
.
fixedRowCount
,
rowCount
);
let
fixedColumnCount
=
Math
.
min
(
fixedColumns
,
columnCount
);
let
fixedRowCount
=
showHeader
&&
fixedHeader
?
1
:
0
;
if
(
rotate
)
{
const
temp
=
columnCount
;
columnCount
=
rowCount
;
rowCount
=
temp
;
fixedRowCount
=
0
;
fixedColumnCount
=
Math
.
min
(
fixedColumns
,
rowCount
)
+
(
showHeader
&&
fixedHeader
?
1
:
0
);
}
// Usually called after a sort or the data changes
const
scrollToRow
=
this
.
scrollToTop
?
1
:
-
1
;
// Called after sort or the data changes
const
scroll
=
this
.
scrollToTop
?
1
:
-
1
;
const
scrollToRow
=
rotate
?
-
1
:
scroll
;
const
scrollToColumn
=
rotate
?
scroll
:
-
1
;
if
(
this
.
scrollToTop
)
{
this
.
scrollToTop
=
false
;
}
...
...
@@ -226,9 +265,10 @@ export class Table extends Component<Props, State> {
}
scrollToRow=
{
scrollToRow
}
columnCount=
{
columnCount
}
scrollToColumn=
{
scrollToColumn
}
rowCount=
{
rowCount
}
overscanColumnCount=
{
2
}
overscanRowCount=
{
2
}
overscanColumnCount=
{
8
}
overscanRowCount=
{
8
}
columnWidth=
{
this
.
measurer
.
columnWidth
}
deferredMeasurementCache=
{
this
.
measurer
}
cellRenderer=
{
this
.
cellRenderer
}
...
...
packages/grafana-ui/src/components/Table/TableCellBuilder.tsx
View file @
91a2307b
...
...
@@ -11,6 +11,7 @@ import { InterpolateFunction } from '../../types/panel';
export
interface
TableCellBuilderOptions
{
value
:
any
;
column
?:
Column
;
row
?:
any
[];
table
?:
Table
;
className
?:
string
;
...
...
packages/grafana-ui/src/components/Table/examples.ts
View file @
91a2307b
...
...
@@ -163,5 +163,5 @@ export const migratedTestStyles: ColumnStyle[] = [
export
const
simpleTable
=
{
type
:
'table'
,
columns
:
[{
text
:
'First'
},
{
text
:
'Second'
},
{
text
:
'Third'
}],
rows
:
[[
10
,
23
,
35
],
[
11
,
22
,
31
],
[
12
,
21
,
3
4
]],
}
as
TableData
;
rows
:
[[
701
,
205
,
305
],
[
702
,
206
,
301
],
[
703
,
207
,
30
4
]],
};
public/app/plugins/panel/table2/TablePanelEditor.tsx
View file @
91a2307b
...
...
@@ -3,7 +3,7 @@ import _ from 'lodash';
import
React
,
{
PureComponent
}
from
'react'
;
// Types
import
{
PanelEditorProps
,
Switch
}
from
'@grafana/ui'
;
import
{
PanelEditorProps
,
Switch
,
FormField
}
from
'@grafana/ui'
;
import
{
Options
}
from
'./types'
;
export
class
TablePanelEditor
extends
PureComponent
<
PanelEditorProps
<
Options
>>
{
...
...
@@ -11,14 +11,43 @@ export class TablePanelEditor extends PureComponent<PanelEditorProps<Options>> {
this
.
props
.
onOptionsChange
({
...
this
.
props
.
options
,
showHeader
:
!
this
.
props
.
options
.
showHeader
});
};
onToggleFixedHeader
=
()
=>
{
this
.
props
.
onOptionsChange
({
...
this
.
props
.
options
,
fixedHeader
:
!
this
.
props
.
options
.
fixedHeader
});
};
onToggleRotate
=
()
=>
{
this
.
props
.
onOptionsChange
({
...
this
.
props
.
options
,
rotate
:
!
this
.
props
.
options
.
rotate
});
};
onFixedColumnsChange
=
({
target
})
=>
{
this
.
props
.
onOptionsChange
({
...
this
.
props
.
options
,
fixedColumns
:
target
.
value
});
};
render
()
{
const
{
showHeader
}
=
this
.
props
.
options
;
const
{
showHeader
,
fixedHeader
,
rotate
,
fixedColumns
}
=
this
.
props
.
options
;
return
(
<
div
>
<
div
className=
"section gf-form-group"
>
<
h5
className=
"section-heading"
>
Header
</
h5
>
<
Switch
label=
"Show"
labelClass=
"width-5"
checked=
{
showHeader
}
onChange=
{
this
.
onToggleShowHeader
}
/>
<
Switch
label=
"Show"
labelClass=
"width-6"
checked=
{
showHeader
}
onChange=
{
this
.
onToggleShowHeader
}
/>
<
Switch
label=
"Fixed"
labelClass=
"width-6"
checked=
{
fixedHeader
}
onChange=
{
this
.
onToggleFixedHeader
}
/>
</
div
>
<
div
className=
"section gf-form-group"
>
<
h5
className=
"section-heading"
>
Display
</
h5
>
<
Switch
label=
"Rotate"
labelClass=
"width-8"
checked=
{
rotate
}
onChange=
{
this
.
onToggleRotate
}
/>
<
FormField
label=
"Fixed Columns"
labelWidth=
{
8
}
inputWidth=
{
4
}
type=
"number"
step=
"1"
min=
"0"
max=
"100"
onChange=
{
this
.
onFixedColumnsChange
}
value=
{
fixedColumns
}
/>
</
div
>
</
div
>
);
...
...
public/app/plugins/panel/table2/types.ts
View file @
91a2307b
...
...
@@ -2,11 +2,18 @@ import { ColumnStyle } from '@grafana/ui/src/components/Table/TableCellBuilder';
export
interface
Options
{
showHeader
:
boolean
;
fixedHeader
:
boolean
;
fixedColumns
:
number
;
rotate
:
boolean
;
styles
:
ColumnStyle
[];
}
export
const
defaults
:
Options
=
{
showHeader
:
true
,
fixedHeader
:
true
,
fixedColumns
:
0
,
rotate
:
false
,
styles
:
[
{
type
:
'date'
,
...
...
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