Compare commits
15 Commits
QB-377/err
...
QLIK-98564
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5dc8bb49a4 | ||
|
|
79e753c2b2 | ||
|
|
468598540f | ||
|
|
045d0db215 | ||
|
|
73011d0388 | ||
|
|
41cf77e8d2 | ||
|
|
1355381346 | ||
|
|
730f35a83c | ||
|
|
71bf25e8fb | ||
|
|
9b4fe54239 | ||
|
|
e59c594215 | ||
|
|
97a54e6f5a | ||
|
|
eac9fd2a5f | ||
|
|
96f09f9323 | ||
|
|
58d0f542eb |
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"json.format.enable": false
|
||||||
|
}
|
||||||
@@ -1,14 +1,16 @@
|
|||||||
|
/* eslint-disable react/sort-prop-types */
|
||||||
|
/* eslint-disable space-before-function-paren */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import Tooltip from '../tooltip/index.jsx';
|
import Tooltip from '../tooltip/index.jsx';
|
||||||
|
|
||||||
class DataCell extends React.PureComponent {
|
class DataCell extends React.PureComponent {
|
||||||
constructor (props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.handleSelect = this.handleSelect.bind(this);
|
this.handleSelect = this.handleSelect.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSelect () {
|
handleSelect() {
|
||||||
const {
|
const {
|
||||||
data: {
|
data: {
|
||||||
meta: {
|
meta: {
|
||||||
@@ -26,14 +28,14 @@ class DataCell extends React.PureComponent {
|
|||||||
if (!allowFilteringByClick) {
|
if (!allowFilteringByClick) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// fixes the console error on selection made from data cells
|
||||||
component.backendApi.selectValues(0, [measurement.parents.dimension1.elementNumber], false);
|
component.selectValues(0, [measurement.parents.dimension1.elementNumber], false);
|
||||||
if (hasSecondDimension) {
|
if (hasSecondDimension) {
|
||||||
component.backendApi.selectValues(1, [measurement.parents.dimension2.elementNumber], false);
|
component.selectValues(1, [measurement.parents.dimension2.elementNumber], false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render() {
|
||||||
const {
|
const {
|
||||||
cellWidth,
|
cellWidth,
|
||||||
measurement,
|
measurement,
|
||||||
@@ -41,9 +43,9 @@ class DataCell extends React.PureComponent {
|
|||||||
styling
|
styling
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
let textAlignment = styling.options.textAlignment || 'Right';
|
const textAlignment = styling.options.textAlignment || 'Right';
|
||||||
|
|
||||||
let cellStyle = {
|
const cellStyle = {
|
||||||
fontFamily: styling.options.fontFamily,
|
fontFamily: styling.options.fontFamily,
|
||||||
...styleBuilder.getStyle(),
|
...styleBuilder.getStyle(),
|
||||||
paddingLeft: '5px',
|
paddingLeft: '5px',
|
||||||
@@ -64,10 +66,10 @@ class DataCell extends React.PureComponent {
|
|||||||
const { conditionalColoring } = styling;
|
const { conditionalColoring } = styling;
|
||||||
if (conditionalColoring.enabled) {
|
if (conditionalColoring.enabled) {
|
||||||
const isValidConditionalColoringValue = !styleBuilder.hasComments() && !isNaN(measurement.value);
|
const isValidConditionalColoringValue = !styleBuilder.hasComments() && !isNaN(measurement.value);
|
||||||
const isSpecifiedRow =
|
const isSpecifiedRow
|
||||||
conditionalColoring.rows.indexOf(measurement.parents.dimension1.header) !== -1;
|
= conditionalColoring.rows.indexOf(measurement.parents.dimension1.header) !== -1;
|
||||||
const isSpecifiedMeasure =
|
const isSpecifiedMeasure
|
||||||
conditionalColoring.measures.indexOf(measurement.parents.measurement.index) !== -1;
|
= conditionalColoring.measures.indexOf(measurement.parents.measurement.index) !== -1;
|
||||||
const shouldHaveConditionalColoring = (conditionalColoring.colorAllRows || isSpecifiedRow)
|
const shouldHaveConditionalColoring = (conditionalColoring.colorAllRows || isSpecifiedRow)
|
||||||
&& (conditionalColoring.colorAllMeasures || isSpecifiedMeasure);
|
&& (conditionalColoring.colorAllMeasures || isSpecifiedMeasure);
|
||||||
if (isValidConditionalColoringValue && shouldHaveConditionalColoring) {
|
if (isValidConditionalColoringValue && shouldHaveConditionalColoring) {
|
||||||
@@ -112,7 +114,7 @@ DataCell.propTypes = {
|
|||||||
}).isRequired,
|
}).isRequired,
|
||||||
component: PropTypes.shape({
|
component: PropTypes.shape({
|
||||||
backendApi: PropTypes.shape({
|
backendApi: PropTypes.shape({
|
||||||
selectValues: function (props, propName) {
|
selectValues (props, propName) {
|
||||||
if (props.isSnapshot || typeof props[propName] === 'function') {
|
if (props.isSnapshot || typeof props[propName] === 'function') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -130,7 +132,7 @@ DataCell.propTypes = {
|
|||||||
|
|
||||||
export default DataCell;
|
export default DataCell;
|
||||||
|
|
||||||
function formatMeasurementValue (measurement, styling) {
|
function formatMeasurementValue(measurement, styling) {
|
||||||
if (isNaN(measurement.value)) {
|
if (isNaN(measurement.value)) {
|
||||||
return styling.symbolForNulls;
|
return styling.symbolForNulls;
|
||||||
}
|
}
|
||||||
@@ -138,7 +140,7 @@ function formatMeasurementValue (measurement, styling) {
|
|||||||
return measurement.displayValue;
|
return measurement.displayValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getConditionalColor (measurement, conditionalColoring) {
|
function getConditionalColor(measurement, conditionalColoring) {
|
||||||
if (measurement.value < conditionalColoring.threshold.poor) {
|
if (measurement.value < conditionalColoring.threshold.poor) {
|
||||||
return conditionalColoring.colors.poor;
|
return conditionalColoring.colors.poor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,20 +43,42 @@ class DataTable extends React.PureComponent {
|
|||||||
return injectSeparatorsArray;
|
return injectSeparatorsArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
let measurementDataRow = [],
|
const measurementDataRow = [];
|
||||||
index = 0;
|
let index = 0,
|
||||||
|
match;
|
||||||
dimension2.forEach((dim2) => {
|
dimension2.forEach((dim2) => {
|
||||||
measurements.forEach((measure) => {
|
measurements.forEach((measure, mesInd) => {
|
||||||
for (index = 0; index < injectSeparatorsArray.length; index++) {
|
for (index = 0; index < injectSeparatorsArray.length; index++) {
|
||||||
|
match = false;
|
||||||
if (injectSeparatorsArray[index].parents && dimension1[dimIndex].displayValue === injectSeparatorsArray[index].parents.dimension1.header) {
|
if (injectSeparatorsArray[index].parents && dimension1[dimIndex].displayValue === injectSeparatorsArray[index].parents.dimension1.header) {
|
||||||
if (dim2.displayValue === injectSeparatorsArray[index].parents.dimension2.header) {
|
if (dim2.displayValue === injectSeparatorsArray[index].parents.dimension2.header) {
|
||||||
if (measure.name === injectSeparatorsArray[index].parents.measurement.header) {
|
if (measure.name === injectSeparatorsArray[index].parents.measurement.header) {
|
||||||
measurementDataRow.push(injectSeparatorsArray[index]);
|
measurementDataRow.push(injectSeparatorsArray[index]);
|
||||||
|
match = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!match) {
|
||||||
|
measurementDataRow.push({
|
||||||
|
displayValue: '',
|
||||||
|
parents: {
|
||||||
|
dimension1: {
|
||||||
|
elementNumber: dimension1[dimIndex].elementNumber,
|
||||||
|
header: dimension1[dimIndex].displayValue
|
||||||
|
},
|
||||||
|
dimension2: {
|
||||||
|
elementNumber: dim2.elementNumber,
|
||||||
|
header: dim2.displayValue
|
||||||
|
},
|
||||||
|
measurement: {
|
||||||
|
header: measure.name,
|
||||||
|
index: mesInd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return measurementDataRow;
|
return measurementDataRow;
|
||||||
|
|||||||
@@ -10,9 +10,10 @@ class RowHeader extends React.PureComponent {
|
|||||||
this.handleSelect = this.handleSelect.bind(this);
|
this.handleSelect = this.handleSelect.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fixes the console error on row selected values
|
||||||
handleSelect () {
|
handleSelect () {
|
||||||
const { component, entry } = this.props;
|
const { component, entry } = this.props;
|
||||||
component.backendApi.selectValues(0, [entry.elementNumber], false);
|
component.selectValues(0, [entry.elementNumber], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
@@ -42,13 +43,9 @@ class RowHeader extends React.PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RowHeader.propTypes = {
|
RowHeader.propTypes = {
|
||||||
entry: PropTypes.shape({
|
|
||||||
displayValue: PropTypes.string.isRequired,
|
|
||||||
elementNumber: PropTypes.number.isRequired
|
|
||||||
}).isRequired,
|
|
||||||
component: PropTypes.shape({
|
component: PropTypes.shape({
|
||||||
backendApi: PropTypes.shape({
|
backendApi: PropTypes.shape({
|
||||||
selectValues: function (props, propName) {
|
selectValues (props, propName) {
|
||||||
if (props.isSnapshot || typeof props[propName] === 'function') {
|
if (props.isSnapshot || typeof props[propName] === 'function') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -56,6 +53,10 @@ RowHeader.propTypes = {
|
|||||||
}
|
}
|
||||||
}).isRequired
|
}).isRequired
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
|
entry: PropTypes.shape({
|
||||||
|
displayValue: PropTypes.string.isRequired,
|
||||||
|
elementNumber: PropTypes.number.isRequired
|
||||||
|
}).isRequired,
|
||||||
rowStyle: PropTypes.shape({}).isRequired,
|
rowStyle: PropTypes.shape({}).isRequired,
|
||||||
styleBuilder: PropTypes.shape({}).isRequired,
|
styleBuilder: PropTypes.shape({}).isRequired,
|
||||||
styling: PropTypes.shape({}).isRequired
|
styling: PropTypes.shape({}).isRequired
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
|
/* eslint-disable object-shorthand */
|
||||||
|
/* eslint-disable space-before-function-paren */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { HEADER_FONT_SIZE } from '../initialize-transformed';
|
import { HEADER_FONT_SIZE } from '../initialize-transformed';
|
||||||
import Tooltip from '../tooltip/index.jsx';
|
import Tooltip from '../tooltip/index.jsx';
|
||||||
|
|
||||||
class ColumnHeader extends React.PureComponent {
|
class ColumnHeader extends React.PureComponent {
|
||||||
constructor (props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.handleSelect = this.handleSelect.bind(this);
|
this.handleSelect = this.handleSelect.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSelect () {
|
// fixes console error for column selected values
|
||||||
|
handleSelect() {
|
||||||
const { component, entry } = this.props;
|
const { component, entry } = this.props;
|
||||||
component.backendApi.selectValues(1, [entry.elementNumber], false);
|
component.selectValues(1, [entry.elementNumber], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render() {
|
||||||
const { baseCSS, cellWidth, colSpan, component, entry, styling } = this.props;
|
const { baseCSS, cellWidth, colSpan, component, entry, styling } = this.props;
|
||||||
const inEditState = component.inEditState();
|
const inEditState = component.inEditState();
|
||||||
const isMediumFontSize = styling.headerOptions.fontSizeAdjustment === HEADER_FONT_SIZE.MEDIUM;
|
const isMediumFontSize = styling.headerOptions.fontSizeAdjustment === HEADER_FONT_SIZE.MEDIUM;
|
||||||
|
|||||||
28
src/index.js
28
src/index.js
@@ -115,19 +115,21 @@ export default {
|
|||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.addItem({
|
if (typeof (this.backendApi.model.layout.qMeta.privileges[3]) !== 'undefined' && this.backendApi.model.layout.qMeta.privileges[3] === 'exportdata') {
|
||||||
translation: 'Export as XLS',
|
menu.addItem({
|
||||||
tid: 'export-excel',
|
translation: 'Export as XLS',
|
||||||
icon: 'export',
|
tid: 'export-excel',
|
||||||
select: () => {
|
icon: 'export',
|
||||||
exportXLS(
|
select: () => {
|
||||||
this.$element,
|
exportXLS(
|
||||||
this.$scope.layout.title,
|
this.$element,
|
||||||
this.$scope.layout.subtitle,
|
this.$scope.layout.title,
|
||||||
this.$scope.layout.footnote
|
this.$scope.layout.subtitle,
|
||||||
);
|
this.$scope.layout.footnote
|
||||||
}
|
);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
return menu;
|
return menu;
|
||||||
},
|
},
|
||||||
version: 1.0
|
version: 1.0
|
||||||
|
|||||||
@@ -127,30 +127,6 @@ function generateDataSet (component, dimensionsInformation, measurementsInformat
|
|||||||
dimension1 = distinctArray(dimension1);
|
dimension1 = distinctArray(dimension1);
|
||||||
dimension2 = distinctArray(dimension2);
|
dimension2 = distinctArray(dimension2);
|
||||||
|
|
||||||
// Make sure all rows are saturated, otherwise data risks being displayed in the wrong column
|
|
||||||
matrix = matrix.map((row, rowIndex) => {
|
|
||||||
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 = [];
|
|
||||||
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, dimension1);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
appendMissingCells(row, newRow, 0, measurements, rowIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return newRow;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dimension1: dimension1,
|
dimension1: dimension1,
|
||||||
dimension2: dimension2,
|
dimension2: dimension2,
|
||||||
@@ -159,45 +135,6 @@ function generateDataSet (component, dimensionsInformation, measurementsInformat
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* 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, matrixIndex, dim2, dim1) {
|
|
||||||
|
|
||||||
let index = sourceIndex;
|
|
||||||
measurements.forEach((measurement, measureIndex) => {
|
|
||||||
if (index < sourceRow.length) {
|
|
||||||
// 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: dim1[matrixIndex].elementNumber,
|
|
||||||
header: dim1[matrixIndex].displayValue
|
|
||||||
},
|
|
||||||
dimension2: {
|
|
||||||
elementNumber: dim2.elementNumber,
|
|
||||||
header: dim2.displayValue
|
|
||||||
},
|
|
||||||
measurement: {
|
|
||||||
header: measurement.name,
|
|
||||||
index: measureIndex
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
function initializeTransformed ({ component, dataCube, designList, layout }) {
|
function initializeTransformed ({ component, dataCube, designList, layout }) {
|
||||||
const dimensionsInformation = component.backendApi.getDimensionInfos();
|
const dimensionsInformation = component.backendApi.getDimensionInfos();
|
||||||
const measurementsInformation = component.backendApi.getMeasureInfos();
|
const measurementsInformation = component.backendApi.getMeasureInfos();
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ const path = require('path');
|
|||||||
|
|
||||||
const DIST = path.resolve("./dist");
|
const DIST = path.resolve("./dist");
|
||||||
const MODE = process.env.NODE_ENV || 'development';
|
const MODE = process.env.NODE_ENV || 'development';
|
||||||
|
const SOURCE_MAP = 'sourec-map';
|
||||||
|
const DEVTOOL = (process.env.NODE_ENV === 'development') ? SOURCE_MAP : false;
|
||||||
|
|
||||||
console.log('Webpack mode:', MODE); // eslint-disable-line no-console
|
console.log('Webpack mode:', MODE); // eslint-disable-line no-console
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
devtool: 'source-map',
|
devtool: DEVTOOL,
|
||||||
entry: ['./src/index.js'],
|
entry: ['./src/index.js'],
|
||||||
externals: {
|
externals: {
|
||||||
jquery: {
|
jquery: {
|
||||||
|
|||||||
Reference in New Issue
Block a user