From f2f201c6e2cbb973a7b8f52492a5ed0efceaccf8 Mon Sep 17 00:00:00 2001 From: Kristoffer Lind Date: Fri, 8 Feb 2019 14:04:48 +0100 Subject: [PATCH 01/15] let react handle rendering --- src/data-table/data-cell.jsx | 103 +++++++++------ src/data-table/index.jsx | 133 ++++++++++--------- src/data-table/row-header.jsx | 49 +++++++ src/headers-table/column-header.jsx | 61 ++++++--- src/headers-table/index.jsx | 16 ++- src/initialize-transformed.js | 49 +++++-- src/paint.jsx | 195 ++++++---------------------- src/store.js | 133 +------------------ 8 files changed, 319 insertions(+), 420 deletions(-) create mode 100644 src/data-table/row-header.jsx diff --git a/src/data-table/data-cell.jsx b/src/data-table/data-cell.jsx index 7178553..2407195 100644 --- a/src/data-table/data-cell.jsx +++ b/src/data-table/data-cell.jsx @@ -5,7 +5,7 @@ import { addSeparators } from '../utilities'; function formatMeasurementValue (measurement, styling) { // TODO: measurement.name is a horrible propertyname, it's actually the column header - const isColumnPercentageBased = measurement.name.substring(0, 1) === '%'; + const isColumnPercentageBased = measurement.parents.measurement.header.substring(0, 1) === '%'; let formattedMeasurementValue = ''; if (isColumnPercentageBased) { if (isNaN(measurement.value)) { @@ -62,50 +62,74 @@ function getSemaphoreColors (measurement, semaphoreColors) { return semaphoreColors.statusColors.normal; } -const DataCell = ({ data, general, measurement, styleBuilder, styling }) => { - const isColumnPercentageBased = measurement.name.substring(0, 1) === '%'; - let formattedMeasurementValue = formatMeasurementValue(measurement, styling); - if (styleBuilder.hasComments()) { - formattedMeasurementValue = '.'; +class DataCell extends React.PureComponent { + constructor (props) { + super(props); + + this.handleSelect = this.handleSelect.bind(this); } - let cellStyle = { - fontFamily: styling.options.fontFamily, - ...styleBuilder.getStyle(), - paddingRight: '4px', - textAlign: 'right' + handleSelect () { + const { data: { meta: { dimensionCount } }, general: { allowFilteringByClick }, measurement, qlik } = this.props; + const hasSecondDimension = dimensionCount > 1; + if (!allowFilteringByClick) { + return; + } - }; - const { semaphoreColors } = styling; - const isValidSemaphoreValue = !styleBuilder.hasComments() && !isNaN(measurement.value); - const shouldHaveSemaphoreColors = semaphoreColors.fieldsToApplyTo.applyToAll || semaphoreColors.fieldsToApplyTo.specificFields.indexOf(measurement.name) !== -1; - if (isValidSemaphoreValue && shouldHaveSemaphoreColors) { - const { backgroundColor, color } = getSemaphoreColors(measurement, semaphoreColors); - cellStyle = { - backgroundColor, - color, + qlik.backendApi.selectValues(0, [measurement.parents.dimension1.elementNumber], true); + + if (hasSecondDimension) { + qlik.backendApi.selectValues(1, [measurement.parents.dimension2.elementNumber], true); + } + } + + render () { + const { data, general, measurement, styleBuilder, styling } = this.props; + const isColumnPercentageBased = measurement.name.substring(0, 1) === '%'; + let formattedMeasurementValue = formatMeasurementValue(measurement, styling); + if (styleBuilder.hasComments()) { + formattedMeasurementValue = '.'; + } + + let cellStyle = { fontFamily: styling.options.fontFamily, - fontSize: styleBuilder.getStyle().fontSize, - paddingLeft: '4px', + ...styleBuilder.getStyle(), + paddingRight: '4px', textAlign: 'right' + }; - } + const { semaphoreColors } = styling; + const isValidSemaphoreValue = !styleBuilder.hasComments() && !isNaN(measurement.value); + const shouldHaveSemaphoreColors = semaphoreColors.fieldsToApplyTo.applyToAll || semaphoreColors.fieldsToApplyTo.specificFields.indexOf(measurement.parents.dimension1.header) !== -1; + if (isValidSemaphoreValue && shouldHaveSemaphoreColors) { + const { backgroundColor, color } = getSemaphoreColors(measurement, semaphoreColors); + cellStyle = { + backgroundColor, + color, + fontFamily: styling.options.fontFamily, + fontSize: styleBuilder.getStyle().fontSize, + paddingLeft: '4px', + textAlign: 'right' + }; + } - let cellClass = 'grid-cells'; - const shouldUseSmallCells = isColumnPercentageBased && data.headers.measurements.length > 1; - if (shouldUseSmallCells) { - cellClass = 'grid-cells-small'; - } + let cellClass = 'grid-cells'; + const shouldUseSmallCells = isColumnPercentageBased && data.headers.measurements.length > 1; + if (shouldUseSmallCells) { + cellClass = 'grid-cells-small'; + } - return ( - - {formattedMeasurementValue} - - ); -}; + return ( + + {formattedMeasurementValue} + + ); + } +} DataCell.propTypes = { data: PropTypes.shape({ @@ -121,6 +145,11 @@ DataCell.propTypes = { name: PropTypes.string, value: PropTypes.any }).isRequired, + qlik: PropTypes.shape({ + backendApi: PropTypes.shape({ + selectValues: PropTypes.func.isRequired + }).isRequired + }).isRequired, styleBuilder: PropTypes.shape({ hasComments: PropTypes.func.isRequired }).isRequired, diff --git a/src/data-table/index.jsx b/src/data-table/index.jsx index afe4aa5..5da451c 100644 --- a/src/data-table/index.jsx +++ b/src/data-table/index.jsx @@ -3,9 +3,10 @@ import PropTypes from 'prop-types'; import StyleBuilder from '../style-builder'; import DataCell from './data-cell.jsx'; import HeaderPadding from './header-padding.jsx'; +import RowHeader from './row-header.jsx'; import { injectSeparators } from '../utilities'; -const DataTable = ({ data, general, styling }) => { +const DataTable = ({ data, general, qlik, renderData, styling }) => { const { headers: { dimension1, @@ -17,79 +18,85 @@ const DataTable = ({ data, general, styling }) => { 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() - }; + + {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() + }; - return ( - - - {injectSeparators( - matrix[dimensionIndex], - styling.useSeparatorColumns, - { atEvery: measurements.length } - ).map(measurementData => { - if (measurementData.isSeparator) { - const separatorStyle = { - color: 'white', - fontFamily: styling.options.fontFamily, - fontSize: `${12 + styling.options.fontSizeAdjustment}px` - }; + {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` + }; + return ( + + ); + } + const { dimension1: dimension1Info, dimension2, measurement } = measurementData.parents; + const id = `${dimension1Info.elementNumber}-${dimension2 && dimension2.elementNumber}-${measurement.header}`; return ( - + ); - } - return ( - - ); - })} - - ); - })} + })} + + ); + })} +
- + - {dimensionEntry.displayValue} - + * + - * -
); }; +DataTable.defaultProps = { + renderData: true +}; + DataTable.propTypes = { data: PropTypes.shape({ headers: PropTypes.shape({ @@ -98,6 +105,8 @@ DataTable.propTypes = { matrix: PropTypes.arrayOf(PropTypes.array.isRequired).isRequired }).isRequired, general: PropTypes.shape({}).isRequired, + qlik: PropTypes.shape({}).isRequired, + renderData: PropTypes.bool, styling: PropTypes.shape({ hasCustomFileStyle: PropTypes.bool.isRequired }).isRequired diff --git a/src/data-table/row-header.jsx b/src/data-table/row-header.jsx new file mode 100644 index 0000000..06da248 --- /dev/null +++ b/src/data-table/row-header.jsx @@ -0,0 +1,49 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import HeaderPadding from './header-padding.jsx'; + +class RowHeader extends React.PureComponent { + constructor (props) { + super(props); + + this.handleSelect = this.handleSelect.bind(this); + } + + handleSelect () { + const { entry, qlik } = this.props; + qlik.backendApi.selectValues(0, [entry.elementNumber], true); + } + + render () { + const { entry, rowStyle, styleBuilder, styling } = this.props; + return ( + + + {entry.displayValue} + + ); + } +} + +RowHeader.propTypes = { + entry: PropTypes.shape({ + displayValue: PropTypes.string.isRequired + }).isRequired, + qlik: PropTypes.shape({ + backendApi: PropTypes.shape({ + selectValues: PropTypes.func.isRequired + }).isRequired + }).isRequired, + rowStyle: PropTypes.shape({}).isRequired, + styleBuilder: PropTypes.shape({}).isRequired, + styling: PropTypes.shape({}).isRequired +}; + +export default RowHeader; diff --git a/src/headers-table/column-header.jsx b/src/headers-table/column-header.jsx index 3c9f251..d50d666 100644 --- a/src/headers-table/column-header.jsx +++ b/src/headers-table/column-header.jsx @@ -1,24 +1,39 @@ import React from 'react'; import PropTypes from 'prop-types'; -const ColumnHeader = ({ baseCSS, cellSuffix, colSpan, styling, title }) => { - const style = { - ...baseCSS, - fontSize: `${14 + styling.headerOptions.fontSizeAdjustment} px`, - height: '45px', - verticalAlign: 'middle' - }; +class ColumnHeader extends React.PureComponent { + constructor (props) { + super(props); - return ( - - {title} - - ); -}; + this.handleSelect = this.handleSelect.bind(this); + } + + handleSelect () { + const { entry, qlik } = this.props; + qlik.backendApi.selectValues(1, [entry.elementNumber], true); + } + + render () { + const { baseCSS, cellSuffix, colSpan, entry, styling } = this.props; + const style = { + ...baseCSS, + fontSize: `${14 + styling.headerOptions.fontSizeAdjustment} px`, + height: '45px', + verticalAlign: 'middle' + }; + + return ( + + {entry.displayValue} + + ); + } +} ColumnHeader.defaultProps = { cellSuffix: '', @@ -29,12 +44,20 @@ ColumnHeader.propTypes = { baseCSS: PropTypes.shape({}).isRequired, cellSuffix: PropTypes.string, colSpan: PropTypes.number, + entry: PropTypes.shape({ + elementNumber: PropTypes.number.isRequired, + name: PropTypes.string.isRequired + }).isRequired, + qlik: PropTypes.shape({ + backendApi: PropTypes.shape({ + selectValues: PropTypes.func.isRequired + }).isRequired + }).isRequired, styling: PropTypes.shape({ headerOptions: PropTypes.shape({ fontSizeAdjustment: PropTypes.number.isRequired }).isRequired - }).isRequired, - title: PropTypes.string.isRequired + }).isRequired }; export default ColumnHeader; diff --git a/src/headers-table/index.jsx b/src/headers-table/index.jsx index c45fa48..019a0f1 100644 --- a/src/headers-table/index.jsx +++ b/src/headers-table/index.jsx @@ -5,7 +5,7 @@ import ColumnHeader from './column-header.jsx'; import MeasurementColumnHeader from './measurement-column-header.jsx'; import { injectSeparators } from '../utilities'; -const HeadersTable = ({ data, general, styling }) => { +const HeadersTable = ({ data, general, qlik, styling }) => { const baseCSS = { backgroundColor: styling.headerOptions.colorSchema, color: styling.headerOptions.textColor, @@ -43,7 +43,7 @@ const HeadersTable = ({ data, general, styling }) => { styling={styling} /> ))} - {hasSecondDimension && injectSeparators(dimension2, styling.useSeparatorColumns).map(entry => { + {hasSecondDimension && injectSeparators(dimension2, styling.useSeparatorColumns).map((entry, index) => { if (entry.isSeparator) { const separatorStyle = { color: 'white', @@ -54,6 +54,7 @@ const HeadersTable = ({ data, general, styling }) => { return ( * @@ -65,16 +66,17 @@ const HeadersTable = ({ data, general, styling }) => { baseCSS={baseCSS} cellSuffix={general.cellSuffix} colSpan={measurements.length} + entry={entry} key={entry.displayValue} + qlik={qlik} styling={styling} - title={entry.displayValue} /> ); })} {hasSecondDimension && ( - {injectSeparators(dimension2, styling.useSeparatorColumns).map(dimensionEntry => { + {injectSeparators(dimension2, styling.useSeparatorColumns).map((dimensionEntry, index) => { if (dimensionEntry.isSeparator) { const separatorStyle = { color: 'white', @@ -85,6 +87,7 @@ const HeadersTable = ({ data, general, styling }) => { return ( * @@ -120,6 +123,11 @@ HeadersTable.propTypes = { }) }).isRequired, general: PropTypes.shape({}).isRequired, + qlik: PropTypes.shape({ + backendApi: PropTypes.shape({ + selectValues: PropTypes.func.isRequired + }).isRequired + }).isRequired, styling: PropTypes.shape({ headerOptions: PropTypes.shape({}), options: PropTypes.shape({}) diff --git a/src/initialize-transformed.js b/src/initialize-transformed.js index b58f7ca..f5e9585 100644 --- a/src/initialize-transformed.js +++ b/src/initialize-transformed.js @@ -91,24 +91,41 @@ function generateMeasurements (information) { function generateDimensionEntry (information, data) { return { displayValue: data.qText, + elementNumber: data.qElemNumber, name: information.qFallbackTitle, value: data.qNum }; } -function generateMatrixCell (information, data) { - return { - displayValue: data.qText, - elementNumber: data.qElemNumber, - format: information.format, - magnitude: information.magnitudeLabelSuffix.substring( - information.magnitudeLabelSuffix.length - 2, - information.magnitudeLabelSuffix.length - 1 +function generateMatrixCell ({ cell, dimension1Information, dimension2Information, measurementInformation }) { + const matrixCell = { + displayValue: cell.qText, + format: measurementInformation.format, + magnitude: measurementInformation.magnitudeLabelSuffix.substring( + measurementInformation.magnitudeLabelSuffix.length - 2, + measurementInformation.magnitudeLabelSuffix.length - 1 ), - magnitudeLabelSuffix: information.magnitudeLabelSuffix, - name: information.name, - value: data.qNum + magnitudeLabelSuffix: measurementInformation.magnitudeLabelSuffix, + name: measurementInformation.name, + parents: { + dimension1: { + elementNumber: dimension1Information.qElemNumber, + header: dimension1Information.qText + }, + measurement: { + header: measurementInformation.name + } + }, + value: cell.qNum }; + + if (dimension2Information) { + matrixCell.parents.dimension2 = { + elementNumber: dimension2Information.qElemNumber + }; + } + + return matrixCell; } let lastRow = 0; @@ -135,7 +152,14 @@ function generateDataSet (component, dimensionsInformation, measurementsInformat .slice(firstDataCell, row.length) .map((cell, cellIndex) => { const measurementInformation = measurements[cellIndex]; - const generatedCell = generateMatrixCell(measurementInformation, cell); + const dimension1Information = row[0]; // eslint-disable-line prefer-destructuring + const dimension2Information = hasSecondDimension ? row[1] : null; + const generatedCell = generateMatrixCell({ + cell, + dimension1Information, + dimension2Information, + measurementInformation + }); return generatedCell; }); @@ -228,6 +252,7 @@ async function initializeTransformed ({ $element, layout, component }) { }, general: { allowExcelExport: layout.allowexportxls, + allowFilteringByClick: layout.filteroncellclick, cellSuffix: getCellSuffix(layout.columnwidthslider), // TOOD: move to matrix cells or is it headers.measurements? errorMessage: layout.errormessage, maxLoops diff --git a/src/paint.jsx b/src/paint.jsx index 2ed949d..f16a912 100644 --- a/src/paint.jsx +++ b/src/paint.jsx @@ -1,9 +1,7 @@ import $ from 'jquery'; -import { enableExcelExport } from './excel-export'; import initializeStore from './store'; import React from 'react'; -// import ReactDOM from 'react-dom'; -import { renderToStaticMarkup } from 'react-dom/server'; +import ReactDOM from 'react-dom'; import HeadersTable from './headers-table/index.jsx'; import DataTable from './data-table/index.jsx'; @@ -14,29 +12,20 @@ export default async function paint ($element, layout, component) { layout }); - const { - ConceptMatrixColElem, - ConceptMatrixColElemTable, - ConceptMatrixRowElem - } = state.properties; - - const { - data: { meta: { dimensionCount } }, - selection: { dimensionSelectionCounts }, - styling: { useSeparatorColumns } - } = state; - const jsx = (
@@ -44,159 +33,57 @@ export default async function paint ($element, layout, component) {
); - // TODO: switch to render when jquery interaction stuff in renderData is gone - const html = renderToStaticMarkup(jsx); - $element.html(html); - // ReactDOM.render(jsx, $element[0]); + ReactDOM.render(jsx, $element[0]); - RenderData(); - // TODO: move jquery interactions into their respective components - // Hook up interactions and some html mangling - function RenderData () { - $('.data-table .row-wrapper').on('scroll', function () { - $(`[tid="${layout.qInfo.qId}"] .kpi-table .row-wrapper`).scrollTop($(this).scrollTop()); + // TODO: skipped the following as they weren't blockers for letting react handle rendering, + // they are however the only reason we still depend on jQuery and should be removed as part of unnecessary dependencies issue + $(`[tid="${layout.qInfo.qId}"] .data-table .row-wrapper`).on('scroll', function () { + $(`[tid="${layout.qInfo.qId}"] .kpi-table .row-wrapper`).scrollTop($(this).scrollTop()); + }); + + // freeze first column + $(`[tid="${layout.qInfo.qId}"] .qv-object-content-container`).on('scroll', (t) => { + $(`[tid="${layout.qInfo.qId}"] .kpi-table`).css('left', `${Math.round(t.target.scrollLeft)}px`); + }); + + // TODO: fixing tooltips has a seperate issue, make sure to remove this as part of that issue + $(`[tid="${layout.qInfo.qId}"] .header-wrapper th`).hover(function () { + $(`[tid="${layout.qInfo.qId}"] .tooltip`).delay(500) + .show(0); + $(`[tid="${layout.qInfo.qId}"] .header-wrapper th`).children(`[tid="${layout.qInfo.qId}"] .tooltip`) + .remove(); + + const element = $(this); + const offset = element.offset(); + const toolTip = $('
'); + + toolTip.css({ + left: offset.left, + top: offset.top }); - // on hover popup with cell value, only in headers - $('.header-wrapper th').hover(function () { - $('.tooltip').delay(500) - .show(0); - $('.header-wrapper th').children('.tooltip') - .remove(); + toolTip.text(element.text()); + $(`[tid="${layout.qInfo.qId}"] .header-wrapper th`).append(toolTip); + }, () => { + $(`[tid="${layout.qInfo.qId}"] .tooltip`).delay(0) + .hide(0); + }); - const element = $(this); - const offset = element.offset(); - const toolTip = $("
"); - - toolTip.css({ - top: offset.top, - left: offset.left - }); - - toolTip.text(element.text()); - $('.header-wrapper th').append(toolTip); - }, () => { - $('.tooltip').delay(0) - .hide(0); - }); - - // allow making selections inside the table - $('.data-table td').on('click', function () { - if (layout.filteroncellclick == false) { - return; - } - const indextr = $(this).parent() - .parent() - .children() - .index($(this).parent()); // identifica la row - const indextd = $(this).parent() - .children() - .index($(this)); // identifica la col - - let SelectRow = 0; - let SelectCol = 0; - - SelectRow = ConceptMatrixRowElem[(indextr)]; - - // este if verifica primero si hay selecciones hechas en la dimensión, si las hay - // las reselecciona para poder borrar antes de poder seleccionar lo que quiero - // no es viable pedirle que seleccione a la vez elementos de 2 selecciones, se queda - // colgado el menú de confirm, por eso uso este sistema, que sí funciona. - // it can cause issues like error messages and wrong selections if there are null values - // and the check allow null values is active - if (dimensionCount > 1 && indextd > 0) { - if (dimensionSelectionCounts[1] > 0) { - const SelectB = JSON.parse(JSON.stringify(ConceptMatrixColElemTable)); - component.backendApi.selectValues(1, SelectB, true); - $(this).toggleClass('selected'); - } - SelectCol = ConceptMatrixColElemTable[(indextd)]; - - component.backendApi.selectValues(1, [SelectCol], true); - $(this).toggleClass('selected'); - } - - if (indextd > 0 && dimensionSelectionCounts[0] > 0) { - const SelectA = JSON.parse(JSON.stringify(ConceptMatrixRowElem)); - component.backendApi.selectValues(0, SelectA, true); - $(this).toggleClass('selected'); - } - - if (indextd > 0) { - component.backendApi.selectValues(0, [SelectRow], true); - $(this).toggleClass('selected'); - } - }); - // allow selections through the header of the second dimension - $('.header-wrapper th').on('click', function () { - const indextd = $(this).parent() - .children() - .index($(this)); // identifica la col - - let SelectCol = 0; - - if (dimensionCount > 1 && indextd > 0) { - if (dimensionSelectionCounts[1] > 0) { - const SelectB = JSON.parse(JSON.stringify(ConceptMatrixColElem)); - component.backendApi.selectValues(1, SelectB, true); - $(this).toggleClass('selected'); - } - if (useSeparatorColumns) { - SelectCol = ConceptMatrixColElem[(Math.round(indextd / 2) - 1)]; - } else { - SelectCol = ConceptMatrixColElem[(Math.round(indextd) - 1)]; - } - - component.backendApi.selectValues(1, [SelectCol], true); - $(this).toggleClass('selected'); - } - }); - // allow selections in desc dimension cells - $('.kpi-table td').on('click', function () { - const indextr = $(this).parent() - .parent() - .children() - .index($(this).parent()); // identifica la row - let SelectRow = 0; - SelectRow = ConceptMatrixRowElem[(indextr)]; - - if (dimensionSelectionCounts[0] > 0) { - const SelectA = JSON.parse(JSON.stringify(ConceptMatrixRowElem)); - component.backendApi.selectValues(0, SelectA, true); - $(this).toggleClass('selected'); - } - - component.backendApi.selectValues(0, [SelectRow], true); - $(this).toggleClass('selected'); - }); - - enableExcelExport(layout, html); - - // freeze first column - $('.qv-object-content-container').on('scroll', (t) => { - $('.kpi-table').css('left', `${Math.round(t.target.scrollLeft)}px`); - }); - $('.kpi-table .row-wrapper tr').each(function () { - $(this).find('th:not(.fdim-cells)') - .remove(); - $(this).find('td:not(.fdim-cells)') - .remove(); - }); - $('.kpi-table .header-wrapper tr').each(function () { - $(this).find('th:not(.fdim-cells)') - .remove(); - }); - } + // TODO: excel export is broken in most browsers, fixing it has an issue of it's own (leaving it disabled for now) + // import { enableExcelExport } from './excel-export'; + // enableExcelExport(layout, html); } diff --git a/src/store.js b/src/store.js index 7f4b3f3..6987015 100644 --- a/src/store.js +++ b/src/store.js @@ -1,4 +1,3 @@ -import { onlyUnique } from './utilities'; import initializeTransformed from './initialize-transformed'; async function initialize ({ $element, layout, component }) { @@ -8,137 +7,7 @@ async function initialize ({ $element, layout, component }) { layout }); - // TODO: remove everything from here to return statement once jquery parts in paint has been refactored - const vMaxLoops = layout.maxloops; - const vErrorMessage = layout.errormessage; - let vDimName = ''; - const ConceptMatrixFirst = new Array(); - const ConceptMatrixSecond = new Array(); - const LabelsArray = new Array(); - const ArrayGetSelectedCount = new Array(); - let vNumDims = 0; - let vNumMeasures = 0; - const MeasuresFormat = new Array(); - const dim_count = layout.qHyperCube.qDimensionInfo.length; - const measure_count = layout.qHyperCube.qMeasureInfo.length; - let vSeparatorCols = layout.separatorcols; - if (dim_count == 1) { - vSeparatorCols = false; - } - let lastrow = 0; - const ConceptMatrix = new Array(); - let ConceptMatrixRowElem = new Array(); - let ConceptMatrixColElem = new Array(); - const ConceptMatrixColElemTable = new Array(); - const ConceptMatrixPivot = new Array(); - let ConceptMatrixFirstClean = new Array(); - const nRows = component.backendApi.getRowCount(); - - const dimensionInfos = component.backendApi.getDimensionInfos(); - LabelsArray.push(dimensionInfos[0].qFallbackTitle); - ArrayGetSelectedCount.concat(dimensionInfos.map(dimensionInfo => dimensionInfo.qStateCounts.qSelected)); - vNumDims += dimensionInfos.length; - - const measureInfos = component.backendApi.getMeasureInfos(); - measureInfos.forEach(measureInfo => { - vDimName = measureInfo.qFallbackTitle; - LabelsArray.push(vDimName); - let mfor = ''; - - if (measureInfo.qNumFormat.qType == 'U' || measureInfo.qNumFormat.qFmt == '##############') { - mfor = '#.##0'; // in case of undefined - } else if (measureInfo.qNumFormat.qType == 'R') { - mfor = measureInfo.qNumFormat.qFmt; - mfor = mfor.replace(/(|)/gi, ''); - } else { - mfor = measureInfo.qNumFormat.qFmt; - } - - MeasuresFormat.push(mfor); - - vNumMeasures++; - }); - - component.backendApi.eachDataRow((t, a) => { - lastrow = t; - - const vNumMeasuresPlus = vNumMeasures + 1; - - ConceptMatrix[t] = new Array(); - ConceptMatrix[t][0] = a[0].qText; - - ConceptMatrixFirst[t] = a[0].qText; - ConceptMatrixRowElem[t] = a[0].qElemNumber; - let nMeasures = 0; - if (vNumDims == 1) { - for (nMeasures = 1; nMeasures <= vNumMeasures; nMeasures++) { - ConceptMatrix[t][nMeasures] = a[nMeasures].qNum; - } - } else { - ConceptMatrix[t][1] = a[1].qText; - ConceptMatrixColElem[t] = a[1].qElemNumber; - ConceptMatrixSecond[t] = a[1].qText; - // set the hipercube in a plain array without pivoting - for (nMeasures = 2; nMeasures <= vNumMeasuresPlus; nMeasures++) { - ConceptMatrix[t][nMeasures] = a[nMeasures].qNum; - } - } - }); - - ConceptMatrixFirstClean = ConceptMatrixFirst.filter(onlyUnique); - - if (nRows >= (vMaxLoops * 1000)) { - alert(vErrorMessage); - } - - if (vNumDims == 2) { - // new array with unique values for 2nd dim - var SecondHeader = ConceptMatrixSecond.filter(onlyUnique);// second dimension concepts - ConceptMatrixRowElem = ConceptMatrixRowElem.filter(onlyUnique);// first dimension concepts - ConceptMatrixColElem = ConceptMatrixColElem.filter(onlyUnique);// dimension code for further selections - const eo = ConceptMatrixColElem.length; - let vLoopColsMeasures = 1; - ConceptMatrixColElemTable[0] = ConceptMatrixColElem[0]; - for (let xx = 0; xx < eo; xx++) { - if (vSeparatorCols && xx > 0) { - ConceptMatrixColElemTable[vLoopColsMeasures] = ConceptMatrixColElem[xx]; - vLoopColsMeasures++; - } - - for (let xxx = 0; xxx < vNumMeasures; xxx++) { - ConceptMatrixColElemTable[vLoopColsMeasures] = ConceptMatrixColElem[xx]; - vLoopColsMeasures++; - } - } - - let ConceptPos = 0; - let nMeas3 = 0; - let vHeaderIndex = 0; - let MeasurePos = 0; - for (let nPivotElems = 0; nPivotElems <= lastrow; nPivotElems++) { - ConceptMatrixPivot[nPivotElems] = new Array(); - ConceptPos = ConceptMatrixFirstClean.indexOf(ConceptMatrix[nPivotElems][0]); - ConceptMatrixPivot[ConceptPos][0] = ConceptMatrix[nPivotElems][0]; - - for (let nMeas2 = 1; nMeas2 <= measure_count; nMeas2++) { - nMeas3 = nMeas2 + 1; - vHeaderIndex = (SecondHeader.indexOf(ConceptMatrix[nPivotElems][1]) + 1); - MeasurePos = (vHeaderIndex * measure_count) + (nMeas2 - measure_count); - ConceptMatrixPivot[ConceptPos][MeasurePos] = ConceptMatrix[nPivotElems][nMeas3]; - } - } - } - - const properties = { - ConceptMatrixColElem, - ConceptMatrixColElemTable, - ConceptMatrixRowElem - }; - - return { - properties, - ...transformedProperties - }; + return transformedProperties; } export default initialize; From 3c330465dd332e0d4471559ecc5fe51608788cdb Mon Sep 17 00:00:00 2001 From: ahmed-Bazzara Date: Tue, 12 Feb 2019 12:03:05 +0100 Subject: [PATCH 02/15] Definition object is Qlik standard --- src/definition/index.js | 19 ++++++++++--------- src/index.js | 12 ++++++++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/definition/index.js b/src/definition/index.js index fd6a2a9..9352f61 100644 --- a/src/definition/index.js +++ b/src/definition/index.js @@ -9,15 +9,16 @@ import pijamaColorLibrary from './pijama-color-library'; const definition = { component: 'accordion', items: { - dimensions: { - max: 2, - min: 1, - uses: 'dimensions' - }, - measures: { - max: 9, - min: 1, - uses: 'measures' + data: { + items: { + dimensions: { + disabledRef: '' + }, + measures: { + disabledRef: '' + } + }, + uses: 'data' }, settings: { items: { diff --git a/src/index.js b/src/index.js index 0ead03a..e173730 100644 --- a/src/index.js +++ b/src/index.js @@ -12,6 +12,18 @@ export default { '$timeout', function () { } ], + data: { + dimensions: { + max: 2, + min: 1, + uses: 'dimensions' + }, + measures: { + max: 9, + min: 1, + uses: 'measures' + } + }, definition, initialProperties: { qHyperCubeDef: { From c47b401a1db770dc344a2278ba6ff486cd583bc2 Mon Sep 17 00:00:00 2001 From: ahmed-Bazzara Date: Tue, 12 Feb 2019 12:05:01 +0100 Subject: [PATCH 03/15] typo in definiton object --- src/definition/header.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/definition/header.js b/src/definition/header.js index ebf830a..fd61a63 100644 --- a/src/definition/header.js +++ b/src/definition/header.js @@ -27,7 +27,7 @@ const header = { ref: 'HeaderColorSchema', type: 'string', component: 'dropdown', - label: 'BackGround Header Color', + label: 'Background Header Color', options: [ { value: 'Clean', From d723451656c472901cff734988ac55a99919b007 Mon Sep 17 00:00:00 2001 From: Kristoffer Lind Date: Wed, 13 Feb 2019 13:52:20 +0100 Subject: [PATCH 04/15] revert accidental design change --- src/data-table/data-cell.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data-table/data-cell.jsx b/src/data-table/data-cell.jsx index 2407195..adde657 100644 --- a/src/data-table/data-cell.jsx +++ b/src/data-table/data-cell.jsx @@ -94,7 +94,7 @@ class DataCell extends React.PureComponent { let cellStyle = { fontFamily: styling.options.fontFamily, ...styleBuilder.getStyle(), - paddingRight: '4px', + paddingLeft: '4px', textAlign: 'right' }; From 8b843e028a41068200245ef7c8d859c3159223f1 Mon Sep 17 00:00:00 2001 From: Kristoffer Lind Date: Thu, 14 Feb 2019 11:08:34 +0100 Subject: [PATCH 05/15] fix excel export --- src/excel-export.js | 144 +++++++++++---------- src/export-button.jsx | 19 ++- src/headers-table/export-column-header.jsx | 8 +- src/headers-table/index.jsx | 1 + src/initialize-transformed.js | 5 +- src/paint.jsx | 3 - 6 files changed, 101 insertions(+), 79 deletions(-) diff --git a/src/excel-export.js b/src/excel-export.js index 9734e8c..ff67e12 100644 --- a/src/excel-export.js +++ b/src/excel-export.js @@ -1,73 +1,75 @@ -import $ from 'jquery'; +function buildTableHTML (title, subtitle, footnote) { + const titleHTML = `

${title}

`; + const subtitleHTML = `

${subtitle}

`; + const footnoteHTML = `

Note:${footnote}

`; + const dataTableClone = document.querySelector('.data-table').cloneNode(true); + const tableHTML = ` + + + + + + + ${titleHTML.length > 0 ? titleHTML : ''} + ${subtitleHTML.length > 0 ? subtitleHTML : ''} + ${footnoteHTML.length > 0 ? footnoteHTML : ''} + ${dataTableClone.outerHTML} + + + `.split('>.<') + .join('><') + .split('>*<') + .join('><'); -const isIE = /* @cc_on!@*/false || Boolean(document.documentMode); -const isChrome = Boolean(window.chrome) && Boolean(window.chrome.webstore); -const isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; -const isFirefox = typeof InstallTrigger !== 'undefined'; - -export function enableExcelExport (layout, f) { - let myTitle = ''; - let mySubTitle = ''; - let myFootNote = ''; - if (layout.title.length > 0) { - myTitle += '

'; - myTitle += layout.title; - myTitle += '

'; - } - if (layout.subtitle.length > 0) { - mySubTitle += '

'; - mySubTitle += layout.subtitle; - mySubTitle += '

'; - } - if (layout.footnote.length > 0) { - myFootNote += '

Note:'; - myFootNote += layout.footnote; - myFootNote += '

'; - } - - $('.icon-xls').on('click', () => { - $('.header-wrapper th').children('.tooltip') - .remove(); // remove some popup effects when exporting - $('.header-wrapper th').children('.icon-xls') - .remove(); // remove the xls icon when exporting - if (isChrome || isSafari) { - const $clonedDiv = $('.data-table').clone(true); // .kpi-table a secas exporta la 1ªcol - let vEncodeHead = ''; - vEncodeHead += myTitle + mySubTitle + myFootNote; - const vEncode = encodeURIComponent($clonedDiv.html()); - let vDecode = `${vEncodeHead + vEncode}`; - - $clonedDiv.find('tr.header'); - vDecode = vDecode.split('%3E.%3C').join('%3E%3C'); - window.open(`data:application/vnd.ms-excel,${vDecode}`); - $.preventDefault(); - } - if (isIE) { - let a = ''; - a += myTitle + mySubTitle + myFootNote; - a += f; - a = a.split('>.<').join('><'); - a += ''; - - const w = window.open(); - w.document.open(); - w.document.write(a); - w.document.close(); - w.document.execCommand('SaveAs', true, 'Analysis.xls' || 'c:\TMP'); - w.close(); - } - - if (isFirefox) { - const $clonedDiv = $('.data-table').clone(true);// .kpi-table a secas exporta la 1ªcol - let vEncodeHead = ''; - vEncodeHead += myTitle + mySubTitle + myFootNote; - const vEncode = encodeURIComponent($clonedDiv.html()); - let vDecode = `${vEncodeHead + vEncode}`; - - $clonedDiv.find('tr.header'); - vDecode = vDecode.split('>.<').join('><'); - window.open(`data:application/vnd.ms-excel,${vDecode}`); - $.preventDefault(); - } - }); + return tableHTML; +} + +function downloadXLS (html) { + const filename = 'analysis.xls'; + // IE/Edge + if (window.navigator.msSaveOrOpenBlob) { + const blobObject = new Blob([html]); + return window.navigator.msSaveOrOpenBlob(blobObject, filename); + } + + const dataURI = generateDataURI(html); + const link = window.document.createElement('a'); + link.href = dataURI; + link.download = filename; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + + return true; +} + +function generateDataURI (html) { + const dataType = 'data:application/vnd.ms-excel;base64,'; + const data = window.btoa(unescape(encodeURIComponent(html))); + + return `${dataType}${data}`; +} + +export function exportXLS (title, subtitle, footnote) { + // close all tooltips (awaiting tooltips rewrite, should add a close all action for it) + // original was removing icon when starting export, disable and some spinner instead, shouldn't take enough time to warrant either..? + const table = buildTableHTML(title, subtitle, footnote); + downloadXLS(table); } diff --git a/src/export-button.jsx b/src/export-button.jsx index 60ea0d2..76436ed 100644 --- a/src/export-button.jsx +++ b/src/export-button.jsx @@ -1,13 +1,27 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { exportXLS } from './excel-export'; -// TODO: move interaction logic in here from excel-export.js class ExportButton extends React.PureComponent { + constructor (props) { + super(props); + this.handleExport = this.handleExport.bind(this); + } + + handleExport () { + const { excelExport, general } = this.props; + const { title, subtitle, footnote } = general; + if (excelExport) { + exportXLS(title, subtitle, footnote); + } + } + render () { const { excelExport } = this.props; return excelExport === true && ( @@ -20,7 +34,8 @@ ExportButton.defaultProps = { }; ExportButton.propTypes = { - excelExport: PropTypes.bool + excelExport: PropTypes.bool, + general: PropTypes.shape({}).isRequired }; export default ExportButton; diff --git a/src/headers-table/export-column-header.jsx b/src/headers-table/export-column-header.jsx index 640e89e..96fe045 100644 --- a/src/headers-table/export-column-header.jsx +++ b/src/headers-table/export-column-header.jsx @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import ExportButton from '../export-button.jsx'; -const ExportColumnHeader = ({ baseCSS, title, allowExcelExport, hasSecondDimension, styling }) => { +const ExportColumnHeader = ({ baseCSS, general, title, allowExcelExport, hasSecondDimension, styling }) => { const rowSpan = hasSecondDimension ? 2 : 1; const style = { ...baseCSS, @@ -19,7 +19,10 @@ const ExportColumnHeader = ({ baseCSS, title, allowExcelExport, hasSecondDimensi rowSpan={rowSpan} style={style} > - + {title} ); @@ -28,6 +31,7 @@ const ExportColumnHeader = ({ baseCSS, title, allowExcelExport, hasSecondDimensi ExportColumnHeader.propTypes = { allowExcelExport: PropTypes.bool.isRequired, baseCSS: PropTypes.shape({}).isRequired, + general: PropTypes.shape({}).isRequired, hasSecondDimension: PropTypes.bool.isRequired, styling: PropTypes.shape({ headerOptions: PropTypes.shape({ diff --git a/src/headers-table/index.jsx b/src/headers-table/index.jsx index c45fa48..06db659 100644 --- a/src/headers-table/index.jsx +++ b/src/headers-table/index.jsx @@ -29,6 +29,7 @@ const HeadersTable = ({ data, general, styling }) => { dimensionInfo.qStateCounts.qSelected) diff --git a/src/paint.jsx b/src/paint.jsx index 2ed949d..9b5b691 100644 --- a/src/paint.jsx +++ b/src/paint.jsx @@ -1,5 +1,4 @@ import $ from 'jquery'; -import { enableExcelExport } from './excel-export'; import initializeStore from './store'; import React from 'react'; // import ReactDOM from 'react-dom'; @@ -182,8 +181,6 @@ export default async function paint ($element, layout, component) { $(this).toggleClass('selected'); }); - enableExcelExport(layout, html); - // freeze first column $('.qv-object-content-container').on('scroll', (t) => { $('.kpi-table').css('left', `${Math.round(t.target.scrollLeft)}px`); From db67b864ee84e9d91ff2d14f55ff7b244716d4a5 Mon Sep 17 00:00:00 2001 From: ahmed-Bazzara Date: Thu, 14 Feb 2019 13:54:17 +0100 Subject: [PATCH 06/15] edit mode interaction prevented --- src/main.less | 4 +++- src/paint.jsx | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main.less b/src/main.less index 9f96728..e836cbb 100644 --- a/src/main.less +++ b/src/main.less @@ -1,7 +1,9 @@ .qv-object-qlik-smart-pivot { @TableBorder: 1px solid #d3d3d3; @KpiTableWidth: 230px; - + .edit-mode{ + pointer-events: none; + } ._cell(@Width: 50px) { min-width: @Width!important; max-width: @Width!important; diff --git a/src/paint.jsx b/src/paint.jsx index f16a912..e750dfb 100644 --- a/src/paint.jsx +++ b/src/paint.jsx @@ -11,10 +11,10 @@ export default async function paint ($element, layout, component) { component, layout }); - + const editmodeClass = component.inAnalysisState() ? '' : 'edit-mode'; const jsx = ( -
+
-
+
Date: Thu, 14 Feb 2019 15:14:23 +0100 Subject: [PATCH 07/15] cleanup tooltips (resulted in whatever header was last hovered to be appended to each column header in xls) --- src/excel-export.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/excel-export.js b/src/excel-export.js index ff67e12..413f391 100644 --- a/src/excel-export.js +++ b/src/excel-export.js @@ -1,8 +1,20 @@ +function removeAllTooltips (node) { + const tooltips = node.querySelectorAll('.tooltip'); + [].forEach.call(tooltips, tooltip => { + if (tooltip.parentNode) { + tooltip.parentNode.removeChild(tooltip); + } + }); +} + function buildTableHTML (title, subtitle, footnote) { const titleHTML = `

${title}

`; const subtitleHTML = `

${subtitle}

`; const footnoteHTML = `

Note:${footnote}

`; const dataTableClone = document.querySelector('.data-table').cloneNode(true); + + removeAllTooltips(dataTableClone); + const tableHTML = ` Date: Sat, 16 Feb 2019 10:48:49 +0100 Subject: [PATCH 08/15] Update config.yml --- .circleci/config.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 040ea5c..c7735ea 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -18,6 +18,14 @@ jobs: - run: name: Install dependencies command: npm install + - run: + name: BlackDuck scan + command: curl -s https://blackducksoftware.github.io/hub-detect/hub-detect.sh | bash -s -- \ + --blackduck.url="https://qliktech.blackducksoftware.com" \ + --blackduck.trust.cert=true \ + --blackduck.username="svc-blackduck" \ + --blackduck.password=${svc_blackduck} \ + --detect.project.name="viz-bundle-qlik-smart-pivot" - run: name: Run tests command: npm run test-once From b65d1c51fcd5d0ee6219886d817ce7739caf14f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20=C3=85str=C3=B6m?= Date: Sat, 16 Feb 2019 10:49:46 +0100 Subject: [PATCH 09/15] Update qlik-smart-pivot.qext --- assets/qlik-smart-pivot.qext | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/qlik-smart-pivot.qext b/assets/qlik-smart-pivot.qext index c980707..4c1f96f 100644 --- a/assets/qlik-smart-pivot.qext +++ b/assets/qlik-smart-pivot.qext @@ -1,6 +1,6 @@ { - "name": "Smart pivot", - "description": "Formatted table for P&L reports.", + "name": "P&L pivot", + "description": "Profit & Loss reporting with color and font customizations.", "type": "visualization", "version": "X.Y.Z", "icon": "table", From 34477d7ef1d6494868794f1835b5c832be722fe1 Mon Sep 17 00:00:00 2001 From: ahmed-Bazzara Date: Mon, 18 Feb 2019 16:12:40 +0100 Subject: [PATCH 10/15] qlik font added to the fonts dropdown and was made a default value --- src/definition/formatted.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/definition/formatted.js b/src/definition/formatted.js index 3e1cce6..851b491 100644 --- a/src/definition/formatted.js +++ b/src/definition/formatted.js @@ -139,6 +139,10 @@ const formatted = { component: 'dropdown', label: 'FontFamily', options: [ + { + value: 'QlikView Sans', + label: 'QlikView Sans' + }, { value: 'Arial', label: 'Arial' @@ -164,7 +168,7 @@ const formatted = { label: 'Verdana' } ], - defaultValue: 'Calibri' + defaultValue: 'QlikView Sans' }, DataFontSize: { ref: 'lettersize', From ec140efc563a5548b35bf75854345da612b93672 Mon Sep 17 00:00:00 2001 From: ahmed-Bazzara Date: Mon, 18 Feb 2019 16:42:39 +0100 Subject: [PATCH 11/15] Text alignment property added --- src/data-table/data-cell.jsx | 14 ++++++++++++-- src/definition/formatted.js | 20 ++++++++++++++++++++ src/initialize-transformed.js | 3 ++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/data-table/data-cell.jsx b/src/data-table/data-cell.jsx index adde657..deb216b 100644 --- a/src/data-table/data-cell.jsx +++ b/src/data-table/data-cell.jsx @@ -90,12 +90,22 @@ class DataCell extends React.PureComponent { if (styleBuilder.hasComments()) { formattedMeasurementValue = '.'; } + let textAlignment = 'Right'; + const textAlignmentProp = styling.options.textAlignment; + + if (textAlignmentProp === 1) { + textAlignment = 'Left'; + } else if (textAlignmentProp === 2) { + textAlignment = 'Center'; + } else { + textAlignment = 'Right'; + } let cellStyle = { fontFamily: styling.options.fontFamily, ...styleBuilder.getStyle(), paddingLeft: '4px', - textAlign: 'right' + textAlign: textAlignment }; const { semaphoreColors } = styling; @@ -109,7 +119,7 @@ class DataCell extends React.PureComponent { fontFamily: styling.options.fontFamily, fontSize: styleBuilder.getStyle().fontSize, paddingLeft: '4px', - textAlign: 'right' + textAlign: textAlignment }; } diff --git a/src/definition/formatted.js b/src/definition/formatted.js index 3e1cce6..ed9d110 100644 --- a/src/definition/formatted.js +++ b/src/definition/formatted.js @@ -183,6 +183,26 @@ const formatted = { ], defaultValue: 2 }, + textAlignment: { + ref: 'cellTextAlignment', + label: 'Cell Text alignment', + component: 'buttongroup', + options: [ + { + value: 1, + label: 'Left' + }, + { + value: 2, + label: 'Center' + }, + { + value: 3, + label: 'Right' + } + ], + defaultValue: 3 + }, ColumnWidthSlider: { type: 'number', component: 'slider', diff --git a/src/initialize-transformed.js b/src/initialize-transformed.js index f5e9585..42e38cc 100644 --- a/src/initialize-transformed.js +++ b/src/initialize-transformed.js @@ -279,7 +279,8 @@ async function initializeTransformed ({ $element, layout, component }) { backgroundColorOdd: colors[`vColLib${layout.ColorSchemaP}`], color: layout.BodyTextColorSchema, fontFamily: layout.FontFamily, - fontSizeAdjustment: getFontSizeAdjustment(layout.lettersize) + fontSizeAdjustment: getFontSizeAdjustment(layout.lettersize), + textAlignment: layout.cellTextAlignment }, semaphoreColors: { fieldsToApplyTo: { From bcb9d30237ed2ab95df6c26dcf00324e4f7a72c8 Mon Sep 17 00:00:00 2001 From: ahmed-Bazzara Date: Tue, 19 Feb 2019 14:55:50 +0100 Subject: [PATCH 12/15] sending the alignment value straight from props instead of numbers --- src/data-table/data-cell.jsx | 9 ++------- src/definition/formatted.js | 8 ++++---- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/data-table/data-cell.jsx b/src/data-table/data-cell.jsx index deb216b..d176fc8 100644 --- a/src/data-table/data-cell.jsx +++ b/src/data-table/data-cell.jsx @@ -92,13 +92,8 @@ class DataCell extends React.PureComponent { } let textAlignment = 'Right'; const textAlignmentProp = styling.options.textAlignment; - - if (textAlignmentProp === 1) { - textAlignment = 'Left'; - } else if (textAlignmentProp === 2) { - textAlignment = 'Center'; - } else { - textAlignment = 'Right'; + if (textAlignmentProp) { + textAlignment = textAlignmentProp; } let cellStyle = { diff --git a/src/definition/formatted.js b/src/definition/formatted.js index ed9d110..2a41478 100644 --- a/src/definition/formatted.js +++ b/src/definition/formatted.js @@ -189,19 +189,19 @@ const formatted = { component: 'buttongroup', options: [ { - value: 1, + value: 'Left', label: 'Left' }, { - value: 2, + value: 'Center', label: 'Center' }, { - value: 3, + value: 'Right', label: 'Right' } ], - defaultValue: 3 + defaultValue: 'Right' }, ColumnWidthSlider: { type: 'number', From e70e76a401f6d008b35eb419788a442c446eb2ba Mon Sep 17 00:00:00 2001 From: ahmed-Bazzara Date: Wed, 20 Feb 2019 15:44:36 +0100 Subject: [PATCH 13/15] small font size is set to be default and its value matched to Qlik defalut font size --- src/definition/formatted.js | 2 +- src/initialize-transformed.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/definition/formatted.js b/src/definition/formatted.js index 851b491..92647c4 100644 --- a/src/definition/formatted.js +++ b/src/definition/formatted.js @@ -185,7 +185,7 @@ const formatted = { label: 'Medium' } ], - defaultValue: 2 + defaultValue: 1 }, ColumnWidthSlider: { type: 'number', diff --git a/src/initialize-transformed.js b/src/initialize-transformed.js index f5e9585..6c31343 100644 --- a/src/initialize-transformed.js +++ b/src/initialize-transformed.js @@ -39,8 +39,8 @@ function getAlignment (option) { function getFontSizeAdjustment (option) { const fontSizeAdjustmentOptions = { - 1: -2, - 2: 0, + 1: -1, + 2: 1, 3: 2 }; From 35d4dde1181a4b330224a5001eb9dbf8a4b803d6 Mon Sep 17 00:00:00 2001 From: ahmed-Bazzara Date: Wed, 20 Feb 2019 15:50:54 +0100 Subject: [PATCH 14/15] exporting image and PDF enabled --- src/index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/index.js b/src/index.js index 0ead03a..107b2f5 100644 --- a/src/index.js +++ b/src/index.js @@ -25,6 +25,11 @@ export default { qMeasures: [] } }, + support: { + export: true, + exportData: true, + snapshot: true + }, paint ($element, layout) { try { paint($element, layout, this); From 24edf1c6f4de5b834dcb3a9feb22454f465b6691 Mon Sep 17 00:00:00 2001 From: ahmed-Bazzara Date: Thu, 21 Feb 2019 12:02:42 +0100 Subject: [PATCH 15/15] values of text alignement property set to have lowercase --- src/definition/formatted.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/definition/formatted.js b/src/definition/formatted.js index 2a41478..5c9f266 100644 --- a/src/definition/formatted.js +++ b/src/definition/formatted.js @@ -189,19 +189,19 @@ const formatted = { component: 'buttongroup', options: [ { - value: 'Left', + value: 'left', label: 'Left' }, { - value: 'Center', + value: 'center', label: 'Center' }, { - value: 'Right', + value: 'right', label: 'Right' } ], - defaultValue: 'Right' + defaultValue: 'right' }, ColumnWidthSlider: { type: 'number',