Skip to content
Snippets Groups Projects
Commit b6db542b authored by Tom Robinson's avatar Tom Robinson
Browse files

Merge branch 'pivot-dashcards' of github.com:metabase/metabase into multiseries_charts_v1

parents a3a92c12 760767e1
No related branches found
No related tags found
No related merge requests found
......@@ -4,6 +4,7 @@ import TableInteractive from "./TableInteractive.jsx";
import TableSimple from "./TableSimple.jsx";
import Query from "metabase/lib/query";
import DataGrid from "metabase/lib/data_grid";
export default class Bar extends Component {
static displayName = "Table";
......@@ -18,34 +19,50 @@ export default class Bar extends Component {
// scalar can always be rendered, nothing needed here
}
render() {
let { card, data, cellClickedFn, setSortFn } = this.props;
constructor(props, context) {
super(props, context);
this.state = {
data: null,
isPivoted: null
};
}
if (this.props.isDashboard) {
return <TableSimple {...this.props} />;
} else {
let pivot = false;
let sort = card.dataset_query.query && card.dataset_query.query.order_by || null;
componentWillMount() {
this.componentWillReceiveProps(this.props);
}
componentWillReceiveProps(newProps) {
if (newProps.data !== this.state.rawData && newProps.data) {
// check if the data is pivotable (2 groupings + 1 agg != 'rows')
if (Query.isStructured(card.dataset_query) &&
!Query.isBareRowsAggregation(card.dataset_query.query) &&
data.cols.length === 3
) {
pivot = true;
setSortFn = null;
cellClickedFn = () => false;
}
return (
<TableInteractive
{...this.props}
pivot={pivot}
sort={sort}
setSortFn={setSortFn}
cellClickedFn={cellClickedFn}
/>
const isPivoted = !!(
Query.isStructured(newProps.card.dataset_query) &&
!Query.isBareRowsAggregation(newProps.card.dataset_query.query) &&
newProps.data.cols.length === 3
);
const data = isPivoted ? DataGrid.pivot(newProps.data) : newProps.data;
this.setState({
isPivoted: isPivoted,
data: data,
rawData: newProps.data
});
}
}
render() {
let { card, cellClickedFn, setSortFn, isDashboard } = this.props;
const { isPivoted, data } = this.state;
const sort = card.dataset_query.query && card.dataset_query.query.order_by || null;
const TableComponent = isDashboard ? TableSimple : TableInteractive;
return (
<TableComponent
{...this.props}
data={data}
isPivoted={isPivoted}
sort={sort}
setSortFn={isPivoted ? undefined : setSortFn}
cellClickedFn={isPivoted ? undefined : cellClickedFn}
/>
);
}
}
......@@ -7,7 +7,6 @@ import Icon from "metabase/components/Icon.jsx";
import Popover from "metabase/components/Popover.jsx";
import MetabaseAnalytics from "metabase/lib/analytics";
import DataGrid from "metabase/lib/data_grid";
import { formatValue, capitalize } from "metabase/lib/formatting";
import _ from "underscore";
......@@ -27,10 +26,8 @@ export default class TableInteractive extends Component {
this.state = {
width: 0,
height: 0,
columnWidths: [],
popover: null,
data: null,
rawData: null,
columnWidths: [],
contentWidths: null
};
......@@ -41,11 +38,17 @@ export default class TableInteractive extends Component {
static propTypes = {
data: PropTypes.object.isRequired,
isPivoted: PropTypes.bool.isRequired,
sort: PropTypes.array,
setSortFn: PropTypes.func.isRequired,
setSortFn: PropTypes.func,
cellIsClickableFn: PropTypes.func.isRequired,
cellClickedFn: PropTypes.func.isRequired,
pivot: PropTypes.bool.isRequired
cellClickedFn: PropTypes.func.isRequired
};
static defaultProps = {
isPivoted: false,
cellIsClickableFn: () => false,
cellClickedFn: () => {}
};
componentWillMount() {
......@@ -53,18 +56,11 @@ export default class TableInteractive extends Component {
}
componentWillReceiveProps(newProps) {
if (newProps.data && newProps.data !== this.state.rawData) {
let gridData = (newProps.pivot) ? DataGrid.pivot(newProps.data) : newProps.data;
if (JSON.stringify(this.props.data && this.props.data.cols) !== JSON.stringify(newProps.data && newProps.data.cols)) {
this.setState({
data: gridData,
rawData: this.props.data
columnWidths: newProps.data.cols ? newProps.data.cols.map(col => 0) : [], // content cells don't wrap so this is fine
contentWidths: null
});
if (JSON.stringify(this.state.data && this.state.data.cols) !== JSON.stringify(gridData.cols)) {
this.setState({
columnWidths: gridData.cols.map(col => 0), // content cells don't wrap so this is fine
contentWidths: null
});
}
}
}
......@@ -97,7 +93,7 @@ export default class TableInteractive extends Component {
contentWidths[cellIndex] = Math.max(contentWidths[cellIndex] || 0, cellElements[cellIndex].offsetWidth);
}
}
this.setState({ contentWidths }, () => this.calculateColumnWidths(this.state.data.cols));
this.setState({ contentWidths }, () => this.calculateColumnWidths(this.props.data.cols));
}
}
......@@ -159,8 +155,8 @@ export default class TableInteractive extends Component {
var row = {
hasPopover: this.state.popover && this.state.popover.rowIndex === rowIndex || false
};
for (var i = 0; i < this.state.data.rows[rowIndex].length; i++) {
row[i] = this.state.data.rows[rowIndex][i];
for (var i = 0; i < this.props.data.rows[rowIndex].length; i++) {
row[i] = this.props.data.rows[rowIndex][i];
}
return row;
}
......@@ -179,7 +175,7 @@ export default class TableInteractive extends Component {
}
cellRenderer(cellData, cellDataKey, rowData, rowIndex, columnData, width) {
cellData = cellData != null ? formatValue(cellData, this.state.data.cols[cellDataKey], { jsx: true }) : null;
cellData = cellData != null ? formatValue(cellData, this.props.data.cols[cellDataKey], { jsx: true }) : null;
var key = 'cl'+rowIndex+'_'+cellDataKey;
if (this.props.cellIsClickableFn(rowIndex, cellDataKey)) {
......@@ -227,7 +223,7 @@ export default class TableInteractive extends Component {
}
tableHeaderRenderer(columnIndex) {
var column = this.state.data.cols[columnIndex],
var column = this.props.data.cols[columnIndex],
colVal = (column && column.display_name && column.display_name.toString()) ||
(column && column.name && column.name.toString());
......@@ -235,7 +231,7 @@ export default class TableInteractive extends Component {
colVal += ": " + capitalize(column.unit.replace(/-/g, " "))
}
if (!colVal && this.props.pivot && columnIndex !== 0) {
if (!colVal && this.props.isPivoted && columnIndex !== 0) {
colVal = "Unset";
}
......@@ -271,11 +267,11 @@ export default class TableInteractive extends Component {
}
render() {
if(!this.state.data) {
if(!this.props.data) {
return false;
}
var tableColumns = this.state.data.cols.map((column, idx) => {
var tableColumns = this.props.data.cols.map((column, idx) => {
var colVal = (column !== null) ? column.name.toString() : null;
var colWidth = this.state.columnWidths[idx];
......@@ -298,12 +294,12 @@ export default class TableInteractive extends Component {
});
return (
<span className={cx('MB-DataTable', { 'MB-DataTable--pivot': this.props.pivot, 'MB-DataTable--ready': this.state.contentWidths })}>
<span className={cx('MB-DataTable', { 'MB-DataTable--pivot': this.props.isPivoted, 'MB-DataTable--ready': this.state.contentWidths })}>
<Table
ref="table"
rowHeight={35}
rowGetter={this.rowGetter}
rowsCount={this.state.data.rows.length}
rowsCount={this.props.data.rows.length}
width={this.state.width}
height={this.state.height}
headerHeight={50}
......
......@@ -35,26 +35,30 @@ export default class TableSimple extends Component {
render() {
var { rows, cols } = this.props.data;
return (
<div className={"Card--table scroll-x scroll-y " + this.props.className}>
<table className="Table border-top">
<thead>
<tr>
{ cols.map((column, colIndex) => <th key={colIndex}>{this.getDatasetColumnTitleByIndex(colIndex)}</th>) }
</tr>
</thead>
<tbody>
{
rows.slice(0, 100).map((row, rowIndex) =>
<tr key={rowIndex}>
{row.map((cell, colIndex) => <td key={colIndex}>
{ formatValue(cell, cols[colIndex], { jsx: true }) }
</td>)}
</tr>
)
}
</tbody>
</table>
</div>
<div className={"Card--table scroll-x scroll-y " + this.props.className}>
<table className="Table border-top">
<thead>
<tr>
{cols.map((column, colIndex) =>
<th key={colIndex}>
{ this.getDatasetColumnTitleByIndex(colIndex) }
</th>
)}
</tr>
</thead>
<tbody>
{rows.slice(0, 100).map((row, rowIndex) =>
<tr key={rowIndex}>
{row.map((cell, colIndex) =>
<td key={colIndex}>
{ formatValue(cell, cols[colIndex], { jsx: true }) }
</td>
)}
</tr>
)}
</tbody>
</table>
</div>
);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment