diff --git a/src/data-table/data-cell.jsx b/src/data-table/data-cell.jsx
index 27f11f8..6e38a66 100644
--- a/src/data-table/data-cell.jsx
+++ b/src/data-table/data-cell.jsx
@@ -42,7 +42,7 @@ class DataCell extends React.PureComponent {
render () {
const {
- general,
+ cellWidth,
measurement,
styleBuilder,
styling
@@ -55,17 +55,15 @@ class DataCell extends React.PureComponent {
...styleBuilder.getStyle(),
paddingLeft: '5px',
textAlign: textAlignment,
- minWidth: general.cellWidth,
- maxWidth: general.cellWidth
+ minWidth: cellWidth,
+ maxWidth: cellWidth
};
const isEmptyCell = measurement.displayValue === '';
let formattedMeasurementValue;
- if (isEmptyCell) {
+ if (isEmptyCell || styleBuilder.hasComments()) {
formattedMeasurementValue = '';
cellStyle.cursor = 'default';
- } else if (styleBuilder.hasComments()) {
- formattedMeasurementValue = '.';
} else {
formattedMeasurementValue = formatMeasurementValue(measurement, styling);
}
@@ -104,6 +102,7 @@ class DataCell extends React.PureComponent {
}
DataCell.propTypes = {
+ cellWidth: PropTypes.string.isRequired,
data: PropTypes.shape({
headers: PropTypes.shape({
dimension1: PropTypes.array.isRequired,
@@ -114,9 +113,7 @@ DataCell.propTypes = {
dimensionCount: PropTypes.number.isRequired
}).isRequired
}).isRequired,
- general: PropTypes.shape({
- cellWidth: PropTypes.string.isRequired
- }).isRequired,
+ general: PropTypes.shape({}).isRequired,
measurement: PropTypes.shape({
format: PropTypes.string,
name: PropTypes.string,
diff --git a/src/data-table/index.jsx b/src/data-table/index.jsx
index a798e53..b4d7116 100644
--- a/src/data-table/index.jsx
+++ b/src/data-table/index.jsx
@@ -5,102 +5,114 @@ import DataCell from './data-cell.jsx';
import RowHeader from './row-header.jsx';
import { injectSeparators } from '../utilities';
-const DataTable = ({ data, general, component, renderData, styling }) => {
- const {
- headers: {
- dimension1,
- measurements
- },
- matrix
- } = data;
+class DataTable extends React.PureComponent {
+ render () {
+ const {
+ cellWidth,
+ columnSeparatorWidth,
+ component,
+ data,
+ general,
+ renderData,
+ styling
+ } = this.props;
- return (
-
-
-
- {dimension1.map((dimensionEntry, dimensionIndex) => {
- const rowHeaderText = dimensionEntry.displayValue || '';
- if (rowHeaderText === '-') {
- return null;
- }
- const styleBuilder = new StyleBuilder(styling);
- if (styling.hasCustomFileStyle) {
- styleBuilder.parseCustomFileStyle(rowHeaderText);
- } else {
- styleBuilder.applyStandardAttributes(dimensionIndex);
- styleBuilder.applyCustomStyle({
- fontSize: `${14 + styling.options.fontSizeAdjustment}px`
- });
- }
- const rowStyle = {
- fontFamily: styling.options.fontFamily,
- width: '230px',
- ...styleBuilder.getStyle()
- };
+ const {
+ headers: {
+ dimension1,
+ measurements
+ },
+ matrix
+ } = data;
- return (
-
- {!renderData ?
- : null
- }
- {renderData && injectSeparators(
- matrix[dimensionIndex],
- styling.useSeparatorColumns,
- { atEvery: measurements.length }
- ).map((measurementData, index) => {
- if (measurementData.isSeparator) {
- const separatorStyle = {
- color: 'white',
- fontFamily: styling.options.fontFamily,
- fontSize: `${12 + styling.options.fontSizeAdjustment}px`
- };
+ const separatorStyle = {
+ minWidth: columnSeparatorWidth,
+ maxWidth: columnSeparatorWidth
+ };
- return (
- |
- *
- |
- );
- }
+ return (
+
+
+
+ {dimension1.map((dimensionEntry, dimensionIndex) => {
+ const rowHeaderText = dimensionEntry.displayValue || '';
+ if (rowHeaderText === '-') {
+ return null;
+ }
+ const styleBuilder = new StyleBuilder(styling);
+ if (styling.hasCustomFileStyle) {
+ styleBuilder.parseCustomFileStyle(rowHeaderText);
+ } else {
+ styleBuilder.applyStandardAttributes(dimensionIndex);
+ styleBuilder.applyCustomStyle({
+ fontSize: `${14 + styling.options.fontSizeAdjustment}px`
+ });
+ }
+ const rowStyle = {
+ fontFamily: styling.options.fontFamily,
+ width: '230px',
+ ...styleBuilder.getStyle()
+ };
- const { dimension1: dimension1Info, dimension2, measurement } = measurementData.parents;
- const id = `${dimension1Info.elementNumber}-${dimension2 && dimension2.elementNumber}-${measurement.header}-${measurement.index}`;
- return (
-
+ {!renderData ?
+
- );
- })}
-
- );
- })}
-
-
-
- );
-};
+ /> : null
+ }
+ {renderData && injectSeparators(
+ matrix[dimensionIndex],
+ columnSeparatorWidth,
+ { atEvery: measurements.length }
+ ).map((measurementData, index) => {
+ if (measurementData.isSeparator) {
+ return (
+ |
+ );
+ }
+
+ const { dimension1: dimension1Info, dimension2, measurement } = measurementData.parents;
+ const id = `${dimension1Info.elementNumber}-${dimension2 && dimension2.elementNumber}-${measurement.header}-${measurement.index}`;
+ return (
+
+ );
+ })}
+
+ );
+ })}
+
+
+
+ );
+ }
+}
DataTable.defaultProps = {
renderData: true
};
DataTable.propTypes = {
+ cellWidth: PropTypes.string.isRequired,
+ columnSeparatorWidth: PropTypes.string.isRequired,
data: PropTypes.shape({
headers: PropTypes.shape({
dimension1: PropTypes.array.isRequired
diff --git a/src/definition/table-format.js b/src/definition/table-format.js
index 726e09f..98f29f0 100644
--- a/src/definition/table-format.js
+++ b/src/definition/table-format.js
@@ -209,6 +209,23 @@ const tableFormat = {
],
defaultValue: 'right'
},
+ FitChartWidth: {
+ ref: 'fitchartwidth',
+ type: 'boolean',
+ component: 'switch',
+ label: 'Fill chart width',
+ options: [
+ {
+ value: true,
+ label: 'On'
+ },
+ {
+ value: false,
+ label: 'Off'
+ }
+ ],
+ defaultValue: false
+ },
ColumnWidthSlider: {
type: 'number',
component: 'slider',
@@ -217,7 +234,8 @@ const tableFormat = {
min: 20,
max: 250,
step: 10,
- defaultValue: 50
+ defaultValue: 50,
+ show: data => !data.fitchartwidth
},
SymbolForNulls: {
ref: 'symbolfornulls',
diff --git a/src/headers-table/column-header.jsx b/src/headers-table/column-header.jsx
index b782034..cd9b8f7 100644
--- a/src/headers-table/column-header.jsx
+++ b/src/headers-table/column-header.jsx
@@ -17,7 +17,7 @@ class ColumnHeader extends React.PureComponent {
}
render () {
- const { baseCSS, cellWidth, colSpan, entry, styling, component } = this.props;
+ const { baseCSS, cellWidth, colSpan, component, entry, styling } = this.props;
const inEditState = component.inEditState();
const isMediumFontSize = styling.headerOptions.fontSizeAdjustment === HEADER_FONT_SIZE.MEDIUM;
@@ -55,7 +55,7 @@ ColumnHeader.defaultProps = {
ColumnHeader.propTypes = {
baseCSS: PropTypes.shape({}).isRequired,
- cellWidth: PropTypes.string,
+ cellWidth: PropTypes.string.isRequired,
colSpan: PropTypes.number,
entry: PropTypes.shape({
displayValue: PropTypes.string.isRequired,
diff --git a/src/headers-table/index.jsx b/src/headers-table/index.jsx
index c2ff861..0dabad3 100644
--- a/src/headers-table/index.jsx
+++ b/src/headers-table/index.jsx
@@ -5,121 +5,124 @@ import ColumnHeader from './column-header.jsx';
import MeasurementColumnHeader from './measurement-column-header.jsx';
import { injectSeparators } from '../utilities';
-const HeadersTable = ({ data, general, component, styling, isKpi }) => {
- const baseCSS = {
- backgroundColor: styling.headerOptions.colorSchema,
- color: styling.headerOptions.textColor,
- fontFamily: styling.options.fontFamily,
- textAlign: styling.headerOptions.alignment
- };
+class HeadersTable extends React.PureComponent {
+ render () {
+ const {
+ cellWidth,
+ columnSeparatorWidth,
+ component,
+ data,
+ general,
+ isKpi,
+ styling
+ } = this.props;
- const {
- dimension1,
- dimension2,
- measurements
- } = data.headers;
+ const baseCSS = {
+ backgroundColor: styling.headerOptions.colorSchema,
+ color: styling.headerOptions.textColor,
+ fontFamily: styling.options.fontFamily,
+ textAlign: styling.headerOptions.alignment
+ };
- const hasSecondDimension = dimension2.length > 0;
+ const {
+ dimension1,
+ dimension2,
+ measurements
+ } = data.headers;
- return (
-
-
-
-
- {isKpi ?
- : null
- }
- {!isKpi && !hasSecondDimension && measurements.map(measurementEntry => (
-
- ))}
- {!isKpi && hasSecondDimension && injectSeparators(dimension2, styling.useSeparatorColumns).map((entry, index) => {
- if (entry.isSeparator) {
- const separatorStyle = {
- color: 'white',
- fontFamily: styling.options.fontFamily,
- fontSize: `${13 + styling.headerOptions.fontSizeAdjustment}px`
- };
+ const hasSecondDimension = dimension2.length > 0;
- return (
- |
- *
- |
- );
- }
- return (
-
+
+
+
+ {isKpi ?
+ : null
+ }
+ {!isKpi && !hasSecondDimension && measurements.map(measurementEntry => (
+
- );
- })}
-
- {!isKpi && hasSecondDimension && (
-
- {injectSeparators(dimension2, styling.useSeparatorColumns).map((dimensionEntry, index) => {
- if (dimensionEntry.isSeparator) {
- const separatorStyle = {
- color: 'white',
- fontFamily: styling.options.fontFamily,
- fontSize: `${12 + styling.headerOptions.fontSizeAdjustment}px`
- };
-
+ ))}
+ {!isKpi && hasSecondDimension && injectSeparators(dimension2, columnSeparatorWidth).map((entry, index) => {
+ if (entry.isSeparator) {
return (
|
- *
- |
+ />
);
}
- return measurements.map(measurementEntry => (
-
- ));
+ );
})}
- )}
-
-
-
- );
-};
+ {!isKpi && hasSecondDimension && (
+
+ {injectSeparators(dimension2, columnSeparatorWidth).map((dimensionEntry, index) => {
+ if (dimensionEntry.isSeparator) {
+ return (
+ |
+ );
+ }
+ return measurements.map(measurementEntry => (
+
+ ));
+ })}
+
+ )}
+
+
+
+ );
+ }
+}
HeadersTable.propTypes = {
+ cellWidth: PropTypes.string.isRequired,
+ columnSeparatorWidth: PropTypes.string.isRequired,
data: PropTypes.shape({
headers: PropTypes.shape({
dimension1: PropTypes.array,
diff --git a/src/headers-table/measurement-column-header.jsx b/src/headers-table/measurement-column-header.jsx
index 1f9d716..0b5ce5f 100644
--- a/src/headers-table/measurement-column-header.jsx
+++ b/src/headers-table/measurement-column-header.jsx
@@ -3,25 +3,27 @@ import PropTypes from 'prop-types';
import { HEADER_FONT_SIZE } from '../initialize-transformed';
import Tooltip from '../tooltip/index.jsx';
-const MeasurementColumnHeader = ({ baseCSS, general, hasSecondDimension, measurement, styling }) => {
+const MeasurementColumnHeader = ({ baseCSS, cellWidth, hasSecondDimension, measurement, styling }) => {
const title = `${measurement.name}`;
const { fontSizeAdjustment } = styling.headerOptions;
const isMediumFontSize = fontSizeAdjustment === HEADER_FONT_SIZE.MEDIUM;
+ const cellStyle = {
+ ...baseCSS,
+ verticalAlign: 'middle',
+ minWidth: cellWidth,
+ maxWidth: cellWidth
+ };
+
if (hasSecondDimension) {
const isPercentageFormat = measurement.format.substring(measurement.format.length - 1) === '%';
let baseFontSize = 14;
if (isPercentageFormat) {
baseFontSize = 13;
}
- const cellStyle = {
- ...baseCSS,
- fontSize: `${baseFontSize + fontSizeAdjustment}px`,
- height: isMediumFontSize ? '45px' : '35px',
- verticalAlign: 'middle',
- minWidth: general.cellWidth,
- maxWidth: general.cellWidth
- };
+ cellStyle.fontSize = `${baseFontSize + fontSizeAdjustment}px`;
+ cellStyle.height = isMediumFontSize ? '45px' : '35px';
+
return (
10 ? layout.columnwidthslider : 60}px`;
+ }
+
// top level properties could be reducers and then components connect to grab what they want,
// possibly with reselect for some presentational transforms (moving some of the presentational logic like formatting and such)
const transformedProperties = {
@@ -245,13 +257,13 @@ function initializeTransformed ({ $element, component, dataCube, designList, lay
general: {
allowExcelExport: layout.allowexportxls,
allowFilteringByClick: layout.filteroncellclick,
- // If using the previous solution just set 60px
- cellWidth: `${layout.columnwidthslider > 10 ? layout.columnwidthslider : 60}px`,
+ cellWidth: cellWidth,
errorMessage: layout.errormessage,
footnote: layout.footnote,
maxLoops,
subtitle: layout.subtitle,
- title: layout.title
+ title: layout.title,
+ useColumnSeparator: layout.separatorcols && dimensionCount > 1
},
selection: {
dimensionSelectionCounts: dimensionsInformation.map(dimensionInfo => dimensionInfo.qStateCounts.qSelected)
@@ -305,8 +317,7 @@ function initializeTransformed ({ $element, component, dataCube, designList, lay
}
},
symbolForNulls: layout.symbolfornulls,
- usePadding: layout.indentbool,
- useSeparatorColumns: dimensionCount === 1 ? false : layout.separatorcols
+ usePadding: layout.indentbool
}
};
diff --git a/src/main.less b/src/main.less
index 569c3ff..384a250 100644
--- a/src/main.less
+++ b/src/main.less
@@ -57,10 +57,8 @@
}
.empty {
- width: 3%;
background: #fff;
- min-width: 4px !important;
- max-width: 4px !important;
+ padding: 0 !important;
}
th.main-kpi {
diff --git a/src/root.jsx b/src/root.jsx
index c202ce7..b66be8f 100644
--- a/src/root.jsx
+++ b/src/root.jsx
@@ -4,61 +4,129 @@ import HeadersTable from './headers-table/index.jsx';
import DataTable from './data-table/index.jsx';
import { LinkedScrollWrapper, LinkedScrollSection } from './linked-scroll';
-const Root = ({ state, component, editmodeClass }) => (
-
-
-
-
-
-
-
+class Root extends React.PureComponent {
+ constructor (props) {
+ super(props);
+ this.onDataTableRefSet = this.onDataTableRefSet.bind(this);
+ this.renderedTableWidth = 0;
+ }
+
+ componentDidUpdate () {
+ const tableWidth = this.dataTableRef.getBoundingClientRect().width;
+ if (this.renderedTableWidth !== tableWidth) {
+ this.forceUpdate();
+ }
+ }
+
+ onDataTableRefSet (element) {
+ this.dataTableRef = element;
+ this.forceUpdate();
+ }
+
+ render () {
+ const { editmodeClass, component, state } = this.props;
+ const { data, general, styling } = state;
+
+ // Determine cell- and column separator width
+ let cellWidth = '0px';
+ let columnSeparatorWidth = '';
+ if (this.dataTableRef) {
+ const tableWidth = this.dataTableRef.getBoundingClientRect().width;
+ this.renderedTableWidth = tableWidth;
+
+ if (general.cellWidth) {
+ cellWidth = general.cellWidth;
+ if (general.useColumnSeparator) {
+ columnSeparatorWidth = '8px';
+ }
+ } else {
+ const headerMarginRight = 8;
+ const borderWidth = 1;
+ const rowCellCount = data.matrix[0].length;
+
+ let separatorCount = 0;
+ let separatorWidth = 0;
+ if (general.useColumnSeparator) {
+ separatorCount = data.headers.dimension2.length - 1;
+ separatorWidth = Math.min(Math.floor(tableWidth * 0.2 / separatorCount), 8);
+ columnSeparatorWidth = `${separatorWidth}px`;
+ }
+
+ const separatorWidthSum = (separatorWidth + borderWidth) * separatorCount;
+ cellWidth = `${Math.floor((tableWidth - separatorWidthSum - headerMarginRight - borderWidth)
+ / rowCellCount) - borderWidth}px`;
+ }
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-);
+ );
+ }
+}
Root.propTypes = {
component: PropTypes.shape({}).isRequired,
+ editmodeClass: PropTypes.string.isRequired,
state: PropTypes.shape({
data: PropTypes.object.isRequired,
general: PropTypes.object.isRequired,
styling: PropTypes.object.isRequired
- }).isRequired,
- editmodeClass: PropTypes.string.isRequired
+ }).isRequired
};
export default Root;
diff --git a/src/utilities.js b/src/utilities.js
index 407c511..928269c 100644
--- a/src/utilities.js
+++ b/src/utilities.js
@@ -16,7 +16,7 @@ export function Deferred () {
});
}
-export function injectSeparators (array, shouldHaveSeparator, suppliedOptions) {
+export function injectSeparators (array, columnSeparatorWidth, suppliedOptions) {
const defaultOptions = {
atEvery: 1,
separator: { isSeparator: true }
@@ -26,7 +26,7 @@ export function injectSeparators (array, shouldHaveSeparator, suppliedOptions) {
...suppliedOptions
};
- if (!shouldHaveSeparator) {
+ if (!columnSeparatorWidth) {
return array;
}
return array.reduce((result, entry, index) => {
|