Compare commits

...

14 Commits

Author SHA1 Message Date
Purwa Shrivastava
26de3b63ed Merge pull request #56 from qlik-oss/DEB-213/misalignedTable
DEB-213: Introdued a minimum height for the table rows, so even if th…
2019-05-02 13:04:17 +02:00
Purwa Shrivastava
8eafeffcec DEB-213: Introdued a minimum height for the table rows, so even if the content is null, the rows are displayed even. 2019-05-02 11:31:15 +02:00
Albert Backenhof
98401db922 Merge pull request #52 from qlik-oss/saturateMatrix
Fixed bug that prevented row saturation
2019-04-23 07:01:34 +02:00
Albert Backenhof
75771e4815 Merge pull request #50 from qlik-oss/DEB-187/ColorMeasures
Color by measure indices
2019-04-23 07:01:25 +02:00
Albert Backenhof
a12205c840 Fixed bug that prevented row saturation 2019-04-18 09:44:07 +02:00
Albert Backenhof
ebfee69c7b Merge pull request #51 from qlik-oss/DEB-188/LimitSize
Fixed layout and styling of table
2019-04-18 08:28:26 +02:00
Albert Backenhof
05c25c72cb Fixed layout and styling of table
-Now using flexbox to make the layout more
 dynamic.
-Row selection of hover works as intended.
-Improved the way scrollbars are shown.

Issue: DEB-188, DEB-192
2019-04-17 11:02:23 +02:00
Albert Backenhof
d2a24dd256 Color by measure indices
-Used to specify what measure columns should
 use conditional coloring.

Issue: DEB-187
2019-04-15 14:15:12 +02:00
Albert Backenhof
a6a6ef24b5 Merge pull request #49 from qlik-oss/DEB-183/CellSpacing
Fixed cellspacing on IE, Edge and FF
2019-04-15 07:01:48 +02:00
Albert Backenhof
8374ecce85 Merge pull request #48 from qlik-oss/DEB-182/OverlayScrollbar
Overlay scrollbar in webkit browsers
2019-04-15 07:01:29 +02:00
Albert Backenhof
0135d4fc64 Merge pull request #43 from qlik-oss/DEB-176/EmptyMeasureCells
Show cells for single-dimension tables
2019-04-15 07:01:06 +02:00
Albert Backenhof
3ec5d13ae6 Fixed cellspacing on IE, Edge and FF
Issue: DEB-183
2019-04-12 09:37:49 +02:00
Albert Backenhof
2133bb44ef Overlay scrollbar in webkit browsers
-To prevent scrollbar from offsetting the cells
 those browsers that support overlay scrollbars
 should use it.

Issue: DEB-182
2019-04-12 08:15:37 +02:00
Albert Backenhof
b1a9130663 Show cells for single-dimension tables
-Recent commit introduced a bug that prevented
 single-dimension tables from showing any cells.

Issue: DEB-176
2019-04-10 13:41:24 +02:00
9 changed files with 198 additions and 96 deletions

View File

@@ -59,7 +59,10 @@ class DataCell extends React.PureComponent {
const isValidConditionalColoringValue = !styleBuilder.hasComments() && !isNaN(measurement.value);
const isSpecifiedRow =
conditionalColoring.rows.indexOf(measurement.parents.dimension1.header) !== -1;
const shouldHaveConditionalColoring = conditionalColoring.colorAllRows || isSpecifiedRow;
const isSpecifiedMeasure =
conditionalColoring.measures.indexOf(measurement.parents.measurement.index) !== -1;
const shouldHaveConditionalColoring = (conditionalColoring.colorAllRows || isSpecifiedRow)
&& (conditionalColoring.colorAllMeasures || isSpecifiedMeasure);
if (isValidConditionalColoringValue && shouldHaveConditionalColoring) {
const { color, textColor } = getConditionalColor(measurement, conditionalColoring);
cellStyle.backgroundColor = color.color;

View File

@@ -61,6 +61,36 @@ const conditionalColoring = {
return data.conditionalcoloring.enabled && !data.conditionalcoloring.colorall;
}
},
ColorAllMeasures: {
ref: 'conditionalcoloring.colorallmeasures',
type: 'boolean',
label: 'Color all measures',
component: 'switch',
defaultValue: true,
options: [
{
value: true,
label: 'All measures'
},
{
value: false,
label: 'Specified measures'
}
],
show (data) {
return data.conditionalcoloring.enabled;
}
},
Measures: {
ref: 'conditionalcoloring.measures',
translation: 'Measure indices (ex: 0,3)',
type: 'string',
defaultValue: '',
show (data) {
return data.conditionalcoloring.enabled
&& data.conditionalcoloring.colorallmeasures === false;
}
},
ThresholdPoor: {
ref: 'conditionalcoloring.threshold_poor',
translation: 'Poor is less than',

View File

@@ -22,7 +22,7 @@ class ColumnHeader extends React.PureComponent {
const style = {
...baseCSS,
fontSize: `${14 + styling.headerOptions.fontSizeAdjustment}px`,
height: isMediumFontSize ? '45px' : '35px',
height: isMediumFontSize ? '43px' : '33px',
verticalAlign: 'middle'
};

View File

@@ -77,7 +77,7 @@ const HeadersTable = ({ data, general, qlik, styling, isKpi }) => {
);
})}
</tr>
{hasSecondDimension && (
{!isKpi && hasSecondDimension && (
<tr>
{injectSeparators(dimension2, styling.useSeparatorColumns).map((dimensionEntry, index) => {
if (dimensionEntry.isSeparator) {

View File

@@ -18,7 +18,6 @@ const MeasurementColumnHeader = ({ baseCSS, general, hasSecondDimension, measure
}
const cellStyle = {
...baseCSS,
cursor: 'default',
fontSize: `${baseFontSize + fontSizeAdjustment}px`,
height: isMediumFontSize ? '45px' : '35px',
verticalAlign: 'middle'
@@ -40,7 +39,6 @@ const MeasurementColumnHeader = ({ baseCSS, general, hasSecondDimension, measure
const style = {
...baseCSS,
cursor: 'default',
fontSize: `${15 + fontSizeAdjustment}px`,
height: isMediumFontSize ? '90px' : '70px',
verticalAlign: 'middle'

View File

@@ -90,7 +90,8 @@ function generateMatrixCell ({ cell, dimension1Information, dimension2Informatio
header: dimension1Information.qText
},
measurement: {
header: measurementInformation.name
header: measurementInformation.name,
index: measurementInformation.index
}
},
value: cell.qNum
@@ -130,6 +131,7 @@ function generateDataSet (
.slice(firstDataCell, row.length)
.map((cell, cellIndex) => {
const measurementInformation = measurements[cellIndex];
measurementInformation.index = cellIndex;
const dimension1Information = row[0]; // eslint-disable-line prefer-destructuring
const dimension2Information = hasSecondDimension ? row[1] : null;
const generatedCell = generateMatrixCell({
@@ -161,33 +163,24 @@ function generateDataSet (
// 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) {
if ((hasSecondDimension && row.length == (dimension2.length * measurements.length))
|| (!hasSecondDimension && row.length == measurements.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 }
}
});
}
if (hasSecondDimension) {
// Got a second dimension, so need to add measurements for all values of the second dimension
let rowDataIndex = 0;
dimension2.forEach(dim => {
rowDataIndex = appendMissingCells(
row, newRow, rowDataIndex, measurements, rowIndex, dim.elementNumber);
});
});
} else {
appendMissingCells(row, newRow, 0, measurements, rowIndex);
}
return newRow;
});
@@ -200,6 +193,42 @@ function generateDataSet (
};
}
/*
* Appends the cells of the source row, as well as those missing, to the destination row, starting
* from the given source index. Returns the source index of the next source cell after this has
* completed. If there is a second dimension the dim2ElementNumber should be set to the current
* index of the dimension2 value being processed.
*/
function appendMissingCells (
sourceRow, destRow, sourceIndex, measurements, dim1ElementNumber, dim2ElementNumber = -1) {
let index = sourceIndex;
measurements.forEach((measurement, measureIndex) => {
if (index < sourceRow.length
&& (dim2ElementNumber === -1
|| sourceRow[index].parents.dimension2.elementNumber === dim2ElementNumber)
&& sourceRow[index].parents.measurement.header === measurement.name) {
// Source contains the expected cell
destRow.push(sourceRow[index]);
index++;
} else {
// Source doesn't contain the expected cell, so add empty
destRow.push({
displayValue: '',
parents: {
dimension1: { elementNumber: dim1ElementNumber },
dimension2: { elementNumber: dim2ElementNumber },
measurement: {
header: measurement.name,
index: measureIndex
}
}
});
}
});
return index;
}
function initializeTransformed ({ $element, component, dataCube, designList, layout }) {
const dimensionsInformation = component.backendApi.getDimensionInfos();
const measurementsInformation = component.backendApi.getMeasureInfos();
@@ -285,6 +314,10 @@ function initializeTransformed ({ $element, component, dataCube, designList, lay
enabled: layout.conditionalcoloring.enabled,
colorAllRows: layout.conditionalcoloring.colorall,
rows: layout.conditionalcoloring.rows.map(row => row.rowname),
colorAllMeasures: typeof layout.conditionalcoloring.colorallmeasures === 'undefined'
|| layout.conditionalcoloring.colorallmeasures,
measures: !layout.conditionalcoloring.measures
? [] : layout.conditionalcoloring.measures.split(',').map(index => Number(index)),
threshold: {
poor: layout.conditionalcoloring.threshold_poor,
fair: layout.conditionalcoloring.threshold_fair

View File

@@ -1,6 +1,5 @@
/* eslint-disable */
.qv-object-qlik-smart-pivot {
@TableBorder: 1px solid #d3d3d3;
@KpiTableWidth: 230px;
*,
@@ -33,18 +32,17 @@
}
table {
border-collapse: collapse;
border-spacing: 0;
border-collapse: separate;
border-spacing: 1px;
width: auto;
border-left: @TableBorder;
border-right: @TableBorder;
border-top: @TableBorder;
}
tr {
height: 23px;
}
td,
th {
border: 1px solid #fff;
border-collapse: collapse;
padding: 5px !important; // prevent overwriting from single object
white-space: nowrap;
overflow: hidden;
@@ -70,7 +68,6 @@
th.main-kpi {
text-align: center;
vertical-align: middle;
border-bottom: @TableBorder;
}
.numeric {
@@ -146,12 +143,7 @@
background-color: #fff;
}
.fdim-cells:hover {
background-color: #808080 !important;
color: #fff;
}
tbody tr:hover {
tbody tr:hover td {
cursor: default;
background-color: #808080 !important;
color: #fff;
@@ -178,29 +170,50 @@
border: groove;
}
.root {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
height: 100%;
width: 100%;
}
.kpi-table .fdim-cells,
.data-table td {
line-height: 1em !important;
}
.kpi-table {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
flex: none;
width: @KpiTableWidth !important;
overflow: hidden !important;
height: 100%;
margin: 0;
padding: 0;
position: absolute;
top: 0;
left: 0;
border-right: 1px solid #fff;
box-shadow: 4px 2px 8px #e1e1e1;
.header-wrapper {
flex: none;
box-shadow: 4px 2px 8px #e1e1e1;
}
.row-wrapper {
height: calc(~"100% - 92px");
overflow: scroll;
position: absolute;
margin: 0;
margin-bottom: 8px;
padding: 0;
margin-top: 0;
box-shadow: 4px 2px 8px #e1e1e1;
min-height: 0; /* This is to make flex size-filling work */
/* Adapt for Edge */
@supports (-ms-ime-align: auto) {
margin-bottom: 16px;
}
/* Adapt for IE11 */
@media screen and (-ms-high-contrast: none) {
margin-bottom: 16px;
}
}
}
@@ -209,27 +222,50 @@
}
.data-table {
height: 100%;
width: calc(100% - 243px);
position: absolute;
margin-left: @KpiTableWidth + 13px;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
margin-left: 13px;
min-width: 0; /* This is to make flex size-filling work */
.header-wrapper {
flex: none;
overflow: scroll;
width: 100%;
margin-right: 8px;
}
.row-wrapper {
height: calc(~"100% - 92px");
width: 100%;
overflow: scroll;
margin: 0;
padding: 0;
margin-top: 0;
min-height: 0; /* This is to make flex size-filling work */
/* Style scrollbar for FF */
scrollbar-width: thin;
scrollbar-color: #d3d3d3 transparent;
}
/* Adapt for Edge */
@supports (-ms-ime-align: auto) {
.header-wrapper {
margin-right: 16px;
}
}
/* Adapt for IE11 */
@media screen and (-ms-high-contrast: none) {
width: 100%;
height: 100%;
.header-wrapper {
margin-right: 16px;
}
}
}
// hide scrollbars
.kpi-table .header-wrapper,
.kpi-table .row-wrapper,
.data-table .header-wrapper {
// stylelint-disable-next-line property-no-unknown
scrollbar-width: none;

View File

@@ -5,48 +5,50 @@ import DataTable from './data-table/index.jsx';
import { LinkedScrollWrapper, LinkedScrollSection } from './linked-scroll';
const Root = ({ state, qlik, editmodeClass }) => (
<LinkedScrollWrapper>
<div className={`kpi-table ${editmodeClass}`}>
<HeadersTable
data={state.data}
general={state.general}
isKpi
qlik={qlik}
styling={state.styling}
/>
<LinkedScrollSection linkVertical>
<DataTable
data={state.data}
general={state.general}
qlik={qlik}
renderData={false}
styling={state.styling}
/>
</LinkedScrollSection>
</div>
<div className={`data-table ${editmodeClass}`}>
<LinkedScrollSection linkHorizontal>
<div className="root">
<LinkedScrollWrapper>
<div className={`kpi-table ${editmodeClass}`}>
<HeadersTable
data={state.data}
general={state.general}
isKpi={false}
isKpi
qlik={qlik}
styling={state.styling}
/>
</LinkedScrollSection>
<LinkedScrollSection
linkHorizontal
linkVertical
>
<DataTable
data={state.data}
general={state.general}
qlik={qlik}
styling={state.styling}
/>
</LinkedScrollSection>
</div>
</LinkedScrollWrapper>
<LinkedScrollSection linkVertical>
<DataTable
data={state.data}
general={state.general}
qlik={qlik}
renderData={false}
styling={state.styling}
/>
</LinkedScrollSection>
</div>
<div className={`data-table ${editmodeClass}`}>
<LinkedScrollSection linkHorizontal>
<HeadersTable
data={state.data}
general={state.general}
isKpi={false}
qlik={qlik}
styling={state.styling}
/>
</LinkedScrollSection>
<LinkedScrollSection
linkHorizontal
linkVertical
>
<DataTable
data={state.data}
general={state.general}
qlik={qlik}
styling={state.styling}
/>
</LinkedScrollSection>
</div>
</LinkedScrollWrapper>
</div>
);
Root.propTypes = {

View File

@@ -84,7 +84,7 @@ module.exports = {
'indentation': 2,
'length-zero-no-unit': true,
'max-empty-lines': 1,
'max-nesting-depth': 3,
'max-nesting-depth': 5,
'media-feature-colon-space-after': 'always',
'media-feature-colon-space-before': 'never',
'media-feature-name-case': 'lower',