Compare commits

..

15 Commits

Author SHA1 Message Date
Albert Backenhof
d4154fde09 Merge pull request #18 from qlik-oss/DEB-133
Aligned build to Dashboard bundle extension builds
2019-05-10 09:11:55 +02:00
Albert Backenhof
d65b619546 Aligned build to Dashboard bundle extension builds
-Part of the work to streamline how the extensions
are handled, irregardless of what bundle.

Issue: DEB-130, DEB-133
2019-03-27 13:05:38 +01:00
Tobias Åström
d15b246db4 Merge pull request #17 from qlik-oss/tsm/QLIK-94112-promise
Make sure promise resolves properly
2019-03-08 14:58:33 +01:00
Tobias Åström
fc8e9b0ba4 Make sure promise resolves properly 2019-03-08 11:17:35 +01:00
John Lunde
b443deca27 Merge pull request #16 from qlik-oss/feature/QPE-592
[QPE-592] only load babel if not already loaded
2019-02-14 13:01:43 +01:00
Kristoffer Lind
8a24c3ee92 only load babel if not already loaded 2019-02-13 15:02:12 +01:00
Tobias Åström
464d137095 Add blackduck 2019-02-04 16:51:08 +01:00
John Lunde
903a2caa1d Merge pull request #15 from qlik-oss/caele/QPE-524
Fix issue with coloring
2019-01-11 14:56:14 +01:00
Tobias Åström
d68b2ed863 Fix issue with coloring 2019-01-10 13:12:14 +01:00
Piotr Nestorow
f87bc3ea88 Merge pull request #14 from qlik-oss/caele-test
Simplification of Network chart data
2019-01-10 09:04:53 +01:00
Tobias Åström
b7753143fd Hide undefined edge labels 2018-12-19 08:46:49 +01:00
Tobias Åström
8f239687f3 Correct selections and add descriptions 2018-12-18 16:54:36 +01:00
Tobias Åström
d970d05711 Make the last dimension optional 2018-12-14 11:09:31 +01:00
Tobias Åström
192f4a8597 Update coloring 2018-12-12 16:47:35 +01:00
Tobias Åström
6eff5e1fd0 Change to allow strings instead of only numerics for IDs 2018-12-12 16:47:02 +01:00
14 changed files with 357 additions and 322 deletions

View File

@@ -19,8 +19,13 @@ jobs:
name: Install dependencies
command: npm install
- run:
name: Run tests
command: npm run test-once
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-network-chart"
bump-version:
<<: *defaults
@@ -48,16 +53,18 @@ jobs:
command: |
export VERSION=$(scripts/get-bumped-version.sh)
echo "Version: ${VERSION}"
npm run build
npm run build:zip
sudo chmod +x scripts/verify-files.sh
scripts/verify-files.sh
environment:
NODE_ENV: production
- persist_to_workspace:
root: ~/qlik-network-chart
paths:
- build
- dist
- store_artifacts:
path: build
destination: build
path: dist
destination: dist
deploy:
<<: *defaults
steps:

2
.gitignore vendored
View File

@@ -1,3 +1,3 @@
node_modules/
build/
dist/
BUMPED_VERSION

View File

@@ -1,24 +1,61 @@
var gulp = require('gulp');
var gutil = require('gulp-util');
var zip = require('gulp-zip');
var del = require('del');
var settings = require('./settings');
var webpackConfig = require('./webpack.config');
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var jeditor = require("gulp-json-editor");
var pkg = require('./package.json');
gulp.task('remove-build-folder', function(){
return del([settings.buildDestination], { force: true });
var DIST = './dist';
var VERSION = process.env.VERSION || 'local-dev';
gulp.task('qext', function () {
var qext = {
name: 'Network chart',
type: 'visualization',
description: pkg.description + '\nVersion: ' + VERSION,
version: VERSION,
icon: 'bubbles',
preview: 'network.png',
keywords: 'qlik-sense, visualization',
author: pkg.author,
homepage: pkg.homepage,
license: pkg.license,
repository: pkg.repository,
dependencies: {
'qlik-sense': '>=5.5.x'
}
};
if (pkg.contributors) {
qext.contributors = pkg.contributors;
}
var src = require('stream').Readable({
objectMode: true
});
src._read = function () {
this.push(new gutil.File({
cwd: '',
base: '',
path: pkg.name + '.qext',
contents: Buffer.from(JSON.stringify(qext, null, 4))
}));
this.push(null);
};
return src.pipe(gulp.dest(DIST));
});
gulp.task('clean', function(){
return del([DIST], { force: true });
});
gulp.task('zip-build', function(){
return gulp.src(settings.buildDestination + '/**/*')
.pipe(zip(`${settings.name}_${settings.version}.zip`))
.pipe(gulp.dest(settings.buildDestination));
return gulp.src(DIST + '/**/*')
.pipe(zip(`${pkg.name}_${VERSION}.zip`))
.pipe(gulp.dest(DIST));
});
gulp.task('add-assets', function(){
return gulp.src("./assets/**/*").pipe(gulp.dest(settings.buildDestination));
return gulp.src('./assets/**/*').pipe(gulp.dest(DIST));
});
gulp.task('webpack-build', done => {
@@ -37,39 +74,13 @@ gulp.task('webpack-build', done => {
});
});
gulp.task('update-qext-version', function () {
return gulp.src(`${settings.buildDestination}/${settings.name}.qext`)
.pipe(jeditor({
'version': settings.version
}))
.pipe(gulp.dest(settings.buildDestination));
});
gulp.task('build',
gulp.series('remove-build-folder', 'webpack-build', 'update-qext-version', 'add-assets', 'zip-build')
gulp.series('clean', 'webpack-build', 'qext', 'add-assets')
);
gulp.task('watch', () => new Promise((resolve, reject) => {
webpackConfig.entry.unshift('webpack-dev-server/client?http://localhost:' + settings.port);
const compiler = webpack(webpackConfig);
const originalOutputFileSystem = compiler.outputFileSystem;
const devServer = new WebpackDevServer(compiler, {
headers: {
"Access-Control-Allow-Origin": "*"
},
}).listen(settings.port, 'localhost', error => {
compiler.outputFileSystem = originalOutputFileSystem;
if (error) {
console.error(error); // eslint-disable-line no-console
return reject(error);
}
// eslint-disable-next-line no-console
console.log('Listening at localhost:' + settings.port);
resolve(null, devServer);
});
}));
gulp.task('zip',
gulp.series('build', 'zip-build')
);
gulp.task('default',
gulp.series('build')

View File

@@ -1,43 +0,0 @@
const settings = require('./settings');
module.exports = (config) => {
config.set({
browsers: ['SlimChromeHeadless'],
customLaunchers: {
SlimChromeHeadless: {
base: 'ChromeHeadless',
flags: ['--headless', '--disable-gpu', '--disable-translate', '--disable-extensions']
}
},
files: [
{ pattern: 'src/*.spec.js', watched: false }
],
frameworks: ['jasmine'],
preprocessors: {
'src/*.spec.js': ['webpack', 'sourcemap']
},
webpack: {
devtool: 'source-map',
mode: settings.mode,
externals: {
qlik: {
amd: 'qlik',
commonjs: 'qlik',
commonjs2: 'qlik',
root: '_'
}
},
module: {
rules: [
{
test: /\.js$/,
exclude: [/node_modules/],
loaders: ['babel-loader']
},
{ test: /\.less$/, loader: 'ignore-loader' },
{ test: /\.json$/, loader: 'ignore-loader' }
]
}
}
});
};

View File

@@ -1,18 +1,15 @@
{
"name": "qlik-network-chart",
"version": "0.0.1",
"description": "Network chart",
"keywords": "network chart qliksense extension",
"description": "Displays hierarchical or relational dimensions as nodes and edges´, with measures to show the significance of its links.",
"homepage": "",
"repository": "https://github.com/qlik-oss/network-vis-chart",
"author": "Michael Laenen (miclae76) <m.laenen@contactoffice.net>",
"license": "MIT",
"scripts": {
"build": "gulp build",
"eslint": "eslint src",
"eslint:fix": "eslint --fix src",
"test": "karma start karma.conf.js",
"test-once": "karma start karma.conf.js --single-run",
"watch": "gulp watch"
"build:zip": "gulp zip",
"eslint": "eslint src"
},
"devDependencies": {
"@babel/core": "7.1.5",
@@ -20,29 +17,20 @@
"@babel/preset-env": "7.1.5",
"babel-eslint": "10.0.1",
"babel-loader": "8.0.4",
"copy-webpack-plugin": "4.6.0",
"css-loader": "1.0.1",
"del": "3.0.0",
"eslint": "5.8.0",
"eslint-loader": "2.1.1",
"file-loader": "2.0.0",
"gulp": "4.0.0",
"gulp-json-editor": "2.4.3",
"gulp-util": "^3.0.7",
"gulp-zip": "4.2.0",
"jasmine-core": "3.3.0",
"karma": "3.1.1",
"karma-chrome-launcher": "2.2.0",
"karma-jasmine": "1.1.2",
"karma-sourcemap-loader": "0.3.7",
"karma-webpack": "3.0.5",
"less": "3.8.1",
"less-loader": "4.1.0",
"style-loader": "0.23.1",
"stylelint": "9.7.1",
"stylelint-webpack-plugin": "0.10.5",
"webpack": "4.25.1",
"webpack-cli": "3.1.2",
"webpack-dev-server": "3.1.10"
"webpack": "4.25.1"
},
"dependencies": {
"vis": "4.21.0"

View File

@@ -2,8 +2,8 @@
set -o errexit
echo "Creating release for version: $VERSION"
echo "Artifact name: ./build/${3}_${VERSION}.zip"
$HOME/bin/ghr -t ${ghoauth} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} ${VERSION} "./build/${3}_${4}.zip"
echo "Artifact name: ./dist/${3}_${VERSION}.zip"
$HOME/bin/ghr -t ${ghoauth} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} ${VERSION} "./dist/${3}_${4}.zip"
# Usage

25
scripts/verify-files.sh Normal file
View File

@@ -0,0 +1,25 @@
#!/bin/bash
# The build script has a known race-condition that sometimes causes it to not include all files
# in the built zip. This script verifies the that the zip contains the correct number of files.
set -o errexit
echo "Verifying built file count"
while read line; do
if [[ $line =~ ^\"name\": ]]; then
name=${line#*: \"}
name=${name%\"*}
fi
done < package.json
expected_file_count=$(($(find dist -type f | wc -l)-1))
zip_file_count=$(zipinfo dist/${name}_${VERSION}.zip | grep ^- | wc -l)
if [ "${expected_file_count}" -ne "${zip_file_count}" ]; then
# File count is incorrect
echo "Expected file count ${expected_file_count}, but was ${zip_file_count}"
exit 1
fi
echo "File count OK"
exit 0

View File

@@ -1,13 +0,0 @@
const path = require('path');
const packageJSON = require('./package.json');
const defaultBuildDestination = path.resolve("./build");
module.exports = {
buildDestination: process.env.BUILD_PATH || defaultBuildDestination,
mode: process.env.NODE_ENV || 'development',
name: packageJSON.name,
version: process.env.VERSION || 'local-dev',
url: process.env.BUILD_URL || defaultBuildDestination,
port: 8082
};

View File

@@ -5,10 +5,37 @@ Tested on Qlik Sense 2.2.3
Agilos.com takes no responsibility for any code.
Use at your own risk.
*/
import "@babel/polyfill";
if (!window._babelPolyfill) { // eslint-disable-line no-underscore-dangle
require('@babel/polyfill'); // eslint-disable-line global-require
}
import paint from './paint';
import './styles/main.less';
const dimDesc = [
"Node Identifier",
"Node Label",
"Node Parent",
"Node Group"
];
const dimLongDesc = [
"Node Identifier - a field in the dataset which should be presented as a node in the network diagram."
+ " these control the actual elements presented in the network diagram.",
"Node Label - controls what field holds the data that described the nodes in the network"
+ " diagram. The field content will be presented as label.",
"Node Parent - is used to determine the ancestor node for the individual nodes."
+ " This field will be used for describing the relationships between network elements.",
"Node Group - is a field which describes groups of a node in the network."
+ " This is used to apply the same color to several nodes."
];
const measureDesc = [
"Tooltip",
"Node size",
"Edge size"
];
const component = {
initialProperties: {
version: 1.0,
@@ -24,8 +51,11 @@ const component = {
//property panel
data: {
dimensions: {
min: 4,
max: 4
min: 3,
max: 4,
description(properties, index) {
return dimDesc[index];
}
/*
1. Dimension: Node ID, numeric (Event ID or else) or String
2. Dimension: Node Label
@@ -35,7 +65,10 @@ const component = {
},
measures: {
min: 0,
max: 3
max: 3,
description(properties, index) {
return measureDesc[index];
}
/*
1. Measure: title text for tooltip (optional)
2. Measure: node value
@@ -51,7 +84,22 @@ const component = {
uses: "data",
items:{
dimensions:{
disabledRef: ""
disabledRef: "",
items: {
helpDesc: {
component: 'text',
style: 'qlik-network-chart-italic-property',
label: function(properties, handler) {
var index;
handler.getDimensions().forEach((element, i) => {
if(element.qDef.cId === properties.qDef.cId) {
index = i;
}
});
return dimLongDesc[index];
}
}
}
},
measures: {
disabledRef: ""

View File

@@ -3,184 +3,215 @@ import qlik from 'qlik';
import { createTooltipHTML } from './tooltip';
import { escapeHTML } from './utilities';
const colorScheme = 'Diverging Classes';
function isTextCellNotEmpty(c) {
return (c.qText && !(c.qIsNull || c.qText.trim() == ''));
}
function getColor (index, colors) {
return colors[index % colors.length];
}
function paint ( $element, layout, qTheme, component ) {
const colorScale = qTheme.properties.scales
.find(scale => scale.name === colorScheme).scale;
const colors = colorScale[colorScale.length - 1];
function getColor (number) {
return colors[number % colors.length];
}
return new qlik.Promise(function(resolve) {
var qData = layout.qHyperCube.qDataPages[0],
id = layout.qInfo.qId,
containerId = 'network-container_' + id;
const colorScale = qTheme.properties.palettes.data[0];
const numDimensions = layout.qHyperCube.qDimensionInfo.length;
const numMeasures = layout.qHyperCube.qMeasureInfo.length;
if(qData && qData.qMatrix) {
$element.empty().append($('<div />')
.attr({ id: containerId })
.toggleClass('is-edit-mode', component.inEditState())
.css({
height: $element.height(),
width: $element.width(),
overflow: 'auto'
}));
var qData = layout.qHyperCube.qDataPages[0],
id = layout.qInfo.qId,
containerId = 'network-container_' + id;
var dataSet = qData.qMatrix.map(function(e){
const nodeName = e[1].qText;
const groupNumber = e[3].qText;
if(qData && qData.qMatrix) {
$element.empty().append($('<div />')
.attr({ id: containerId })
.toggleClass('is-edit-mode', component.inEditState())
.css({
height: $element.height(),
width: $element.width(),
overflow: 'auto'
}));
const dataItem = {
id: e[0].qNum,
label: nodeName,
group: groupNumber,
parentid : e[2].qNum
var dataSet = qData.qMatrix.map(function(e){
const nodeName = e[1].qText;
let groupNumber;
const dataItem = {
id: e[0].qText,
eNum: e[0].qElemNumber,
label: nodeName,
parentid : e[2].qText
};
if(numDimensions === 4) {
groupNumber = e[3].qText;
dataItem.group = groupNumber;
}
// optional measures set
if (numMeasures > 0) {
const tooltip = e[numDimensions];
if (isTextCellNotEmpty(tooltip)) {
const tooltipText = tooltip.qText;
dataItem.title = escapeHTML(tooltipText);
} else if(numMeasures > 1) {
// This part is a bit fishy and should be tested
const nodeMeasure = e[numDimensions+1].qText;
dataItem.title = createTooltipHTML({
name: nodeName,
groupNumber,
nodeMeasure
});
}
}
if (numMeasures > 1) {
if (e[numDimensions+1].qNum) {
// node value - to scale node shape size
dataItem.nodeValue = e[5].qNum;
}
}
if (numMeasures > 2) {
if (e[numDimensions+2].qNum) {
// edge value - to scale edge width
dataItem.edgeValue = e[numDimensions+2].qNum;
}
}
return dataItem;
});
// Require 2 arrays : nodes and edges - nodes array must be unique values of IDs !
var uniqueId = [];
var nodes = [];
var edges = [];
const groups = {};
for(let i = 0; i< dataSet.length; i++){
if (layout.displayEdgeLabel && dataSet[i].edgeValue !== undefined) {
edges.push({
"from":dataSet[i].id,
"to":dataSet[i].parentid,
"value":dataSet[i].edgeValue,
"label": `${dataSet[i].edgeValue}`
}); // with labels
} else {
edges.push({
"from":dataSet[i].id,
"to":dataSet[i].parentid,
"value":dataSet[i].edgeValue
}); // create edges
}
// process uniqueness
if(uniqueId.indexOf(dataSet[i].id) === -1) {
uniqueId.push(dataSet[i].id);
var nodeItem = {
id: dataSet[i].id,
eNum: dataSet[i].eNum,
label: dataSet[i].label,
title: dataSet[i].title,
group: dataSet[i].group,
value: dataSet[i].nodeValue
};
nodes.push(nodeItem); // create node
groups[nodeItem.group] = {};
}
}
const colors = colorScale.scale[Math.min(Object.keys(groups).length-1, colorScale.scale.length-1)];
Object.keys(groups).forEach(function(g,i) {
groups[g].color = getColor(i, colors);
});
// create dataset for \\
var data = {
nodes: nodes,
edges: edges
};
// optional measures set
if (e.length > 4) {
const tooltip = e[4];
// create a network
var container = document.getElementById(containerId);
if (isTextCellNotEmpty(tooltip)) {
const tooltipText = tooltip.qText;
dataItem.title = escapeHTML(tooltipText);
} else {
const nodeMeasure = e[5].qText;
dataItem.title = createTooltipHTML({
name: nodeName,
groupNumber,
nodeMeasure
});
var options = {
groups: groups,
layout: {
randomSeed: 1
},
nodes: {
shape:layout.nodeShape,
shadow:layout.shadowMode
},
edges: {
shadow:layout.shadowMode,
font: {
align: layout.posEdgeLabel
},
smooth: {
type: layout.edgeType
}
},
interaction: {
hideEdgesOnDrag: true,
tooltipDelay: 100
},
physics: {
forceAtlas2Based: {
gravitationalConstant: -100,
centralGravity: 0.005,
springLength: 230,
springConstant: 0.18
},
maxVelocity: 146,
solver: 'forceAtlas2Based',
timestep: 0.35,
stabilization: { iterations: 150 }
}
}
};
var network = new Network(container, data, options);
network.fit();
if (e.length > 5) {
if (e[5].qNum) {
// node value - to scale node shape size
dataItem.nodeValue = e[5].qNum;
// Handle Selection on 1-node
$("#"+containerId).css('cursor','default');
network.on('select', function (properties) {
if (properties.hasOwnProperty("nodes")) {
if (properties.nodes.length > 0) {
// find connected nodes to selection
var connectedNodes = network.getConnectedNodes(properties.nodes[0]);
// append node to the array
connectedNodes.push(properties.nodes[0]);
const toSelect = [];
connectedNodes.forEach(function(node) {
var id;
data.nodes.forEach(function(dataNode) {
// Find match, ignore null
if(dataNode.id === node && node !== "-") {
id = dataNode.eNum;
}
});
if(id !== undefined) {
// Remove duplicates
toSelect.indexOf(id) === -1 && toSelect.push(id);
}
});
//Make the selections
component.backendApi.selectValues(0,toSelect,false);
}
}
}
});
if (e.length > 6) {
if (e[6].qNum) {
// edge value - to scale edge width
dataItem.edgeValue = e[6].qNum;
}
}
return dataItem;
});
// Require 2 arrays : nodes and edges - nodes array must be unique values of IDs !
var uniqueId = [];
var nodes = [];
var edges = [];
const groups = {};
for(let i = 0; i< dataSet.length; i++){
if (layout.displayEdgeLabel) {
edges.push({
"from":dataSet[i].id,
"to":dataSet[i].parentid,
"value":dataSet[i].edgeValue,
"label": `${dataSet[i].edgeValue}`
}); // with labels
} else {
edges.push({
"from":dataSet[i].id,
"to":dataSet[i].parentid,
"value":dataSet[i].edgeValue
}); // create edges
}
// process uniqueness
if(uniqueId.indexOf(dataSet[i].id) === -1) {
uniqueId.push(dataSet[i].id);
var nodeItem = {
id: dataSet[i].id,
label: dataSet[i].label,
title: dataSet[i].title,
group: dataSet[i].group,
value: dataSet[i].nodeValue
};
nodes.push(nodeItem); // create node
groups[nodeItem.group] = {
color: getColor(nodeItem.group)
};
}
network.on('stabilizationIterationsDone', function() {
resolve();
});
} else {
resolve();
}
// create dataset for \\
var data = {
nodes: nodes,
edges: edges
};
// create a network
var container = document.getElementById(containerId);
var options = {
groups: groups,
layout: {
randomSeed: 1
},
nodes: {
shape:layout.nodeShape,
shadow:layout.shadowMode
},
edges: {
shadow:layout.shadowMode,
font: {
align: layout.posEdgeLabel
},
smooth: {
type: layout.edgeType
}
},
interaction: {
hideEdgesOnDrag: true,
tooltipDelay: 100
},
physics: {
forceAtlas2Based: {
gravitationalConstant: -100,
centralGravity: 0.005,
springLength: 230,
springConstant: 0.18
},
maxVelocity: 146,
solver: 'forceAtlas2Based',
timestep: 0.35,
stabilization: { iterations: 150 }
}
};
var network = new Network(container, data, options);
network.fit();
// Handle Selection on 1-node
$("#"+containerId).css('cursor','default');
network.on('select', function (properties) {
if (properties.hasOwnProperty("nodes")) {
if (properties.nodes.length > 0) {
// find connected nodes to selection
var connectedNodes = network.getConnectedNodes(properties.nodes[0]);
// append node to the array
connectedNodes.push(properties.nodes[0]);
//Make the selections
component.backendApi.selectValues(0,connectedNodes,false);
}
}
});
}
});
}
function themePaint ($element, layout) {
@@ -188,8 +219,8 @@ function themePaint ($element, layout) {
try {
const app = qlik.currApp(this);
app.theme.getApplied().then( function( qTheme ) {
paint($element, layout, qTheme, component);
return app.theme.getApplied().then( function( qTheme ) {
return paint($element, layout, qTheme, component);
});
} catch (exception) {
console.error(exception); // eslint-disable-line no-console

View File

@@ -1,7 +0,0 @@
import paint from './paint';
describe('paint', () => {
it('should be defined', () => {
expect(paint).toBeDefined();
});
});

View File

@@ -1,16 +0,0 @@
{
"name" : "Network chart",
"description" : "Displays hierarchical or relational dimensions as nodes and edges´, with measures to show the significance of its links.",
"icon" : "bubbles",
"type" : "visualization",
"version": "X.Y.Z",
"preview" : "network.png",
"keywords": "qlik-sense, visualization",
"author": "Michael Laenen <michael.laenen@agilos.com>",
"homepage": "",
"license": "MIT",
"repository": "",
"dependencies": {
"qlik-sense": ">=5.5.x"
}
}

View File

@@ -11,3 +11,7 @@
padding: 10px;
max-width: 200px;
}
.qlik-network-chart-italic-property {
font-style: italic;
}

View File

@@ -1,20 +1,23 @@
const CopyWebpackPlugin = require('copy-webpack-plugin');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const settings = require('./settings');
const packageJSON = require('./package.json');
const path = require('path');
const webpack = require('webpack');
console.log('Webpack mode:', settings.mode); // eslint-disable-line no-console
const DIST = path.resolve("./dist");
const MODE = process.env.NODE_ENV || 'development';
console.log('Webpack mode:', MODE); // eslint-disable-line no-console
const config = {
devtool: 'source-map',
entry: [
'./src/index.js'
],
mode: settings.mode,
mode: MODE,
output: {
path: settings.buildDestination,
filename: settings.name + '.js',
libraryTarget: 'umd'
filename: `${packageJSON.name}.js`,
libraryTarget: 'amd',
path: DIST
},
externals: {
qlik: {
@@ -71,9 +74,6 @@ const config = {
]
},
plugins: [
new CopyWebpackPlugin([
'src/' + settings.name + '.qext'
], {}),
new StyleLintPlugin(),
new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/en$/),
]