Compare commits
10 Commits
QLIK-95962
...
pol/bd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a65f843008 | ||
|
|
be9570e0aa | ||
|
|
41d3a7c9af | ||
|
|
1e0a7c1204 | ||
|
|
17b5df296c | ||
|
|
64b778b1af | ||
|
|
be6718ccf4 | ||
|
|
28e6237a43 | ||
|
|
4fab3b5933 | ||
|
|
79339a8963 |
@@ -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" \
|
||||
|
||||
BIN
assets/Excel.png
BIN
assets/Excel.png
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB |
@@ -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,
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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'
|
||||
},
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
@@ -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({}),
|
||||
|
||||
32
src/index.js
32
src/index.js
@@ -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,
|
||||
@@ -49,7 +46,9 @@ export default {
|
||||
qWidth: 10
|
||||
}
|
||||
],
|
||||
qMeasures: []
|
||||
qMeasures: [],
|
||||
qSuppressMissing: true,
|
||||
qSuppressZero: false
|
||||
}
|
||||
},
|
||||
support: {
|
||||
@@ -86,5 +85,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
|
||||
};
|
||||
|
||||
@@ -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: {
|
||||
|
||||
Reference in New Issue
Block a user