gridstack: optimizations and bugfixes

This commit is contained in:
Levko Kravets
2018-03-22 17:23:49 +02:00
parent ce9e3fcb35
commit 2fbf8926c4
13 changed files with 407 additions and 84 deletions

View File

@@ -1,29 +0,0 @@
.gridster .preview-holder {
border: none !important;
border-radius: 0 !important;
background: rgba(0, 0, 0, 0.5) !important;
}
.gridster li .heading {
border: #ddd;
background-color: #f5f5f5;
padding: 5px;
}
li.widget {
/*background-color:grey;*/
border-width: 1px;
border-style: solid;
border-color: grey;
opacity: 0.7;
cursor: move;
&:hover {
opacity: 1.0 !important;
-webkit-transition: opacity .6s;
-moz-transition: opacity .6s;
-o-transition: opacity .6s;
-ms-transition: opacity .6s;
transition: opacity .6s;
}
}

View File

@@ -9,7 +9,6 @@
@import '~ui-select/dist/select.css';
@import '~angular-toastr/src/toastr';
@import '~angular-resizable/src/angular-resizable.css';
@import '~angular-gridster/src/angular-gridster';
@import '~pace-progress/themes/blue/pace-theme-minimal.css';
@import '~material-design-iconic-font/dist/css/material-design-iconic-font.css';
@@ -51,7 +50,6 @@
@import 'inc/navbar';
@import 'inc/edit-in-place';
@import 'inc/growl';
@import 'inc/gridster';
@import 'inc/flex';
@import 'inc/ace-editor';
@import 'inc/overlay';

View File

@@ -5,9 +5,6 @@ import 'jquery-ui/ui/widgets/droppable';
import 'jquery-ui/ui/widgets/resizable';
import 'gridstack/dist/gridstack.css';
window.$ = window.jQuery = $;
window._ = _;
// eslint-disable-next-line import/first
import gridstack from 'gridstack';

View File

@@ -59,13 +59,14 @@ function computeAutoHeight($element, grid, node, minHeight, maxHeight) {
return Math.min(Math.max(minHeight, resultHeight), maxHeight);
}
function gridstack() {
function gridstack($parse, dashboardGridOptions) {
return {
restrict: 'A',
replace: false,
scope: {
editing: '=',
batchUpdate: '=', // set by directive - for using in wrapper components
isOneColumnMode: '=',
},
controller() {
this.$el = null;
@@ -205,16 +206,22 @@ function gridstack() {
};
},
link: ($scope, $element, $attr, controller) => {
const batchUpdateAssignable = _.isFunction($parse($attr.batchUpdate).assign);
const isOneColumnModeAssignable = _.isFunction($parse($attr.batchUpdate).assign);
let enablePolling = true;
$element.addClass('grid-stack');
$element.gridstack({
auto: false,
verticalMargin: 15,
cellHeight: 35, // real row height will be `cellHeight` + `verticalMargin`
width: 6, // columns
verticalMargin: dashboardGridOptions.margins,
// real row height will be `cellHeight` + `verticalMargin`
cellHeight: dashboardGridOptions.rowHeight - dashboardGridOptions.margins,
width: dashboardGridOptions.columns, // columns
height: 0, // max rows (0 for unlimited)
animate: true,
float: false,
minWidth: 800,
minWidth: dashboardGridOptions.mobileBreakPoint,
resizable: {
handles: 'e, se, s, sw, w',
start: (event, ui) => {
@@ -253,25 +260,56 @@ function gridstack() {
});
controller.$el = $element;
$element.on('change', (event, nodes) => {
nodes = _.isArray(nodes) ? nodes : [];
console.log('+', nodes.length);
_.each(nodes, (node) => {
// `change` events sometimes fire too frequently (for example,
// on initial rendering when all widgets add themselves to grid, grid
// will fire `change` event will _all_ items available at that moment).
// Collect changed items, and then delegate event with some delay
let changedNodes = {};
const triggerChange = _.debounce(() => {
_.each(changedNodes, (node) => {
if (node.el) {
$(node.el).trigger('gridstack.changed', node);
}
});
changedNodes = {};
});
$element.on('change', (event, nodes) => {
nodes = _.isArray(nodes) ? nodes : [];
_.each(nodes, (node) => {
changedNodes[node.id] = node;
});
triggerChange();
});
$scope.$watch('editing', (value) => {
controller.setEditing(!!value);
});
$scope.batchUpdate = controller.batchUpdateWidgets;
if (batchUpdateAssignable) {
$scope.batchUpdate = controller.batchUpdateWidgets;
}
$scope.$on('$destroy', () => {
enablePolling = false;
controller.$el = null;
});
function updateOneColumnMode() {
const grid = controller.grid();
if (grid) {
$scope.isOneColumnMode = $element.hasClass(grid.opts.oneColumnModeClass);
$scope.$applyAsync();
}
if (enablePolling) {
setTimeout(updateOneColumnMode, 150);
}
}
if (isOneColumnModeAssignable) {
updateOneColumnMode();
}
},
};
}

View File

@@ -1,33 +1,15 @@
const dashboardGridOptions = {
columns: 6,
pushing: true,
floating: true,
swapping: false,
width: 'auto',
colWidth: 'auto',
rowHeight: 50,
margins: [15, 15],
outerMargin: false,
sparse: false,
isMobile: false,
columns: 6, // grid columns count
rowHeight: 50, // grid row height (incl. bottom padding)
margins: 15, // widget margins
mobileBreakPoint: 800,
mobileModeEnabled: true,
minColumns: 6,
minRows: 1,
maxRows: 1000,
// defaults for widgets
defaultSizeX: 3,
defaultSizeY: 3,
minSizeX: 1,
maxSizeX: 6,
minSizeY: 1,
maxSizeY: 1000,
resizable: {
enabled: false,
handles: ['n', 'e', 's', 'w', 'ne', 'se', 'sw', 'nw'],
},
draggable: {
enabled: false,
},
};
export default function init(ngModule) {

View File

@@ -17,7 +17,6 @@ import 'angular-moment';
import 'brace';
import 'angular-ui-ace';
import 'angular-resizable';
import ngGridster from 'angular-gridster';
import { each, isFunction } from 'underscore';
import '@/lib/sortable';
@@ -52,7 +51,6 @@ const requirements = [
'angularResizable',
vsRepeat,
'ui.sortable',
ngGridster.name,
];
const ngModule = angular.module('app', requirements);

View File

@@ -3,7 +3,6 @@ import 'font-awesome/css/font-awesome.css';
import 'ui-select/dist/select.css';
import 'angular-toastr/dist/angular-toastr.css';
import 'angular-resizable/src/angular-resizable.css';
import 'angular-gridster/dist/angular-gridster.css';
import 'pace-progress/themes/blue/pace-theme-minimal.css';
import '@/assets/css/superflat_redash.css';

View File

@@ -85,7 +85,8 @@
</div>
<div style="padding-bottom: 5px;" ng-if="$ctrl.dashboard.widgets.length > 0">
<div gridstack editing="$ctrl.layoutEditing && !$ctrl.saveInProgress" batch-update="$ctrl.updateGridItems" class="dashboard-wrapper"
<div gridstack editing="$ctrl.layoutEditing && !$ctrl.saveInProgress" batch-update="$ctrl.updateGridItems"
is-one-column-mode="$ctrl.isGridDisabled" class="dashboard-wrapper"
ng-class="{'preview-mode': !$ctrl.layoutEditing, 'editing-mode': $ctrl.layoutEditing}">
<div class="dashboard-widget-wrapper"
ng-repeat="widget in $ctrl.dashboard.widgets track by widget.id"

View File

@@ -304,8 +304,7 @@ function DashboardCtrl(
this.removeWidget = () => {
this.extractGlobalParameters();
if (!this.layoutEditing) {
// We need to wait a bit for `angular-gridster` before it updates widgets,
// and only then save new layout
// We need to wait a bit while `angular` updates widgets, and only then save new layout
$timeout(() => {
const changedWidgets = getWidgetsWithChangedPositions(this.dashboard.widgets);
saveDashboardLayout(changedWidgets);

View File

@@ -6,10 +6,14 @@
<filters ng-if="$ctrl.dashboard.dashboard_filters_enabled"></filters>
</div>
<div style="padding-bottom: 5px">
<div gridster="$ctrl.dashboardGridOptions" class="dashboard-wrapper">
<div ng-repeat="widget in $ctrl.dashboard.widgets" gridster-item="widget.options.position" gridster-auto-height>
<dashboard-widget widget="widget" dashboard="$ctrl.dashboard" public="true"></dashboard-widget>
<div style="padding-bottom: 5px" ng-if="$ctrl.dashboard.widgets.length > 0">
<div gridstack editing="false" class="dashboard-wrapper preview-mode">
<div class="dashboard-widget-wrapper"
ng-repeat="widget in $ctrl.dashboard.widgets"
gridstack-item="widget.options.position" gridstack-item-id="{{ widget.id }}">
<div class="grid-stack-item-content">
<dashboard-widget widget="widget" dashboard="$ctrl.dashboard" public="true"></dashboard-widget>
</div>
</div>
</div>
</div>

339
package-lock.json generated
View File

@@ -192,11 +192,6 @@
"resolved": "https://registry.npmjs.org/angular-base64-upload/-/angular-base64-upload-0.1.23.tgz",
"integrity": "sha512-vRSY+7/pag2hEdTSB90LTvT5rU5XPxBNMA1WGz60pNSpChRUzf+h5FR9lObRcGg1WUOvlYinnvoPTD6Nktcx1g=="
},
"angular-gridster": {
"version": "0.13.14",
"resolved": "https://registry.npmjs.org/angular-gridster/-/angular-gridster-0.13.14.tgz",
"integrity": "sha1-er6/Y9fJ++xFOLnMpFfg2oBdQgQ="
},
"angular-messages": {
"version": "1.5.11",
"resolved": "https://registry.npmjs.org/angular-messages/-/angular-messages-1.5.11.tgz",
@@ -447,6 +442,12 @@
"integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
"dev": true
},
"async-limiter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
"integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
"dev": true
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -1374,6 +1375,25 @@
"tweetnacl": "0.14.5"
}
},
"bfj-node4": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/bfj-node4/-/bfj-node4-5.3.1.tgz",
"integrity": "sha512-SOmOsowQWfXc7ybFARsK3C4MCOWzERaOMV/Fl3Tgjs+5dJWyzo3oa127jL44eMbQiAN17J7SvAs2TRxEScTUmg==",
"dev": true,
"requires": {
"bluebird": "3.5.1",
"check-types": "7.3.0",
"tryer": "1.0.0"
},
"dependencies": {
"bluebird": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==",
"dev": true
}
}
},
"big-rat": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/big-rat/-/big-rat-1.0.4.tgz",
@@ -1929,6 +1949,12 @@
"strip-ansi": "0.1.1"
}
},
"check-types": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/check-types/-/check-types-7.3.0.tgz",
"integrity": "sha1-Ro9XGkQ1wkJI9f0MsOjYfDw0Hn0=",
"dev": true
},
"chokidar": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
@@ -3148,6 +3174,12 @@
"resolved": "https://registry.npmjs.org/dup/-/dup-1.0.0.tgz",
"integrity": "sha1-UfxaxoX4GWRp3wuQXpNLIK9bQCk="
},
"duplexer": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
"dev": true
},
"duplexer2": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz",
@@ -3237,6 +3269,12 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
"dev": true
},
"ejs": {
"version": "2.5.7",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz",
"integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=",
"dev": true
},
"electron-to-chromium": {
"version": "1.3.24",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.24.tgz",
@@ -4170,6 +4208,12 @@
"integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
"dev": true
},
"filesize": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.0.tgz",
"integrity": "sha512-g5OWtoZWcPI56js1DFhIEqyG9tnu/7sG3foHwgS9KGYFMfsYguI3E+PRVCmtmE96VajQIEMRU2OhN+ME589Gdw==",
"dev": true
},
"fill-range": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
@@ -6833,6 +6877,24 @@
"integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=",
"dev": true
},
"gzip-size": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-4.1.0.tgz",
"integrity": "sha1-iuCWJX6r59acRb4rZ8RIEk/7UXw=",
"dev": true,
"requires": {
"duplexer": "0.1.1",
"pify": "3.0.0"
},
"dependencies": {
"pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
"dev": true
}
}
},
"handle-thing": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz",
@@ -9581,6 +9643,12 @@
"mimic-fn": "1.1.0"
}
},
"opener": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz",
"integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=",
"dev": true
},
"opn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz",
@@ -12702,6 +12770,12 @@
"integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
"dev": true
},
"tryer": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.0.tgz",
"integrity": "sha1-Antp+oIyJeVRys4+8DsR9qs3wdc=",
"dev": true
},
"tryit": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz",
@@ -13352,6 +13426,251 @@
}
}
},
"webpack-bundle-analyzer": {
"version": "2.11.1",
"resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-2.11.1.tgz",
"integrity": "sha512-VKUVkVMc6TWVXmF1OxsBXoiRjYiDRA4XT0KqtbLMDK+891VX7FCuklYwzldND8J2upUcHHnuXYNTP+4mSFi4Kg==",
"dev": true,
"requires": {
"acorn": "5.5.3",
"bfj-node4": "5.3.1",
"chalk": "2.3.2",
"commander": "2.15.1",
"ejs": "2.5.7",
"express": "4.16.3",
"filesize": "3.6.0",
"gzip-size": "4.1.0",
"lodash": "4.17.4",
"mkdirp": "0.5.1",
"opener": "1.4.3",
"ws": "4.1.0"
},
"dependencies": {
"accepts": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
"integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
"dev": true,
"requires": {
"mime-types": "2.1.18",
"negotiator": "0.6.1"
}
},
"acorn": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz",
"integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==",
"dev": true
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "1.9.0"
}
},
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
"dev": true
},
"chalk": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz",
"integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==",
"dev": true,
"requires": {
"ansi-styles": "3.2.1",
"escape-string-regexp": "1.0.5",
"supports-color": "5.3.0"
}
},
"commander": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
"dev": true
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"requires": {
"ms": "2.0.0"
}
},
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
"dev": true
},
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
"dev": true
},
"express": {
"version": "4.16.3",
"resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz",
"integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=",
"dev": true,
"requires": {
"accepts": "1.3.5",
"array-flatten": "1.1.1",
"body-parser": "1.18.2",
"content-disposition": "0.5.2",
"content-type": "1.0.4",
"cookie": "0.3.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "1.1.2",
"encodeurl": "1.0.2",
"escape-html": "1.0.3",
"etag": "1.8.1",
"finalhandler": "1.1.1",
"fresh": "0.5.2",
"merge-descriptors": "1.0.1",
"methods": "1.1.2",
"on-finished": "2.3.0",
"parseurl": "1.3.2",
"path-to-regexp": "0.1.7",
"proxy-addr": "2.0.3",
"qs": "6.5.1",
"range-parser": "1.2.0",
"safe-buffer": "5.1.1",
"send": "0.16.2",
"serve-static": "1.13.2",
"setprototypeof": "1.1.0",
"statuses": "1.4.0",
"type-is": "1.6.16",
"utils-merge": "1.0.1",
"vary": "1.1.2"
}
},
"finalhandler": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
"dev": true,
"requires": {
"debug": "2.6.9",
"encodeurl": "1.0.2",
"escape-html": "1.0.3",
"on-finished": "2.3.0",
"parseurl": "1.3.2",
"statuses": "1.4.0",
"unpipe": "1.0.0"
}
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"ipaddr.js": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz",
"integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=",
"dev": true
},
"mime": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
"integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==",
"dev": true
},
"mime-db": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz",
"integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==",
"dev": true
},
"mime-types": {
"version": "2.1.18",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz",
"integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==",
"dev": true,
"requires": {
"mime-db": "1.33.0"
}
},
"proxy-addr": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz",
"integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==",
"dev": true,
"requires": {
"forwarded": "0.1.2",
"ipaddr.js": "1.6.0"
}
},
"send": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
"integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
"dev": true,
"requires": {
"debug": "2.6.9",
"depd": "1.1.2",
"destroy": "1.0.4",
"encodeurl": "1.0.2",
"escape-html": "1.0.3",
"etag": "1.8.1",
"fresh": "0.5.2",
"http-errors": "1.6.2",
"mime": "1.4.1",
"ms": "2.0.0",
"on-finished": "2.3.0",
"range-parser": "1.2.0",
"statuses": "1.4.0"
}
},
"serve-static": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
"integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
"dev": true,
"requires": {
"encodeurl": "1.0.2",
"escape-html": "1.0.3",
"parseurl": "1.3.2",
"send": "0.16.2"
}
},
"statuses": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==",
"dev": true
},
"supports-color": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz",
"integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==",
"dev": true,
"requires": {
"has-flag": "3.0.0"
}
},
"type-is": {
"version": "1.6.16",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
"integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
"dev": true,
"requires": {
"media-typer": "0.3.0",
"mime-types": "2.1.18"
}
}
}
},
"webpack-dev-middleware": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.0.tgz",
@@ -13773,6 +14092,16 @@
"mkdirp": "0.5.1"
}
},
"ws": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz",
"integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==",
"dev": true,
"requires": {
"async-limiter": "1.0.0",
"safe-buffer": "5.1.1"
}
},
"xml-char-classes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/xml-char-classes/-/xml-char-classes-1.0.0.tgz",

View File

@@ -6,8 +6,10 @@
"scripts": {
"start": "webpack-dev-server",
"dev": "REDASH_BACKEND=https://dev.redashapp.com npm start",
"build": "rm -rf ./client/dist/ && NODE_ENV=production node node_modules/.bin/webpack",
"watch": "webpack --watch --progress --colors -d"
"build": "rm -rf ./client/dist/ && NODE_ENV=production webpack",
"watch": "webpack --watch --progress --colors -d",
"analyze": "rm -rf ./client/dist/ && BUNDLE_ANALYZER=on webpack",
"analyze:build": "rm -rf ./client/dist/ && NODE_ENV=production BUNDLE_ANALYZER=on webpack"
},
"repository": {
"type": "git",
@@ -26,7 +28,6 @@
"dependencies": {
"angular": "~1.5.8",
"angular-base64-upload": "^0.1.23",
"angular-gridster": "^0.13.14",
"angular-messages": "~1.5.8",
"angular-moment": "^1.1.0",
"angular-resizable": "^1.2.0",
@@ -89,6 +90,7 @@
"url-loader": "^0.5.9",
"webpack": "^3.6.0",
"webpack-build-notifier": "^0.1.16",
"webpack-bundle-analyzer": "^2.11.1",
"webpack-dev-server": "^2.9.1",
"webpack-manifest-plugin": "^1.3.2"
}

View File

@@ -8,6 +8,7 @@ const WebpackBuildNotifierPlugin = require('webpack-build-notifier');
const ManifestPlugin = require('webpack-manifest-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const LessPluginAutoPrefix = require('less-plugin-autoprefix');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const path = require('path');
const redashBackend = process.env.REDASH_BACKEND || 'http://localhost:5000';
@@ -204,4 +205,8 @@ if (process.env.NODE_ENV === 'production') {
config.devtool = 'source-map';
}
if (process.env.BUNDLE_ANALYZER) {
config.plugins.push(new BundleAnalyzerPlugin());
}
module.exports = config;