Compare commits

..

9 Commits

Author SHA1 Message Date
Albert Backenhof
bec68e7cd4 Merge pull request #39 from qlik-oss/DEB-159/Props
Changed order of properties and added About
2019-04-10 12:05:15 +02:00
Albert Backenhof
02bba4ad5a Merge pull request #38 from qlik-oss/DEB-157/NineMeasures
1 Dim and 9 Measures OR 2 Dim and 8 Measures
2019-04-10 11:30:44 +02:00
Albert Backenhof
57c4b12b24 Merge pull request #36 from qlik-oss/DEB-154/EmptyData
Improved setup of data matrix
2019-04-10 09:13:34 +02:00
Albert Backenhof
ca33540fd6 Merge pull request #35 from qlik-oss/DEB-152/HeaderWidth
The header width should match the table format
2019-04-10 09:13:03 +02:00
Albert Backenhof
cac3fabb2f Changed order of properties and added About
Issue: DEB-159
2019-04-10 08:13:24 +02:00
Albert Backenhof
c57b0edea8 1 Dim and 9 Measures OR 2 Dim and 8 Measures
-Dynamic max values for Dimensions and Measures.

Issue: DEB-157
2019-04-10 07:50:07 +02:00
Albert Backenhof
3862bd294c Arrange matching dim1 data on the same row
-The data is not guaranteed to be processed row
 by row. Therefore, make sure to check the entire
 matrix for the correct row (not just previous row)
 when appending new row data.

Issue: DEB-155
2019-04-09 08:29:37 +02:00
Albert Backenhof
0c18523891 Empty data should result in emtpy cells
-Previously, empty data resulted in the cells
 completely missing. This caused other cells
 to not end up in the correct column.

Issue: DEB-154
2019-04-09 07:50:33 +02:00
Albert Backenhof
629821bd6b The header width should match the table format
Issue: DEB-152
2019-04-08 10:39:02 +02:00
6 changed files with 92 additions and 37 deletions

View File

@@ -33,25 +33,27 @@ class DataCell extends React.PureComponent {
styling
} = this.props;
const isColumnPercentageBased = (/%/).test(measurement.format);
let formattedMeasurementValue = formatMeasurementValue(measurement, styling);
if (styleBuilder.hasComments()) {
formattedMeasurementValue = '.';
}
let textAlignment = 'Right';
const textAlignmentProp = styling.options.textAlignment;
if (textAlignmentProp) {
textAlignment = textAlignmentProp;
}
let textAlignment = styling.options.textAlignment || 'Right';
let cellStyle = {
fontFamily: styling.options.fontFamily,
...styleBuilder.getStyle(),
paddingLeft: '5px',
textAlign: textAlignment
};
const isEmptyCell = measurement.displayValue === '';
const isColumnPercentageBased = (/%/).test(measurement.format);
let formattedMeasurementValue;
if (isEmptyCell) {
formattedMeasurementValue = '';
cellStyle.cursor = 'default';
} else if (styleBuilder.hasComments()) {
formattedMeasurementValue = '.';
} else {
formattedMeasurementValue = formatMeasurementValue(measurement, styling);
}
const { semaphoreColors, semaphoreColors: { fieldsToApplyTo } } = styling;
const isValidSemaphoreValue = !styleBuilder.hasComments() && !isNaN(measurement.value);
const dimension1Row = measurement.parents.dimension1.elementNumber;
@@ -79,7 +81,7 @@ class DataCell extends React.PureComponent {
return (
<td
className={`${cellClass}${general.cellSuffix}`}
onClick={this.handleSelect}
onClick={isEmptyCell ? null : this.handleSelect}
style={cellStyle}
>
<Tooltip

View File

@@ -69,6 +69,7 @@ const DataTable = ({ data, general, qlik, renderData, styling }) => {
</td>
);
}
const { dimension1: dimension1Info, dimension2, measurement } = measurementData.parents;
const id = `${dimension1Info.elementNumber}-${dimension2 && dimension2.elementNumber}-${measurement.header}`;
return (

View File

@@ -18,6 +18,9 @@ const definition = {
},
uses: 'data'
},
sorting: {
uses: 'sorting'
},
settings: {
items: {
ConceptSemaphores: conceptSemaphores,
@@ -28,8 +31,25 @@ const definition = {
},
uses: 'settings'
},
sorting: {
uses: 'sorting'
about: {
component: 'items',
label: 'About',
items: {
header: {
label: 'P&L pivot',
style: 'header',
component: 'text'
},
paragraph1: {
label: `P&L pivot is a Qlik Sense extension which allows you to display Profit & Loss
reporting with color and font customizations.`,
component: 'text'
},
paragraph2: {
label: 'P&L pivot is based upon an extension created by Ivan Felipe Asensio.',
component: 'text'
}
}
}
},
type: 'items'

View File

@@ -50,7 +50,7 @@ const MeasurementColumnHeader = ({ baseCSS, general, hasSecondDimension, measure
};
return (
<th
className={`grid-cells2 ${general.cellSuffix}`}
className={`grid-cells2${general.cellSuffix}`}
style={style}
>
<span

View File

@@ -20,12 +20,16 @@ export default {
},
data: {
dimensions: {
max: 3,
max: function (nMeasures) {
return nMeasures < 9 ? 2 : 1;
},
min: 1,
uses: 'dimensions'
},
measures: {
max: 8,
max: function (nDims) {
return nDims < 2 ? 9 : 8;
},
min: 1,
uses: 'measures'
}

View File

@@ -108,12 +108,11 @@ function generateMatrixCell ({ cell, dimension1Information, dimension2Informatio
let lastRow = 0;
function generateDataSet (component, dimensionsInformation, measurementsInformation, cubes) {
const dimension1 = [];
const dimension2 = [];
let dimension1 = [];
let dimension2 = [];
const measurements = generateMeasurements(measurementsInformation);
let matrix = [];
let previousDim1Entry;
const hasDesignDimension = cubes.design;
const hasSecondDimension = hasDesignDimension ? dimensionsInformation.length > 2 : dimensionsInformation.length > 1;
cubes.data.forEach(row => {
@@ -127,7 +126,7 @@ function generateDataSet (component, dimensionsInformation, measurementsInformat
dimension2.push(dimension2Entry);
firstDataCell = 2;
}
const matrixRow = row
let matrixRow = row
.slice(firstDataCell, row.length)
.map((cell, cellIndex) => {
const measurementInformation = measurements[cellIndex];
@@ -143,30 +142,59 @@ function generateDataSet (component, dimensionsInformation, measurementsInformat
return generatedCell;
});
let appendToRowIndex = matrix.length;
if (hasSecondDimension) {
const currentDim1Entry = row[0].qText;
const isSameDimension1AsPrevious = currentDim1Entry === previousDim1Entry;
if (isSameDimension1AsPrevious) {
const updatedRow = matrix[matrix.length - 1].concat(matrixRow);
matrix = [
...matrix.slice(0, matrix.length - 1),
updatedRow
];
} else {
matrix[matrix.length] = matrixRow;
// See if there already is a row for the current dim1
for (let i = 0; i < matrix.length; i++) {
if (matrix[i][0].parents.dimension1.header === matrixRow[0].parents.dimension1.header) {
appendToRowIndex = i;
matrixRow = matrix[i].concat(matrixRow);
}
}
previousDim1Entry = currentDim1Entry;
} else {
matrix[matrix.length] = matrixRow;
}
matrix[appendToRowIndex] = matrixRow;
});
// filter header dimensions to only have distinct values
dimension1 = distinctArray(dimension1);
dimension2 = distinctArray(dimension2);
// Make sure all rows are saturated, otherwise data risks being displayed in the wrong column
matrix = matrix.map((row, rowIndex) => {
if (row.length == dimension2.length) {
// Row is saturated
return row;
}
// Row is not saturated, so must add empty cells to fill the gaps
let newRow = [];
let cellIndex = 0;
dimension2.forEach(dim => {
measurements.forEach(measurement => {
if (cellIndex < row.length
&& row[cellIndex].parents.dimension2.elementNumber === dim.elementNumber
&& row[cellIndex].parents.measurement.header === measurement.name) {
newRow.push(row[cellIndex]);
cellIndex++;
} else {
newRow.push({
displayValue: '',
parents: {
dimension1: { elementNumber: rowIndex },
dimension2: { elementNumber: dim.elementNumber },
measurement: { header: measurement.name }
}
});
}
});
});
return newRow;
});
return {
dimension1: distinctArray(dimension1),
dimension2: distinctArray(dimension2),
dimension1: dimension1,
dimension2: dimension2,
matrix,
measurements
};