diff --git a/bower.json b/bower.json index e3362e29..aff48516 100644 --- a/bower.json +++ b/bower.json @@ -2,10 +2,7 @@ "name": "redash", "version": "0.11.0", "dependencies": { - "pivottable": "2.0.2", "pace": "~0.5.1", "canvg": "gabelerner/canvg", - "leaflet": "~0.7.3", - "leaflet.markercluster": "^0.5.0" }, } diff --git a/frontend/app/visualizations/index.js b/frontend/app/visualizations/index.js index 554a3efb..3301760c 100644 --- a/frontend/app/visualizations/index.js +++ b/frontend/app/visualizations/index.js @@ -13,6 +13,7 @@ import wordCloudVisualization from './word-cloud'; import boxPlotVisualization from './box-plot'; import cohortVisualization from './cohort'; import mapVisualization from './map'; +import pivotVisualization from './pivot'; function VisualizationProvider() { this.visualizations = {}; @@ -168,5 +169,6 @@ export default function (ngModule) { boxPlotVisualization(ngModule); cohortVisualization(ngModule); mapVisualization(ngModule); + pivotVisualization(ngModule); tableVisualization(ngModule); } diff --git a/frontend/app/visualizations/pivot/index.js b/frontend/app/visualizations/pivot/index.js new file mode 100644 index 00000000..e723e4d0 --- /dev/null +++ b/frontend/app/visualizations/pivot/index.js @@ -0,0 +1,68 @@ +import $ from 'jquery'; +import 'pivottable'; +import 'pivottable/dist/pivot.css'; + +function pivotTableRenderer() { + return { + restrict: 'E', + scope: { + queryResult: '=', + visualization: '=', + }, + template: '', + replace: false, + link($scope, element) { + $scope.$watch('queryResult && queryResult.getData()', (data) => { + if (!data) { + return; + } + + if ($scope.queryResult.getData() !== null) { + // We need to give the pivot table its own copy of the data, because it changes + // it which interferes with other visualizations. + data = $.extend(true, [], $scope.queryResult.getRawData()); + const options = { + renderers: $.pivotUtilities.renderers, + onRefresh(config) { + const configCopy = Object.assign({}, config); + // delete some values which are functions + delete configCopy.aggregators; + delete configCopy.renderers; + delete configCopy.onRefresh; + // delete some bulky default values + delete configCopy.rendererOptions; + delete configCopy.localeStrings; + + if ($scope.visualization) { + $scope.visualization.options = configCopy; + } + }, + }; + + if ($scope.visualization) { + Object.assign(options, $scope.visualization.options); + } + $(element).pivotUI(data, options, true); + } + }); + }, + }; +} + +export default function (ngModule) { + ngModule.directive('pivotTableRenderer', pivotTableRenderer); + + ngModule.config((VisualizationProvider) => { + const editTemplate = '
'; + const defaultOptions = { + }; + + VisualizationProvider.registerVisualization({ + type: 'PIVOT', + name: 'Pivot Table', + renderTemplate: '', + editorTemplate: editTemplate, + defaultOptions, + }); + }); +} diff --git a/frontend/package.json b/frontend/package.json index 0ce9c1aa..82755726 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -58,6 +58,7 @@ "ng-annotate": "^1.2.1", "ng-annotate-loader": "^0.2.0", "ng-table": "^2.1.0", + "pivottable": "^2.3.0", "plotly.js": "^1.16.0", "raw-loader": "^0.5.1", "ui-select": "^0.19.6", diff --git a/rd_ui/app/app_layout.html b/rd_ui/app/app_layout.html index 72bbb463..12f26ec3 100644 --- a/rd_ui/app/app_layout.html +++ b/rd_ui/app/app_layout.html @@ -10,7 +10,6 @@ - @@ -55,8 +54,6 @@ {% include 'vendor_scripts.html' %} - - @@ -71,23 +68,6 @@ - - - - - - - - - - - - - - - - -