diff --git a/index.html b/index.html index b05bfd8..5b6b039 100644 --- a/index.html +++ b/index.html @@ -12,6 +12,7 @@ + diff --git a/package.json b/package.json index 1af3dd8..9426407 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "dependencies": { "configstore": "^2.0.0", "dbgeo": "^0.1.0", + "fixed-data-table": "^0.6.0", "install": "^0.6.1", "jquery": "^2.1.4", "lodash": "^4.9.0", @@ -36,11 +37,13 @@ "pg-promise": "^3.7.0", "randomcolor": "^0.4.4", "react": "^15.0.1", + "react-addons-shallow-compare": "^15.0.1", "react-codemirror": "^0.2.6", "react-data-grid": "^0.14.22", "react-dom": "^15.0.1", "react-json-table": "0.0.3", "react-modal": "^1.0.0", + "react-virtualized": "^6.1.2", "sql-parser": "^0.5.0", "turf": "^2.0.2" } diff --git a/resources/css/react-virtualized.css b/resources/css/react-virtualized.css new file mode 100644 index 0000000..f356ee4 --- /dev/null +++ b/resources/css/react-virtualized.css @@ -0,0 +1,111 @@ +/* Grid default theme */ + +.Grid { + position: relative; + overflow: auto; + -webkit-overflow-scrolling: touch; + + /* Without this property, Chrome repaints the entire Grid any time a new row or column is added. + Firefox only repaints the new row or column (regardless of this property). + Safari and IE don't support the property at all. */ + will-change: transform; +} + +.Grid__innerScrollContainer { + box-sizing: border-box; + overflow: hidden; +} + +.Grid__cell { + position: absolute; +} + +/* FlexTable default theme */ + +.FlexTable { +} + +.FlexTable__Grid { + overflow-x: hidden; +} + +.FlexTable__headerRow { + font-weight: 700; + text-transform: uppercase; + display: flex; + flex-direction: row; + align-items: center; + overflow: hidden; +} +.FlexTable__headerTruncatedText { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} +.FlexTable__row { + display: flex; + flex-direction: row; + align-items: center; + overflow: hidden; +} + +.FlexTable__headerColumn, +.FlexTable__rowColumn { + margin-right: 10px; + min-width: 0px; +} + +.FlexTable__headerColumn:first-of-type, +.FlexTable__rowColumn:first-of-type { + margin-left: 10px; +} +.FlexTable__headerColumn { + align-items: center; + display: flex; + flex-direction: row; + overflow: hidden; +} +.FlexTable__sortableHeaderColumn { + cursor: pointer; +} +.FlexTable__rowColumn { + justify-content: center; + flex-direction: column; + display: flex; + overflow: hidden; + height: 100%; +} + +.FlexTable__sortableHeaderIconContainer { + display: flex; + align-items: center; +} +.FlexTable__sortableHeaderIcon { + flex: 0 0 24px; + height: 1em; + width: 1em; + fill: currentColor; +} + +.FlexTable__truncatedColumnText { + text-overflow: ellipsis; + overflow: hidden; +} + +/* VirtualScroll default theme */ + +.VirtualScroll { + position: relative; + overflow-y: auto; + overflow-x: hidden; + -webkit-overflow-scrolling: touch; +} + +.VirtualScroll__innerScrollContainer { + box-sizing: border-box; + overflow: hidden; +} + +.VirtualScroll__row { + position: absolute; +} diff --git a/resources/scss/workspace.scss b/resources/scss/workspace.scss index a5b0e68..fa143d3 100644 --- a/resources/scss/workspace.scss +++ b/resources/scss/workspace.scss @@ -25,7 +25,7 @@ .workspace-table { width: 100%; - max-height: 500px; + height: 500px; } .workspace-logs { diff --git a/src/table.js b/src/table.js index dc00b49..d24c88a 100644 --- a/src/table.js +++ b/src/table.js @@ -2,27 +2,15 @@ import React from 'react'; import ReactDOM from 'react-dom'; import DataGrid from 'react-data-grid'; import {isGeometry} from './database.js'; -import JsonTable from 'react-json-table'; +import { AutoSizer, FlexTable, FlexColumn } from 'react-virtualized'; import * as _ from 'lodash'; -// Even though huge tables are fun it does not make any sense -// to query a million rows and scroll through all of them -// therefore we make our life easy by limiting the displayed rows -const maxRows = 1000; - -// Because we use a split window with the table on the left -// we don't have space for unlimited columns better -// limit the number since the user can click on a row -// to get the full detail on the map interface itself -const maxColumns = 6; - export class GeoJSONTable extends React.Component { constructor(props) { super(props); this.populateTable = this.populateTable.bind(this); - this.showRowDetail = this.showRowDetail.bind(this); this.state = { - columns: [], + fields: [], features: [] }; } @@ -37,31 +25,43 @@ export class GeoJSONTable extends React.Component { populateTable(result) { this.setState({ - features: result.geojson.features.slice(0, maxRows).map(f => { - return _.extend({ _feature: f }, f.properties); - }), - columns: result.fields - .filter(f => !isGeometry(f.name)) - .slice(0, maxColumns) - .map(field => { - return { - key: field.name, - label: field.name - }; - }) + features: result.geojson.features, + fields: result.fields.filter(f => !isGeometry(f.name)) }); } - showRowDetail(e, row) { - window.events.publish('data.detail', row._feature); - } - render() { - const table = ; + const features = this.state.features; + const showRowDetail = i => window.events.publish('data.detail', features[i]); + const columns = this.state.fields.map(field => + rowData.properties[dataKey]} + /> + ); - return this.state.features.length > 0 ? table : null; + const table = ( + + {({ height, width }) => ( + features[index]} + onRowClick={showRowDetail} + > + {columns} + + )} + + ); + + return features.length > 0 ? table : null; } }