diff --git a/index.jsx b/index.jsx index 63e27ad..621cbcf 100644 --- a/index.jsx +++ b/index.jsx @@ -1,53 +1,55 @@ var _ = { - filter: require('lodash/filter'), - map: require('lodash/map'), - find: require('lodash/find') -} -var React = require('react') -var createReactClass = require('create-react-class') -var DataFrame = require('dataframe') -var Emitter = require('wildemitter') - -var partial = require('./lib/partial') -var download = require('./lib/download') -var getValue = require('./lib/get-value') -var PivotTable = require('./lib/pivot-table.jsx') -var Dimensions = require('./lib/dimensions.jsx') -var ColumnControl = require('./lib/column-control.jsx') + filter: require("lodash/filter"), + map: require("lodash/map"), + find: require("lodash/find") +}; +var React = require("react"); +var createReactClass = require("create-react-class"); +var DataFrame = require("dataframe"); +var Emitter = require("wildemitter"); + +var partial = require("./lib/partial"); +var download = require("./lib/download"); +var getValue = require("./lib/get-value"); +var PivotTable = require("./lib/pivot-table.jsx"); +var Dimensions = require("./lib/dimensions.jsx"); +var ColumnControl = require("./lib/column-control.jsx"); module.exports = createReactClass({ - displayName: 'ReactPivot', + displayName: "ReactPivot", getDefaultProps: function() { return { rows: [], dimensions: [], activeDimensions: [], reduce: function() {}, - tableClassName: '', - csvDownloadFileName: 'table.csv', + tableClassName: "", + csvDownloadFileName: "table.csv", csvTemplateFormat: false, defaultStyles: true, nPaginateRows: 25, solo: {}, hiddenColumns: [], sortBy: null, - sortDir: 'asc', - eventBus: new Emitter, + sortDir: "asc", + eventBus: new Emitter(), compact: false, excludeSummaryFromExport: false, - onData: function () {}, + onData: function() {}, soloText: "solo", subDimensionText: "Sub Dimension..." - } + }; }, getInitialState: function() { - var allDimensions = this.props.dimensions - var activeDimensions = _.filter(this.props.activeDimensions, function (title) { + var allDimensions = this.props.dimensions; + var activeDimensions = _.filter(this.props.activeDimensions, function( + title + ) { return _.find(allDimensions, function(col) { - return col.title === title - }) - }) + return col.title === title; + }); + }); return { dimensions: activeDimensions, @@ -57,81 +59,92 @@ module.exports = createReactClass({ hiddenColumns: this.props.hiddenColumns, solo: this.props.solo, rows: [] - } + }; }, componentWillMount: function() { - if (this.props.defaultStyles) loadStyles() + if (this.props.defaultStyles) loadStyles(); this.dataFrame = DataFrame({ rows: this.props.rows, dimensions: this.props.dimensions, reduce: this.props.reduce - }) + }); - this.updateRows() + this.updateRows(); }, componentWillReceiveProps: function(newProps) { - if(newProps.hiddenColumns !== this.props.hiddenColumns) { - this.setHiddenColumns(newProps.hiddenColumns); - } + if (newProps.hiddenColumns !== this.props.hiddenColumns) { + this.setHiddenColumns(newProps.hiddenColumns); + } - if(newProps.rows !== this.props.rows) { + if (newProps.rows !== this.props.rows) { this.dataFrame = DataFrame({ rows: newProps.rows, dimensions: newProps.dimensions, reduce: newProps.reduce - }) + }); - this.updateRows() + this.updateRows(); } }, getColumns: function() { - var self = this - var columns = [] + var self = this; + var columns = []; this.state.dimensions.forEach(function(title) { - var d = _.find(self.props.dimensions, function(col) { - return col.title === title - }) + var d = _.find(self.props.dimensions, function(col) { + return col.title === title; + }); columns.push({ - type: 'dimension', title: d.title, value: d.value, - className: d.className, template: d.template, sortBy: d.sortBy - }) - }) + type: "dimension", + title: d.title, + value: d.value, + className: d.className, + template: d.template, + sortBy: d.sortBy + }); + }); this.props.calculations.forEach(function(c) { - if (self.state.hiddenColumns.indexOf(c.title) >= 0) return + if (self.state.hiddenColumns.indexOf(c.title) >= 0) return; columns.push({ - type:'calculation', title: c.title, template: c.template, - value: c.value, className: c.className, sortBy: c.sortBy - }) - }) - - return columns + type: "calculation", + title: c.title, + template: c.template, + value: c.value, + className: c.className, + sortBy: c.sortBy + }); + }); + + return columns; }, render: function() { - var self = this + var self = this; var html = ( -
- - { this.props.hideDimensionFilter ? '' : - - } +
+ {this.props.hideDimensionFilter ? ( + "" + ) : ( + + )} + onChange={this.setHiddenColumns} + />
- { Object.keys(this.state.solo).map(function (title) { - var value = self.state.solo[title] + {Object.keys(this.state.solo).map(function(title) { + var value = self.state.solo[title]; return (
+ style={{ clear: "both" }} + className="reactPivot-soloDisplay" + key={"solo-" + title} + > + className="reactPivot-clearSolo" + onClick={partial(self.clearSolo, title)} + > × {title}: {value}
- ) - }) } + ); + })}
- ) + ); - return html + return html; }, - updateRows: function () { - var columns = this.getColumns() + updateRows: function() { + var columns = this.getColumns(); - var sortByTitle = this.state.sortBy - var sortCol = _.find(columns, function(col) { - return col.title === sortByTitle - }) || {} - var sortBy = sortCol.sortBy || (sortCol.type === 'dimension' ? sortCol.title : sortCol.value); - var sortDir = this.state.sortDir + var sortByTitle = this.state.sortBy; + var sortCol = + _.find(columns, function(col) { + return col.title === sortByTitle; + }) || {}; + var sortBy = + sortCol.sortBy || + (sortCol.type === "dimension" ? sortCol.title : sortCol.value); + var sortDir = this.state.sortDir; var calcOpts = { dimensions: this.state.dimensions, sortBy: sortBy, sortDir: sortDir, compact: this.props.compact - } + }; - var filter = this.state.solo + var filter = this.state.solo; if (filter) { calcOpts.filter = function(dVals) { - var pass = true - Object.keys(filter).forEach(function (title) { - if (dVals[title] !== filter[title]) pass = false - }) - return pass - } + var pass = true; + Object.keys(filter).forEach(function(title) { + if (dVals[title] !== filter[title]) pass = false; + }); + return pass; + }; } - var rows = this.dataFrame.calculate(calcOpts) - this.setState({rows: rows}) - this.props.onData(rows) + var rows = this.dataFrame.calculate(calcOpts); + this.setState({ rows: rows }); + this.props.onData(rows); }, - setDimensions: function (updatedDimensions) { - this.props.eventBus.emit('activeDimensions', updatedDimensions) - this.setState({dimensions: updatedDimensions}) - setTimeout(this.updateRows, 0) + setDimensions: function(updatedDimensions) { + this.props.eventBus.emit("activeDimensions", updatedDimensions); + this.setState({ dimensions: updatedDimensions }); + setTimeout(this.updateRows, 0); }, - setHiddenColumns: function (hidden) { - this.props.eventBus.emit('hiddenColumns', hidden) - this.setState({hiddenColumns: hidden}) - setTimeout(this.updateRows, 0) + setHiddenColumns: function(hidden) { + this.props.eventBus.emit("hiddenColumns", hidden); + this.setState({ hiddenColumns: hidden }); + setTimeout(this.updateRows, 0); }, setSort: function(cTitle) { - var sortBy = this.state.sortBy - var sortDir = this.state.sortDir + var sortBy = this.state.sortBy; + var sortDir = this.state.sortDir; if (sortBy === cTitle) { - sortDir = (sortDir === 'asc') ? 'desc' : 'asc' + sortDir = sortDir === "asc" ? "desc" : "asc"; } else { - sortBy = cTitle - sortDir = 'asc' + sortBy = cTitle; + sortDir = "asc"; } - this.props.eventBus.emit('sortBy', sortBy) - this.props.eventBus.emit('sortDir', sortDir) - this.setState({sortBy: sortBy, sortDir: sortDir}) - setTimeout(this.updateRows, 0) + this.props.eventBus.emit("sortBy", sortBy); + this.props.eventBus.emit("sortDir", sortDir); + this.setState({ sortBy: sortBy, sortDir: sortDir }); + setTimeout(this.updateRows, 0); }, setSolo: function(solo) { - var newSolo = this.state.solo - newSolo[solo.title] = solo.value - this.props.eventBus.emit('solo', newSolo) - this.setState({solo: newSolo }) - setTimeout(this.updateRows, 0) + var newSolo = this.state.solo; + newSolo[solo.title] = solo.value; + this.props.eventBus.emit("solo", newSolo); + this.setState({ solo: newSolo }); + setTimeout(this.updateRows, 0); }, clearSolo: function(title) { - var oldSolo = this.state.solo - var newSolo = {} - Object.keys(oldSolo).forEach(function (k) { - if (k !== title) newSolo[k] = oldSolo[k] - }) - this.props.eventBus.emit('solo', newSolo) - this.setState({solo: newSolo}) - setTimeout(this.updateRows, 0) + var oldSolo = this.state.solo; + var newSolo = {}; + Object.keys(oldSolo).forEach(function(k) { + if (k !== title) newSolo[k] = oldSolo[k]; + }); + this.props.eventBus.emit("solo", newSolo); + this.setState({ solo: newSolo }); + setTimeout(this.updateRows, 0); }, hideColumn: function(cTitle) { - var hidden = this.state.hiddenColumns.concat([cTitle]) - this.setHiddenColumns(hidden) - setTimeout(this.updateRows, 0) + var hidden = this.state.hiddenColumns.concat([cTitle]); + this.setHiddenColumns(hidden); + setTimeout(this.updateRows, 0); }, downloadCSV: function(rows) { - var self = this + var self = this; - var columns = this.getColumns() + var columns = this.getColumns(); - var csv = _.map(columns, 'title') - .map(JSON.stringify.bind(JSON)) - .join(',') + '\n' + var csv = + _.map(columns, "title") + .map(JSON.stringify.bind(JSON)) + .join(",") + "\n"; - var maxLevel = this.state.dimensions.length - 1 - var excludeSummary = this.props.excludeSummaryFromExport + var maxLevel = this.state.dimensions.length - 1; + var excludeSummary = this.props.excludeSummaryFromExport; rows.forEach(function(row) { - if (excludeSummary && (row._level < maxLevel)) return + if (excludeSummary && row._level < maxLevel) return; var vals = columns.map(function(col) { - - if (col.type === 'dimension') { - var val = row[col.title] + if (col.type === "dimension") { + var val = row[col.title]; } else { - var val = getValue(col, row) + var val = getValue(col, row); } if (col.template && self.props.csvTemplateFormat) { - val = col.template(val) + val = col.template(val); } - return JSON.stringify(val) - }) - csv += vals.join(',') + '\n' - }) + return JSON.stringify(val); + }); + csv += vals.join(",") + "\n"; + }); - download(csv, this.props.csvDownloadFileName, 'text/csv') + download(csv, this.props.csvDownloadFileName, "text/csv"); } -}) +}); -function loadStyles () { require('./style.css') } +function loadStyles() { + require("./style.css"); +} diff --git a/style.css b/style.css index 21ae850..732dbf6 100644 --- a/style.css +++ b/style.css @@ -25,8 +25,8 @@ border: none; margin-right: 5px; margin-top: 5px; - background-color: #FFF; - border: 1px solid #CCC; + background-color: #fff; + border: 1px solid #ccc; } .reactPivot-results table { @@ -42,8 +42,12 @@ opacity: 0.5; } -.reactPivot-results th.asc:after { content: ' ▲' } -.reactPivot-results th.desc:after { content: ' ▼' } +.reactPivot-results th.asc:after { + content: " ▲"; +} +.reactPivot-results th.desc:after { + content: " ▼"; +} .reactPivot-results td { border-top: 1px solid #ddd; @@ -55,16 +59,22 @@ } .reactPivot-results tr:hover td { - background: #f5f5f5 + background: #f5f5f5; } .reactPivot-results tr:hover td.reactPivot-indent { background: none; } -.reactPivot-solo {opacity: 0} -.reactPivot-solo:hover {font-weight: bold} -td:hover .reactPivot-solo {opacity: 0.5} +.reactPivot-solo { + opacity: 0; +} +.reactPivot-solo:hover { + font-weight: bold; +} +td:hover .reactPivot-solo { + opacity: 0.5; +} .reactPivot-csvExport, .reactPivot-columnControl { @@ -73,8 +83,8 @@ td:hover .reactPivot-solo {opacity: 0.5} } .reactPivot-csvExport button { - background-color: #FFF; - border: 1px solid #CCC; + background-color: #fff; + border: 1px solid #ccc; height: 28px; color: #555; cursor: pointer; @@ -89,7 +99,9 @@ td:hover .reactPivot-solo {opacity: 0.5} text-align: left; } -.reactPivot-hideColumn { opacity: 0 } +.reactPivot-hideColumn { + opacity: 0; +} th:hover .reactPivot-hideColumn { opacity: 0.5;