Skip to content

Commit ea0be03

Browse files
committed
Add JSONTable component
fixed-data-table react-virtualized vanilla HTML
1 parent 2a957c6 commit ea0be03

File tree

19 files changed

+495
-82
lines changed

19 files changed

+495
-82
lines changed

README.md

Lines changed: 64 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# jupyterlab_table
22

3-
A JupyterLab and Jupyter Notebook extension for rendering JSONTable
3+
A JupyterLab and Jupyter Notebook extension for rendering [JSON Table Schema](http://frictionlessdata.io/guides/json-table-schema/)
44

5-
![output renderer](http://g.recordit.co/QAsC7YULcY.gif)
5+
![output renderer](http://g.recordit.co/l9WLsSxPPd.gif)
66

77
## Prerequisites
88

@@ -15,19 +15,73 @@ To render JSONTable output in IPython:
1515
```python
1616
from jupyterlab_table import JSONTable
1717

18-
JSONTable({
19-
"string": "string",
20-
"array": [1, 2, 3],
21-
"bool": True,
22-
"object": {
23-
"foo": "bar"
18+
JSONTable(data=[
19+
{
20+
"Date": "2000-03-01",
21+
"Adj Close": 33.68,
22+
"Open": 89.62,
23+
"Low": 88.94,
24+
"Volume": 106889800,
25+
"High": 94.09,
26+
"Close": 90.81
27+
},
28+
{
29+
"Date": "2000-03-02",
30+
"Adj Close": 34.63,
31+
"Open": 91.81,
32+
"Low": 91.12,
33+
"Volume": 106932600,
34+
"High": 95.37,
35+
"Close": 93.37
2436
}
37+
], schema={
38+
"fields": [
39+
{
40+
"type": "any",
41+
"name": "Date"
42+
},
43+
{
44+
"type": "number",
45+
"name": "Open"
46+
},
47+
{
48+
"type": "number",
49+
"name": "High"
50+
},
51+
{
52+
"type": "number",
53+
"name": "Low"
54+
},
55+
{
56+
"type": "number",
57+
"name": "Close"
58+
},
59+
{
60+
"type": "integer",
61+
"name": "Volume"
62+
},
63+
{
64+
"type": "number",
65+
"name": "Adj Close"
66+
}
67+
]
2568
})
2669
```
2770

28-
To render a `.table.json` file as a tree, simply open it:
71+
Using a pandas DataFrame:
2972

30-
![file renderer](http://g.recordit.co/cbf0xnQHKn.gif)
73+
```python
74+
from jupyterlab_table import JSONTable
75+
import pandas
76+
import numpy
77+
78+
df = pandas.DataFrame(numpy.random.randn(2, 2))
79+
JSONTable(df)
80+
```
81+
82+
To render a .table.json file as a tree, simply open it:
83+
84+
![file renderer](http://g.recordit.co/7BNlGqlKtP.gif)
3185

3286
## Install
3387

component/README.md

Lines changed: 0 additions & 9 deletions
This file was deleted.

component/fixed-data-table.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import React from 'react';
2+
import {
3+
Table,
4+
Column,
5+
Cell
6+
} from 'fixed-data-table';
7+
import 'fixed-data-table/dist/fixed-data-table.min.css';
8+
// hack: `stream.Transform` (stream-browserify) is undefined in `csv-parse` when
9+
// built with @jupyterlabextension-builder
10+
import infer from 'jsontableschema/lib/infer';
11+
// import { infer } from 'jsontableschema';
12+
import './index.css';
13+
14+
const ROW_HEIGHT = 34;
15+
16+
function inferSchema(data) {
17+
const headers = data.reduce((result, row) => [...new Set([...result, ...Object.keys(row)])], []);
18+
const values = data.map(row => Object.values(row));
19+
return infer(headers, values);
20+
}
21+
22+
export default class FixedDataTable extends React.Component {
23+
24+
state = {
25+
columnWidths: {}
26+
}
27+
28+
render() {
29+
let { schema, data } = this.props;
30+
if (!schema) schema = inferSchema(data);
31+
return (
32+
<Table
33+
rowHeight={ROW_HEIGHT}
34+
headerHeight={ROW_HEIGHT}
35+
rowsCount={data.length}
36+
width={3000}
37+
height={ROW_HEIGHT * (data.length + 1)}
38+
onColumnResizeEndCallback={(columnWidth, columnKey) => {
39+
this.setState(({columnWidths}) => ({
40+
columnWidths: {
41+
...columnWidths,
42+
[columnKey]: columnWidth,
43+
}
44+
}));
45+
}}
46+
>
47+
{
48+
schema.fields.map((field, fieldIndex) =>
49+
<Column
50+
key={fieldIndex}
51+
columnKey={field.name}
52+
width={this.state.columnWidths[field.name] || 300}
53+
header={props =>
54+
<Cell>{field.name}</Cell>
55+
}
56+
cell={props =>
57+
<Cell>{data[props.rowIndex][field.name]}</Cell>
58+
}
59+
fixed={false}
60+
isResizable={true}
61+
/>
62+
)
63+
}
64+
</Table>
65+
);
66+
}
67+
68+
}

component/index.css

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,39 @@
1-
.JSONTable {
2-
1+
.fixedDataTableLayout_main {
2+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
3+
font-size: 14px;
4+
}
5+
6+
.public_fixedDataTableCell_main {
7+
border-color: #ddd;
8+
}
9+
10+
.public_fixedDataTable_header {
11+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
12+
font-size: 14px;
13+
}
14+
15+
.public_fixedDataTable_header {
16+
background: #fff;
17+
}
18+
19+
.public_fixedDataTable_header, .public_fixedDataTable_header .public_fixedDataTableCell_main {
20+
background: #fff;
21+
text-align: center;
22+
}
23+
24+
.public_fixedDataTableCell_cellContent {
25+
padding: 6px 13px;
26+
}
27+
28+
.public_fixedDataTableRow_highlighted, .public_fixedDataTableRow_highlighted .public_fixedDataTableCell_main {
29+
background: #f8f8f8;
30+
}
31+
32+
.dataframe {
33+
width: 100%;
34+
border-spacing: 1px;
35+
}
36+
37+
.dataframe .header {
38+
text-align: right;
339
}

component/index.js

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,4 @@
1-
import React from 'react';
2-
import './index.css';
3-
4-
export default class JSONTableComponent extends React.Component {
5-
6-
render() {
7-
return (
8-
<div className="JSONTable">
9-
{JSON.stringify(this.props.data)}
10-
</div>
11-
);
12-
}
13-
14-
}
1+
export VirtualizedTable from './virtualized-table';
2+
export VirtualizedGrid from './virtualized-grid';
3+
export FixedDataTable from './fixed-data-table';
4+
export VanillaTable from './vanilla-table';

component/package.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "jupyterlab_table_react",
33
"version": "1.0.0",
4-
"description": "A React component for rendering JSONTable",
4+
"description": "A React component for rendering JSON schema table",
55
"main": "index.js",
66
"scripts": {
77
"test": "echo \"Error: no test specified\" && exit 1"
@@ -10,9 +10,13 @@
1010
"jupyter",
1111
"react"
1212
],
13-
"author": "Grant Nestor <grantnestor@gmail.com>",
13+
"author": "Grant Nestor",
1414
"license": "ISC",
1515
"dependencies": {
16-
"react": "^15.3.2"
16+
"fixed-data-table": "^0.6.3",
17+
"jsontableschema": "^0.2.2",
18+
"react": "^15.3.2",
19+
"react-addons-shallow-compare": "^15.4.2",
20+
"react-virtualized": "^8.11.4"
1721
}
1822
}

component/vanilla-table.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
// hack: `stream.Transform` (stream-browserify) is undefined in `csv-parse` when
4+
// built with @jupyterlabextension-builder
5+
import infer from 'jsontableschema/lib/infer';
6+
// import { infer } from 'jsontableschema';
7+
import './index.css';
8+
9+
function inferSchema(data) {
10+
const headers = data.reduce((result, row) => [...new Set([...result, ...Object.keys(row)])], []);
11+
const values = data.map(row => Object.values(row));
12+
return infer(headers, values);
13+
}
14+
15+
export default class VanillaTable extends React.Component {
16+
17+
render() {
18+
let { schema, data } = this.props;
19+
if (!schema) schema = inferSchema(data);
20+
return (
21+
<table className="dataframe">
22+
<thead>
23+
<tr className="header">
24+
{
25+
schema.fields.map((field, index) => (
26+
<th key={index}>{field.name}</th>
27+
))
28+
}
29+
</tr>
30+
</thead>
31+
<tbody>
32+
{
33+
props.data.map((row, rowIndex) =>
34+
<tr key={rowIndex}>
35+
{
36+
schema.fields.map((field, index) => (
37+
<td key={index}>{row[field.name]}</td>
38+
))
39+
}
40+
</tr>
41+
)
42+
}
43+
</tbody>
44+
</table>
45+
);
46+
}
47+
48+
}

0 commit comments

Comments
 (0)