Compare commits

...

11 Commits

Author SHA1 Message Date
Purwa Shrivastava
e64af66dab Conversion led to different sort orders of data in different objects so disabling it. 2019-11-27 14:54:42 +01:00
Philip Olsén
ca1b1a9b53 Merge pull request #75 from qlik-oss/pol/bd
Update black duck link
2019-09-20 15:33:56 +02:00
Philip Olsén
a65f843008 Update black duck link 2019-09-20 14:23:37 +02:00
Purwa Shrivastava
be9570e0aa Merge pull request #74 from qlik-oss/atq/about
Updated the About info for the smart pivot.
2019-07-12 12:40:29 +02:00
Purwa Shrivastava
41d3a7c9af Updated the About info for the smart pivot. 2019-07-11 11:01:42 +02:00
Albert Backenhof
1e0a7c1204 Merge pull request #72 from qlik-oss/DEB-211/ContextMenuExportExcel
Moved Excel export to context menu
2019-06-27 12:35:04 +02:00
Albert Backenhof
17b5df296c Moved Excel export to context menu
-Not showing context menu option for desktop
 users.

Issue: DEB-211
2019-06-26 13:41:07 +02:00
Albert Backenhof
64b778b1af Merge pull request #71 from qlik-oss/DEB-244/ExcelRow
Suppress missing values and use correct cube size
2019-06-17 13:37:05 +02:00
Albert Backenhof
be6718ccf4 Merge pull request #73 from qlik-oss/DEB-250/ImprovedSelection
Selecting with backendApi instead of Field
2019-06-17 09:30:27 +02:00
Albert Backenhof
28e6237a43 Selecting with backendApi instead of Field
-Makes it possible to select master fields with
 different names than the original field.

-Alternate state is no longer a problem when using
 this technique to select.

Issue: DEB-250
2019-06-14 08:30:57 +02:00
Albert Backenhof
4fab3b5933 Suppress missing values and use correct cube size
Issue: DEB-244
2019-05-29 15:17:17 +02:00
13 changed files with 94 additions and 112 deletions

View File

@@ -20,7 +20,7 @@ jobs:
command: npm install
- run:
name: BlackDuck scan
command: curl -s https://blackducksoftware.github.io/hub-detect/hub-detect.sh | bash -s -- \
command: curl -s https://detect.synopsys.com/detect.sh | bash -s -- \
--blackduck.url="https://qliktech.blackducksoftware.com" \
--blackduck.trust.cert=true \
--blackduck.username="svc-blackduck" \

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -1,4 +1,3 @@
import qlik from 'qlik';
import React from 'react';
import PropTypes from 'prop-types';
import Tooltip from '../tooltip/index.jsx';
@@ -12,10 +11,8 @@ class DataCell extends React.PureComponent {
handleSelect () {
const {
data: {
headers,
meta: {
dimensionCount,
altState
dimensionCount
}
},
general: {
@@ -30,13 +27,9 @@ class DataCell extends React.PureComponent {
return;
}
const app = qlik.currApp(component);
app.field(headers.dimension1[0].name, altState)
.select([measurement.parents.dimension1.elementNumber], false, false);
component.backendApi.selectValues(0, [measurement.parents.dimension1.elementNumber], false);
if (hasSecondDimension) {
app.field(headers.dimension2[0].name, altState)
.select([measurement.parents.dimension2.elementNumber], false, false);
component.backendApi.selectValues(1, [measurement.parents.dimension2.elementNumber], false);
}
}
@@ -105,11 +98,9 @@ DataCell.propTypes = {
cellWidth: PropTypes.string.isRequired,
data: PropTypes.shape({
headers: PropTypes.shape({
dimension1: PropTypes.array.isRequired,
measurements: PropTypes.array.isRequired
}).isRequired,
meta: PropTypes.shape({
altState: PropTypes.string.isRequired,
dimensionCount: PropTypes.number.isRequired
}).isRequired
}).isRequired,
@@ -119,7 +110,16 @@ DataCell.propTypes = {
name: PropTypes.string,
value: PropTypes.any
}).isRequired,
component: PropTypes.shape({}).isRequired,
component: PropTypes.shape({
backendApi: PropTypes.shape({
selectValues: function (props, propName) {
if (props.isSnapshot || typeof props[propName] === 'function') {
return null;
}
return new Error('Missing implementation of qlik.backendApi.selectValues.');
}
}).isRequired
}).isRequired,
styleBuilder: PropTypes.shape({
hasComments: PropTypes.func.isRequired
}).isRequired,

View File

@@ -58,7 +58,6 @@ class DataTable extends React.PureComponent {
<tr key={dimensionEntry.displayValue}>
{!renderData ?
<RowHeader
altState={data.meta.altState}
component={component}
entry={dimensionEntry}
rowStyle={rowStyle}

View File

@@ -1,4 +1,3 @@
import qlik from 'qlik';
import React from 'react';
import PropTypes from 'prop-types';
import HeaderPadding from './header-padding.jsx';
@@ -12,9 +11,8 @@ class RowHeader extends React.PureComponent {
}
handleSelect () {
const { entry, altState, component } = this.props;
const app = qlik.currApp(component);
app.field(entry.name, altState).select([entry.elementNumber], false, false);
const { component, entry } = this.props;
component.backendApi.selectValues(0, [entry.elementNumber], false);
}
render () {
@@ -46,11 +44,18 @@ class RowHeader extends React.PureComponent {
RowHeader.propTypes = {
entry: PropTypes.shape({
displayValue: PropTypes.string.isRequired,
elementNumber: PropTypes.number.isRequired,
name: PropTypes.string.isRequired
elementNumber: PropTypes.number.isRequired
}).isRequired,
component: PropTypes.shape({
backendApi: PropTypes.shape({
selectValues: function (props, propName) {
if (props.isSnapshot || typeof props[propName] === 'function') {
return null;
}
return new Error('Missing implementation of qlik.backendApi.selectValues.');
}
}).isRequired
}).isRequired,
altState: PropTypes.string.isRequired,
component: PropTypes.shape({}).isRequired,
rowStyle: PropTypes.shape({}).isRequired,
styleBuilder: PropTypes.shape({}).isRequired,
styling: PropTypes.shape({}).isRequired

View File

@@ -6,19 +6,19 @@ function createCube (definition, app) {
});
}
async function buildDataCube (originCubeDefinition, hasTwoDimensions, app) {
async function buildDataCube (originCubeDefinition, originCube, app) {
const cubeDefinition = {
...originCubeDefinition,
qInitialDataFetch: [
{
qHeight: 1000,
qWidth: 10
qHeight: originCube.qSize.qcy,
qWidth: originCube.qSize.qcx
}
],
qDimensions: [originCubeDefinition.qDimensions[0]],
qMeasures: originCubeDefinition.qMeasures
};
if (hasTwoDimensions) {
if (originCube.qDimensionInfo.length === 2) {
cubeDefinition.qDimensions.push(originCubeDefinition.qDimensions[1]);
}
const cube = await createCube(cubeDefinition, app);
@@ -36,12 +36,13 @@ export async function initializeDataCube (component, layout) {
const properties = (await component.backendApi.getProperties());
// If this is a master object, fetch the hyperCubeDef of the original object
const hyperCubeDef = properties.qExtendsId
let hyperCubeDef = properties.qExtendsId
? (await app.getObjectProperties(properties.qExtendsId)).properties.qHyperCubeDef
: properties.qHyperCubeDef;
hyperCubeDef.qStateName = layout.qStateName || "";
hyperCubeDef = JSON.parse(JSON.stringify(hyperCubeDef));
hyperCubeDef.qStateName = layout.qStateName;
return buildDataCube(hyperCubeDef, layout.qHyperCube.qDimensionInfo.length === 2, app);
return buildDataCube(hyperCubeDef, layout.qHyperCube, app);
}
export function initializeDesignList (component, layout) {

View File

@@ -39,7 +39,7 @@ const definition = {
component: 'text'
},
paragraph1: {
label: `P&L pivot is a Qlik Sense extension which allows you to display Profit & Loss
label: `P&L pivot is a Qlik Sense chart which allows you to display Profit & Loss
reporting with color and font customizations.`,
component: 'text'
},

View File

@@ -1,42 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import { exportXLS } from './excel-export';
class ExportButton extends React.PureComponent {
constructor (props) {
super(props);
this.handleExport = this.handleExport.bind(this);
}
handleExport () {
const { component, excelExport, general } = this.props;
const { title, subtitle, footnote } = general;
if (excelExport) {
exportXLS(component.$element, title, subtitle, footnote);
}
}
render () {
const { excelExport } = this.props;
return excelExport === true && (
<input
className="icon-xls"
onClick={this.handleExport}
src="/Extensions/qlik-smart-pivot/Excel.png"
type="image"
/>
);
}
}
ExportButton.defaultProps = {
excelExport: false
};
ExportButton.propTypes = {
component: PropTypes.shape({}).isRequired,
excelExport: PropTypes.bool,
general: PropTypes.shape({}).isRequired
};
export default ExportButton;

View File

@@ -1,4 +1,3 @@
import qlik from 'qlik';
import React from 'react';
import PropTypes from 'prop-types';
import { HEADER_FONT_SIZE } from '../initialize-transformed';
@@ -11,9 +10,8 @@ class ColumnHeader extends React.PureComponent {
}
handleSelect () {
const { entry, altState, component } = this.props;
const app = qlik.currApp(component);
app.field(entry.name, altState).select([entry.elementNumber], false, false);
const { component, entry } = this.props;
component.backendApi.selectValues(1, [entry.elementNumber], false);
}
render () {
@@ -57,13 +55,20 @@ ColumnHeader.propTypes = {
baseCSS: PropTypes.shape({}).isRequired,
cellWidth: PropTypes.string.isRequired,
colSpan: PropTypes.number,
component: PropTypes.shape({
backendApi: PropTypes.shape({
selectValues: function (props, propName) {
if (props.isSnapshot || typeof props[propName] === 'function') {
return null;
}
return new Error('Missing implementation of qlik.backendApi.selectValues.');
}
}).isRequired
}).isRequired,
entry: PropTypes.shape({
displayValue: PropTypes.string.isRequired,
elementNumber: PropTypes.number.isRequired,
name: PropTypes.string.isRequired
elementNumber: PropTypes.number.isRequired
}).isRequired,
altState: PropTypes.string.isRequired,
component: PropTypes.shape({}).isRequired,
styling: PropTypes.shape({
headerOptions: PropTypes.shape({
fontSizeAdjustment: PropTypes.number.isRequired

View File

@@ -1,9 +1,10 @@
import React from 'react';
import PropTypes from 'prop-types';
import ExportButton from '../export-button.jsx';
import { HEADER_FONT_SIZE } from '../initialize-transformed';
import Tooltip from '../tooltip/index.jsx';
const ExportColumnHeader = ({ component, baseCSS, general, title, allowExcelExport, hasSecondDimension, styling }) => {
const Dim1Header = ({ component, baseCSS, title, hasSecondDimension, styling }) => {
const inEditState = component.inEditState();
const rowSpan = hasSecondDimension ? 2 : 1;
const isMediumFontSize = styling.headerOptions.fontSizeAdjustment === HEADER_FONT_SIZE.MEDIUM;
const style = {
@@ -21,21 +22,20 @@ const ExportColumnHeader = ({ component, baseCSS, general, title, allowExcelExpo
rowSpan={rowSpan}
style={style}
>
<ExportButton
component={component}
excelExport={allowExcelExport}
general={general}
/>
{title}
<Tooltip
isTooltipActive={!inEditState}
styling={styling}
tooltipText={title}
>
{title}
</Tooltip>
</th>
);
};
ExportColumnHeader.propTypes = {
component: PropTypes.shape({}).isRequired,
allowExcelExport: PropTypes.bool.isRequired,
Dim1Header.propTypes = {
baseCSS: PropTypes.shape({}).isRequired,
general: PropTypes.shape({}).isRequired,
component: PropTypes.shape({}).isRequired,
hasSecondDimension: PropTypes.bool.isRequired,
styling: PropTypes.shape({
headerOptions: PropTypes.shape({
@@ -45,4 +45,4 @@ ExportColumnHeader.propTypes = {
title: PropTypes.string.isRequired
};
export default ExportColumnHeader;
export default Dim1Header;

View File

@@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import ExportColumnHeader from './export-column-header.jsx';
import Dim1Header from './dim1-header.jsx';
import ColumnHeader from './column-header.jsx';
import MeasurementColumnHeader from './measurement-column-header.jsx';
import { injectSeparators } from '../utilities';
@@ -12,7 +12,6 @@ class HeadersTable extends React.PureComponent {
columnSeparatorWidth,
component,
data,
general,
isKpi,
styling
} = this.props;
@@ -43,11 +42,9 @@ class HeadersTable extends React.PureComponent {
<tbody>
<tr>
{isKpi ?
<ExportColumnHeader
allowExcelExport={general.allowExcelExport}
<Dim1Header
baseCSS={baseCSS}
component={component}
general={general}
hasSecondDimension={hasSecondDimension}
styling={styling}
title={dimension1[0].name}
@@ -75,7 +72,6 @@ class HeadersTable extends React.PureComponent {
}
return (
<ColumnHeader
altState={data.meta.altState}
baseCSS={baseCSS}
cellWidth={cellWidth}
colSpan={measurements.length}
@@ -128,12 +124,8 @@ HeadersTable.propTypes = {
dimension1: PropTypes.array,
dimension2: PropTypes.array,
measurements: PropTypes.array
}),
meta: PropTypes.shape({
altState: PropTypes.string.isRequired
})
}).isRequired,
general: PropTypes.shape({}).isRequired,
component: PropTypes.shape({}).isRequired,
styling: PropTypes.shape({
headerOptions: PropTypes.shape({}),

View File

@@ -1,6 +1,8 @@
import definition from './definition';
import { exportXLS } from './excel-export';
import { initializeDataCube, initializeDesignList } from './dataset';
import initializeStore from './store';
import qlik from 'qlik';
import React from 'react';
import ReactDOM from 'react-dom';
import Root from './root.jsx';
@@ -11,11 +13,6 @@ if (!window._babelPolyfill) { // eslint-disable-line no-underscore-dangle
}
export default {
controller: [
'$scope',
'$timeout',
function controller () {}
],
design: {
dimensions: {
max: 1,
@@ -38,6 +35,9 @@ export default {
uses: 'measures'
}
},
// Prevent conversion from and to this object
exportProperties: null,
importProperties: null,
definition,
initialProperties: {
version: 1.0,
@@ -49,7 +49,9 @@ export default {
qWidth: 10
}
],
qMeasures: []
qMeasures: [],
qSuppressMissing: true,
qSuppressZero: false
}
},
support: {
@@ -86,5 +88,26 @@ export default {
snapshotLayout.snapshotData.designList = await initializeDesignList(this, snapshotLayout);
return snapshotLayout;
},
getContextMenu: async function (obj, menu) {
const app = qlik.currApp(this);
const isPersonalResult = await app.global.isPersonalMode();
if (!this.$scope.layout.allowexportxls || (isPersonalResult && isPersonalResult.qReturn)) {
return menu;
}
menu.addItem({
translation: "Export as XLS",
tid: "export-excel",
icon: "export",
select: () => {
exportXLS(
this.$element,
this.$scope.layout.title,
this.$scope.layout.subtitle,
this.$scope.layout.footnote);
}
});
return menu;
},
version: 1.0
};

View File

@@ -250,8 +250,7 @@ function initializeTransformed ({ $element, component, dataCube, designList, lay
},
matrix, // 2d array of all rows/cells to render in body of datatable
meta: {
dimensionCount: dimensionsInformation.length,
altState: layout.qStateName || ""
dimensionCount: dimensionsInformation.length
}
},
general: {