// ============================================================================== // Copyright (C) 2019 - Philip Paquette, Steven Bocco // // This program is free software: you can redistribute it and/or modify it under // the terms of the GNU Affero General Public License as published by the Free // Software Foundation, either version 3 of the License, or (at your option) any // later version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more // details. // // You should have received a copy of the GNU Affero General Public License along // with this program. If not, see . // ============================================================================== //// Tables. import React from "react"; import PropTypes from 'prop-types'; class DefaultWrapper { constructor(data) { this.data = data; this.get = this.get.bind(this); } get(fieldName) { return this.data[fieldName]; } } function defaultWrapper(data) { return new DefaultWrapper(data); } export class Table extends React.Component { // className // caption // columns : {name: [title, order]} // data: [objects with expected column names] // wrapper: (optional) function to use to wrap one data entry into an object before accessing fields. // Must return an instance with a method get(name). // If provided: wrapper(data_entry).get(field_name) // else: data_entry[field_name] constructor(props) { super(props); if (!this.props.wrapper) this.props.wrapper = defaultWrapper; } static getHeader(columns) { const header = []; for (let entry of Object.entries(columns)) { const name = entry[0]; const title = entry[1][0]; const order = entry[1][1]; header.push([order, name, title]); } header.sort((a, b) => { let t = a[0] - b[0]; if (t === 0) t = a[1].localeCompare(b[1]); if (t === 0) t = a[2].localeCompare(b[2]); return t; }); return header; } static getHeaderLine(header) { return ( {header.map((column, colIndex) => {column[2]})} ); } static getBodyRow(header, row, rowIndex, wrapper) { const wrapped = wrapper(row); return ( {header.map((headerColumn, colIndex) => {wrapped.get(headerColumn[1])})} ); } static getBodyLines(header, data, wrapper) { return ({data.map((row, rowIndex) => Table.getBodyRow(header, row, rowIndex, wrapper))}); } render() { const header = Table.getHeader(this.props.columns); return (
{Table.getHeaderLine(header)} {Table.getBodyLines(header, this.props.data, this.props.wrapper)}
{this.props.caption} ({this.props.data.length})
); } } Table.propTypes = { wrapper: PropTypes.func, columns: PropTypes.object, className: PropTypes.string, caption: PropTypes.string, data: PropTypes.array };