mirror of https://github.com/grafana/grafana.git
				
				
				
			use react-table
This commit is contained in:
		
							parent
							
								
									f59ccdf59c
								
							
						
					
					
						commit
						372e892fab
					
				|  | @ -1,67 +1,376 @@ | ||||||
| // Libraries
 | // Libraries
 | ||||||
| import _ from 'lodash'; | import _ from 'lodash'; | ||||||
|  | import moment from 'moment'; | ||||||
| import React, { PureComponent } from 'react'; | import React, { PureComponent } from 'react'; | ||||||
| 
 | 
 | ||||||
|  | import ReactTable from 'react-table'; | ||||||
|  | 
 | ||||||
|  | import { sanitize } from 'app/core/utils/text'; | ||||||
|  | 
 | ||||||
| // Types
 | // Types
 | ||||||
| import { PanelProps } from '@grafana/ui/src/types'; | import { PanelProps } from '@grafana/ui/src/types'; | ||||||
| import { Options } from './types'; | import { Options, Style, Column, CellFormatter } from './types'; | ||||||
|  | import kbn from 'app/core/utils/kbn'; | ||||||
| 
 | 
 | ||||||
| import { Table, Index, Column } from 'react-virtualized'; | import templateSrv from 'app/features/templating/template_srv'; | ||||||
| 
 | 
 | ||||||
| interface Props extends PanelProps<Options> {} | interface Props extends PanelProps<Options> {} | ||||||
| 
 | 
 | ||||||
| export class TablePanel extends PureComponent<Props> { | export class TablePanel extends PureComponent<Props> { | ||||||
|   getRow = (index: Index): any => { |   isUTC: false; // TODO? get UTC from props?
 | ||||||
|     const { panelData } = this.props; | 
 | ||||||
|     if (panelData.tableData) { |   columns: Column[]; | ||||||
|       return panelData.tableData.rows[index.index]; |   colorState: any; | ||||||
|  | 
 | ||||||
|  |   initColumns() { | ||||||
|  |     this.colorState = {}; | ||||||
|  | 
 | ||||||
|  |     const { panelData, options } = this.props; | ||||||
|  |     if (!panelData.tableData) { | ||||||
|  |       this.columns = []; | ||||||
|  |       return; | ||||||
|     } |     } | ||||||
|     return null; |     const { styles } = options; | ||||||
|   }; | 
 | ||||||
|  |     this.columns = panelData.tableData.columns.map((col, index) => { | ||||||
|  |       let title = col.text; | ||||||
|  |       let style: Style = null; | ||||||
|  | 
 | ||||||
|  |       for (let i = 0; i < styles.length; i++) { | ||||||
|  |         const s = styles[i]; | ||||||
|  |         const regex = kbn.stringToJsRegex(s.pattern); | ||||||
|  |         if (title.match(regex)) { | ||||||
|  |           style = s; | ||||||
|  |           if (s.alias) { | ||||||
|  |             title = title.replace(regex, s.alias); | ||||||
|  |           } | ||||||
|  |           break; | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       return { | ||||||
|  |         header: title, | ||||||
|  |         accessor: col.text, // unique?
 | ||||||
|  |         style: style, | ||||||
|  |         formatter: this.createColumnFormatter(style, col), | ||||||
|  |       }; | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   getColorForValue(value: any, style: Style) { | ||||||
|  |     if (!style.thresholds) { | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|  |     for (let i = style.thresholds.length; i > 0; i--) { | ||||||
|  |       if (value >= style.thresholds[i - 1]) { | ||||||
|  |         return style.colors[i]; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return _.first(style.colors); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   defaultCellFormatter(v: any, style: Style): string { | ||||||
|  |     if (v === null || v === void 0 || v === undefined) { | ||||||
|  |       return ''; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (_.isArray(v)) { | ||||||
|  |       v = v.join(', '); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (style && style.sanitize) { | ||||||
|  |       return sanitize(v); | ||||||
|  |     } else { | ||||||
|  |       return _.escape(v); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   createColumnFormatter(style: Style, header: any): CellFormatter { | ||||||
|  |     if (!style) { | ||||||
|  |       return this.defaultCellFormatter; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (style.type === 'hidden') { | ||||||
|  |       return v => { | ||||||
|  |         return undefined; | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (style.type === 'date') { | ||||||
|  |       return v => { | ||||||
|  |         if (v === undefined || v === null) { | ||||||
|  |           return '-'; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (_.isArray(v)) { | ||||||
|  |           v = v[0]; | ||||||
|  |         } | ||||||
|  |         let date = moment(v); | ||||||
|  |         if (this.isUTC) { | ||||||
|  |           date = date.utc(); | ||||||
|  |         } | ||||||
|  |         return date.format(style.dateFormat); | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (style.type === 'string') { | ||||||
|  |       return v => { | ||||||
|  |         if (_.isArray(v)) { | ||||||
|  |           v = v.join(', '); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const mappingType = style.mappingType || 0; | ||||||
|  | 
 | ||||||
|  |         if (mappingType === 1 && style.valueMaps) { | ||||||
|  |           for (let i = 0; i < style.valueMaps.length; i++) { | ||||||
|  |             const map = style.valueMaps[i]; | ||||||
|  | 
 | ||||||
|  |             if (v === null) { | ||||||
|  |               if (map.value === 'null') { | ||||||
|  |                 return map.text; | ||||||
|  |               } | ||||||
|  |               continue; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Allow both numeric and string values to be mapped
 | ||||||
|  |             if ((!_.isString(v) && Number(map.value) === Number(v)) || map.value === v) { | ||||||
|  |               this.setColorState(v, style); | ||||||
|  |               return this.defaultCellFormatter(map.text, style); | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (mappingType === 2 && style.rangeMaps) { | ||||||
|  |           for (let i = 0; i < style.rangeMaps.length; i++) { | ||||||
|  |             const map = style.rangeMaps[i]; | ||||||
|  | 
 | ||||||
|  |             if (v === null) { | ||||||
|  |               if (map.from === 'null' && map.to === 'null') { | ||||||
|  |                 return map.text; | ||||||
|  |               } | ||||||
|  |               continue; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (Number(map.from) <= Number(v) && Number(map.to) >= Number(v)) { | ||||||
|  |               this.setColorState(v, style); | ||||||
|  |               return this.defaultCellFormatter(map.text, style); | ||||||
|  |             } | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (v === null || v === void 0) { | ||||||
|  |           return '-'; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         this.setColorState(v, style); | ||||||
|  |         return this.defaultCellFormatter(v, style); | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (style.type === 'number') { | ||||||
|  |       const valueFormatter = kbn.valueFormats[style.unit || header.unit]; | ||||||
|  | 
 | ||||||
|  |       return v => { | ||||||
|  |         if (v === null || v === void 0) { | ||||||
|  |           return '-'; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (_.isString(v) || _.isArray(v)) { | ||||||
|  |           return this.defaultCellFormatter(v, style); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         this.setColorState(v, style); | ||||||
|  |         return valueFormatter(v, style.decimals, null); | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return value => { | ||||||
|  |       return this.defaultCellFormatter(value, style); | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   setColorState(value: any, style: Style) { | ||||||
|  |     if (!style.colorMode) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (value === null || value === void 0 || _.isArray(value)) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (_.isNaN(value)) { | ||||||
|  |       return; | ||||||
|  |     } | ||||||
|  |     const numericValue = Number(value); | ||||||
|  |     this.colorState[style.colorMode] = this.getColorForValue(numericValue, style); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   renderRowconstiables(rowIndex) { | ||||||
|  |     const { panelData } = this.props; | ||||||
|  | 
 | ||||||
|  |     const scopedVars = {}; | ||||||
|  |     const row = panelData.tableData.rows[rowIndex]; | ||||||
|  |     for (let i = 0; i < row.length; i++) { | ||||||
|  |       scopedVars[`__cell_${i}`] = { value: row[i] }; | ||||||
|  |     } | ||||||
|  |     return scopedVars; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   renderCell(columnIndex: number, rowIndex: number, value: any, addWidthHack = false) { | ||||||
|  |     const column = this.columns[columnIndex]; | ||||||
|  |     if (column.formatter) { | ||||||
|  |       value = column.formatter(value, column.style); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const style = {}; | ||||||
|  |     const cellClasses = []; | ||||||
|  |     let cellClass = ''; | ||||||
|  | 
 | ||||||
|  |     if (this.colorState.cell) { | ||||||
|  |       style['backgroundColor'] = this.colorState.cell; | ||||||
|  |       style['color'] = 'white'; | ||||||
|  |       this.colorState.cell = null; | ||||||
|  |     } else if (this.colorState.value) { | ||||||
|  |       style['color'] = this.colorState.value; | ||||||
|  |       this.colorState.value = null; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (value === undefined) { | ||||||
|  |       style['display'] = 'none'; | ||||||
|  |       column.hidden = true; | ||||||
|  |     } else { | ||||||
|  |       column.hidden = false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (column.style && column.style.preserveFormat) { | ||||||
|  |       cellClasses.push('table-panel-cell-pre'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     let columnHtml; | ||||||
|  |     if (column.style && column.style.link) { | ||||||
|  |       // Render cell as link
 | ||||||
|  |       const scopedconsts = this.renderRowconstiables(rowIndex); | ||||||
|  |       scopedconsts['__cell'] = { value: value }; | ||||||
|  | 
 | ||||||
|  |       const cellLink = templateSrv.replace(column.style.linkUrl, scopedconsts, encodeURIComponent); | ||||||
|  |       const cellLinkTooltip = templateSrv.replace(column.style.linkTooltip, scopedconsts); | ||||||
|  |       const cellTarget = column.style.linkTargetBlank ? '_blank' : ''; | ||||||
|  | 
 | ||||||
|  |       cellClasses.push('table-panel-cell-link'); | ||||||
|  |       columnHtml = ( | ||||||
|  |         <a | ||||||
|  |           href={cellLink} | ||||||
|  |           target={cellTarget} | ||||||
|  |           data-link-tooltip | ||||||
|  |           data-original-title={cellLinkTooltip} | ||||||
|  |           data-placement="right" | ||||||
|  |         > | ||||||
|  |           {value} | ||||||
|  |         </a> | ||||||
|  |       ); | ||||||
|  |     } else { | ||||||
|  |       columnHtml = <span>{value}</span>; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     let filterLink; | ||||||
|  |     if (column.filterable) { | ||||||
|  |       cellClasses.push('table-panel-cell-filterable'); | ||||||
|  |       filterLink = ( | ||||||
|  |         <span> | ||||||
|  |           <a | ||||||
|  |             className="table-panel-filter-link" | ||||||
|  |             data-link-tooltip | ||||||
|  |             data-original-title="Filter out value" | ||||||
|  |             data-placement="bottom" | ||||||
|  |             data-row={rowIndex} | ||||||
|  |             data-column={columnIndex} | ||||||
|  |             data-operator="!=" | ||||||
|  |           > | ||||||
|  |             <i className="fa fa-search-minus" /> | ||||||
|  |           </a> | ||||||
|  |           <a | ||||||
|  |             className="table-panel-filter-link" | ||||||
|  |             data-link-tooltip | ||||||
|  |             data-original-title="Filter for value" | ||||||
|  |             data-placement="bottom" | ||||||
|  |             data-row={rowIndex} | ||||||
|  |             data-column={columnIndex} | ||||||
|  |             data-operator="=" | ||||||
|  |           > | ||||||
|  |             <i className="fa fa-search-plus" /> | ||||||
|  |           </a> | ||||||
|  |         </span> | ||||||
|  |       ); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (cellClasses.length) { | ||||||
|  |       cellClass = cellClasses.join(' '); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     style['width'] = '100%'; | ||||||
|  |     style['height'] = '100%'; | ||||||
|  |     columnHtml = ( | ||||||
|  |       <div className={cellClass} style={style}> | ||||||
|  |         {columnHtml} | ||||||
|  |         {filterLink} | ||||||
|  |       </div> | ||||||
|  |     ); | ||||||
|  |     return columnHtml; | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   render() { |   render() { | ||||||
|     const { panelData, width, height, options } = this.props; |     const { panelData, height, options } = this.props; | ||||||
|     const { showHeader } = options; |     const { pageSize } = options; | ||||||
| 
 | 
 | ||||||
|     const headerClassName = null; |     let rows = []; | ||||||
|     const headerHeight = 30; |     let columns = []; | ||||||
|     const rowHeight = 20; |  | ||||||
| 
 |  | ||||||
|     let rowCount = 0; |  | ||||||
|     if (panelData.tableData) { |     if (panelData.tableData) { | ||||||
|       rowCount = panelData.tableData.rows.length; |       this.initColumns(); | ||||||
|  |       const fields = this.columns.map(c => { | ||||||
|  |         return c.accessor; | ||||||
|  |       }); | ||||||
|  |       rows = panelData.tableData.rows.map(row => { | ||||||
|  |         return _.zipObject(fields, row); | ||||||
|  |       }); | ||||||
|  |       columns = this.columns.map((c, columnIndex) => { | ||||||
|  |         return { | ||||||
|  |           Header: c.header, | ||||||
|  |           accessor: c.accessor, | ||||||
|  |           filterable: !!c.filterable, | ||||||
|  |           Cell: row => { | ||||||
|  |             return this.renderCell(columnIndex, row.index, row.value); | ||||||
|  |           }, | ||||||
|  |         }; | ||||||
|  |       }); | ||||||
|  |       console.log(templateSrv); | ||||||
|  |       console.log(rows); | ||||||
|     } else { |     } else { | ||||||
|       return <div>No Table Data...</div>; |       return <div>No Table Data...</div>; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     // Only show paging if necessary
 | ||||||
|  |     const showPaginationBottom = pageSize && pageSize < panelData.tableData.rows.length; | ||||||
|  | 
 | ||||||
|     return ( |     return ( | ||||||
|       <div> |       <ReactTable | ||||||
|         <Table |         data={rows} | ||||||
|           disableHeader={!showHeader} |         columns={columns} | ||||||
|           headerClassName={headerClassName} |         defaultPageSize={pageSize} | ||||||
|           headerHeight={headerHeight} |         style={{ | ||||||
|           height={height} |           height: height - 20 + 'px', | ||||||
|           overscanRowCount={5} |         }} | ||||||
|           rowHeight={rowHeight} |         showPaginationBottom={showPaginationBottom} | ||||||
|           rowGetter={this.getRow} |         getTdProps={(state, rowInfo, column, instance) => { | ||||||
|           rowCount={rowCount} |           return { | ||||||
|           width={width} |             onClick: (e, handleOriginal) => { | ||||||
|         > |               console.log('filter', rowInfo.row[column.id]); | ||||||
|           {panelData.tableData.columns.map((col, index) => { |               if (handleOriginal) { | ||||||
|             return ( |                 handleOriginal(); | ||||||
|               <Column |               } | ||||||
|                 label={col.text} |             }, | ||||||
|                 cellDataGetter={({ rowData }) => { |           }; | ||||||
|                   return rowData[index]; |         }} | ||||||
|                 }} |       /> | ||||||
|                 dataKey={index} |  | ||||||
|                 disableSort={true} |  | ||||||
|                 width={100} |  | ||||||
|               /> |  | ||||||
|             ); |  | ||||||
|           })} |  | ||||||
|         </Table> |  | ||||||
|       </div> |  | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ import _ from 'lodash'; | ||||||
| import React, { PureComponent } from 'react'; | import React, { PureComponent } from 'react'; | ||||||
| 
 | 
 | ||||||
| // Types
 | // Types
 | ||||||
| import { PanelEditorProps, Switch } from '@grafana/ui'; | import { PanelEditorProps, Switch, FormField } from '@grafana/ui'; | ||||||
| import { Options } from './types'; | import { Options } from './types'; | ||||||
| 
 | 
 | ||||||
| export class TablePanelEditor extends PureComponent<PanelEditorProps<Options>> { | export class TablePanelEditor extends PureComponent<PanelEditorProps<Options>> { | ||||||
|  | @ -11,8 +11,10 @@ export class TablePanelEditor extends PureComponent<PanelEditorProps<Options>> { | ||||||
|     this.props.onOptionsChange({ ...this.props.options, showHeader: !this.props.options.showHeader }); |     this.props.onOptionsChange({ ...this.props.options, showHeader: !this.props.options.showHeader }); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  |   onRowsPerPageChange = ({ target }) => this.props.onOptionsChange({ ...this.props.options, pageSize: target.value }); | ||||||
|  | 
 | ||||||
|   render() { |   render() { | ||||||
|     const { showHeader } = this.props.options; |     const { showHeader, pageSize } = this.props.options; | ||||||
| 
 | 
 | ||||||
|     return ( |     return ( | ||||||
|       <div> |       <div> | ||||||
|  | @ -20,6 +22,11 @@ export class TablePanelEditor extends PureComponent<PanelEditorProps<Options>> { | ||||||
|           <h5 className="section-heading">Header</h5> |           <h5 className="section-heading">Header</h5> | ||||||
|           <Switch label="Show" labelClass="width-5" checked={showHeader} onChange={this.onToggleShowHeader} /> |           <Switch label="Show" labelClass="width-5" checked={showHeader} onChange={this.onToggleShowHeader} /> | ||||||
|         </div> |         </div> | ||||||
|  | 
 | ||||||
|  |         <div className="section gf-form-group"> | ||||||
|  |           <h5 className="section-heading">Paging</h5> | ||||||
|  |           <FormField label="Rows per page" labelWidth={8} onChange={this.onRowsPerPageChange} value={pageSize} /> | ||||||
|  |         </div> | ||||||
|       </div> |       </div> | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -1,7 +1,63 @@ | ||||||
|  | // Made to match the existing (untyped) settings in the angular table
 | ||||||
|  | export interface Style { | ||||||
|  |   alias?: string; | ||||||
|  |   colorMode?: string; | ||||||
|  |   colors?: any[]; | ||||||
|  |   decimals?: number; | ||||||
|  |   pattern?: string; | ||||||
|  |   thresholds?: any[]; | ||||||
|  |   type?: 'date' | 'number' | 'string' | 'hidden'; | ||||||
|  |   unit?: string; | ||||||
|  |   dateFormat?: string; | ||||||
|  |   sanitize?: boolean; | ||||||
|  |   mappingType?: any; | ||||||
|  |   valueMaps?: any; | ||||||
|  |   rangeMaps?: any; | ||||||
|  | 
 | ||||||
|  |   link?: any; | ||||||
|  |   linkUrl?: any; | ||||||
|  |   linkTooltip?: any; | ||||||
|  |   linkTargetBlank?: boolean; | ||||||
|  | 
 | ||||||
|  |   preserveFormat?: boolean; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export type CellFormatter = (v: any, style: Style) => string; | ||||||
|  | 
 | ||||||
|  | export interface Column { | ||||||
|  |   header: string; | ||||||
|  |   accessor: string; // the field name
 | ||||||
|  |   style?: Style; | ||||||
|  |   hidden?: boolean; | ||||||
|  |   formatter: CellFormatter; | ||||||
|  |   filterable?: boolean; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export interface Options { | export interface Options { | ||||||
|   showHeader: boolean; |   showHeader: boolean; | ||||||
|  |   styles: Style[]; // TODO, just a copy from existing table
 | ||||||
|  |   pageSize: number; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export const defaults: Options = { | export const defaults: Options = { | ||||||
|   showHeader: true, |   showHeader: true, | ||||||
|  |   styles: [ | ||||||
|  |     { | ||||||
|  |       type: 'date', | ||||||
|  |       pattern: 'Time', | ||||||
|  |       alias: 'Time', | ||||||
|  |       dateFormat: 'YYYY-MM-DD HH:mm:ss', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       unit: 'short', | ||||||
|  |       type: 'number', | ||||||
|  |       alias: '', | ||||||
|  |       decimals: 2, | ||||||
|  |       colors: ['rgba(245, 54, 54, 0.9)', 'rgba(237, 129, 40, 0.89)', 'rgba(50, 172, 45, 0.97)'], | ||||||
|  |       colorMode: null, | ||||||
|  |       pattern: '/.*/', | ||||||
|  |       thresholds: [], | ||||||
|  |     }, | ||||||
|  |   ], | ||||||
|  |   pageSize: 100, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -98,7 +98,6 @@ | ||||||
| @import 'components/page_loader'; | @import 'components/page_loader'; | ||||||
| @import 'components/toggle_button_group'; | @import 'components/toggle_button_group'; | ||||||
| @import 'components/popover-box'; | @import 'components/popover-box'; | ||||||
| @import 'components/react_virtualized'; |  | ||||||
| 
 | 
 | ||||||
| // LOAD @grafana/ui components | // LOAD @grafana/ui components | ||||||
| @import '../../packages/grafana-ui/src/index'; | @import '../../packages/grafana-ui/src/index'; | ||||||
|  |  | ||||||
|  | @ -1,83 +0,0 @@ | ||||||
| /** |  | ||||||
| COPIED FROM: |  | ||||||
| https://raw.githubusercontent.com/bvaughn/react-virtualized/master/source/styles.css |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| /* Collection default theme */ |  | ||||||
| 
 |  | ||||||
| .ReactVirtualized__Collection { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .ReactVirtualized__Collection__innerScrollContainer { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Grid default theme */ |  | ||||||
| 
 |  | ||||||
| .ReactVirtualized__Grid { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .ReactVirtualized__Grid__innerScrollContainer { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Table default theme */ |  | ||||||
| 
 |  | ||||||
| .ReactVirtualized__Table { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .ReactVirtualized__Table__Grid { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .ReactVirtualized__Table__headerRow { |  | ||||||
|   font-weight: 700; |  | ||||||
|   text-transform: uppercase; |  | ||||||
|   display: flex; |  | ||||||
|   flex-direction: row; |  | ||||||
|   align-items: center; |  | ||||||
| } |  | ||||||
| .ReactVirtualized__Table__row { |  | ||||||
|   display: flex; |  | ||||||
|   flex-direction: row; |  | ||||||
|   align-items: center; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .ReactVirtualized__Table__headerTruncatedText { |  | ||||||
|   display: inline-block; |  | ||||||
|   max-width: 100%; |  | ||||||
|   white-space: nowrap; |  | ||||||
|   text-overflow: ellipsis; |  | ||||||
|   overflow: hidden; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .ReactVirtualized__Table__headerColumn, |  | ||||||
| .ReactVirtualized__Table__rowColumn { |  | ||||||
|   margin-right: 10px; |  | ||||||
|   min-width: 0px; |  | ||||||
| } |  | ||||||
| .ReactVirtualized__Table__rowColumn { |  | ||||||
|   text-overflow: ellipsis; |  | ||||||
|   white-space: nowrap; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .ReactVirtualized__Table__headerColumn:first-of-type, |  | ||||||
| .ReactVirtualized__Table__rowColumn:first-of-type { |  | ||||||
|   margin-left: 10px; |  | ||||||
| } |  | ||||||
| .ReactVirtualized__Table__sortableHeaderColumn { |  | ||||||
|   cursor: pointer; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .ReactVirtualized__Table__sortableHeaderIconContainer { |  | ||||||
|   display: flex; |  | ||||||
|   align-items: center; |  | ||||||
| } |  | ||||||
| .ReactVirtualized__Table__sortableHeaderIcon { |  | ||||||
|   flex: 0 0 24px; |  | ||||||
|   height: 1em; |  | ||||||
|   width: 1em; |  | ||||||
|   fill: currentColor; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* List default theme */ |  | ||||||
| 
 |  | ||||||
| .ReactVirtualized__List { |  | ||||||
| } |  | ||||||
		Loading…
	
		Reference in New Issue